第4週 課題の学び:業務効率化ツール作成|受注管理
AIを使って業務効率化するプロジェクト始動!
このkeitaroさん率いる「けいたろ軍団」のプロジェクトでは
毎週 課題提出&フィードバックを繰り返し「2ヶ月後にAIを使って業務効率化できるようになること」を目指しています。
【挑戦】
さとふる受注管理をGASで自動化!
コードと運用フローを大公開
前回の「挑戦編」では、「こういうフローを作りたい!」というイメージを描きました。
今回は、実際に構築したコード例やシート設定を具体的に紹介します。
1. 必要なもの
Google ドライブ
CSV保管用のフォルダを準備(例:フォルダ名「さとふるCSV」)
スプレッドシート
寄附受付番号やステータスなどのカラムを用意
Slack (Incoming Webhook URL)
チームのSlackに通知するためのURLを発行
2. スプレッドシートのヘッダ例
下記のような見出しを想定します。シート名は「出荷リスト」です。
これはさとふるから取得できるcsvデータに基づいた並びにしています。
※寄附受付番号がC列、である点に注目
※U列の出荷月はさとふるのcsvにはないので、「I:集荷予定日」を計算式で変換(これは月別の売り上げ集計用に欲しかったので追加しました。)
列:ヘッダインデックス
A:ステータス
B:配送情報番号
C:寄附受付番号
D:送り状No.
E:お礼品ID
F:お礼品名
G:伝票表示名
H:発注日
I:集荷予定日
J:集荷実績日
K:提供価格(税込)
L:提供価格(税込)※予定
M:提供価格(税抜)
N:課税対象外
O:税区分
P:税率
Q:配送先郵便番号
R:配送先都道府県
S:配送先市区町村
T:配送先町名
U:出荷月:=TEXT(I2:I,"YYYYMM")
3. コード例
GASは例の如く、AIに書いてもらいます。
今回は以下のプロンプトで実行してみたところうまくいきました!
”指定したGoogleフォルダにさとふるの受注csvを保存したら、指定した納品管理スプレットシートに行を追加。スプレッドシートでは当日の行を薄い赤で塗りつぶしの条件書式を設定し当日発送分を視覚的に一目でわかるようにする。タイムトリガーで毎日9時に本日の発送数量、明日の発送数量と納品管理スプレットシートのリンクをslackに通知。発送担当者はリンクから納品管理スプレットシートを開き、本日発送分の商品内容、数量を確認して梱包。リストと発送を確認し、集荷が完了したものはステータスを手動でチェック。ステータスが発送完了になっているのはグレーアウトするように条件書式を設定。受注管理者はさとふるから注文のメールが来たらcsvを保存するだけで、一連の作業フローを自動化できるようにGASを使って実現したいです。”
参考までに、実際に組んでみたコードも置いておきますね!
FOLDER_ID
SlackのIncoming Webhook URL
を書き換えれば実行できると思います。
うまく実行できない時はこのコードをAIに投げてみて、修正してくださいと聞いてみてください!
function importCSVAndSendReminder() {
try {
var folder = DriveApp.getFolderById('FOLDER_ID'); // フォルダIDを指定
var files = folder.getFiles();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('出荷リスト');
// 既存のデータをクリア(必要に応じて)
// sheet.clear(); // すべてのデータをクリアする場合はこの行をコメントアウト解除
while (files.hasNext()) {
var file = files.next();
var csvData = Utilities.parseCsv(file.getBlob().getDataAsString('Shift_JIS')); // Shift_JISとして読み込む
var existingData = sheet.getDataRange().getValues();
var existingIds = existingData.map(function(row) { return row[2]; }); // 寄附受付番号の列を取得
for (var i = 1; i < csvData.length; i++) { // ヘッダーをスキップ
var row = csvData[i];
var newId = row[1]; // 寄附受付番号の列を指定
// 重複チェック
if (existingIds.indexOf(newId) === -1) {
var newRow = ['準備中'].concat(row); // A列に「準備中」、B列にCSVデータを追加
// B列にデータがある最後の行を取得し、その次の行に追加
var lastRowWithData = sheet.getRange(sheet.getMaxRows(), 2, 1, 1).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
sheet.insertRowAfter(lastRowWithData);
sheet.getRange(lastRowWithData + 1, 1, 1, newRow.length).setValues([newRow]);
}
}
}
// A列にプルダウンリストを設定
setDropdownForStatus(sheet);
// 出荷予定日がある場合にSlackにリマインドを投稿
postDailyShipmentCounts(sheet);
} catch (e) {
Logger.log('Error: ' + e.message);
}
}
function setDropdownForStatus(sheet) {
var lastRow = sheet.getLastRow();
var range = sheet.getRange(2, 1, lastRow - 1, 1); // A列の2行目以降を指定
var rule = SpreadsheetApp.newDataValidation()
.requireValueInList(['準備中', '出荷済', 'キャンセル'], true) // プルダウンの選択肢
.build();
range.setDataValidation(rule); // データ検証を設定
}
function postDailyShipmentCounts(sheet) {
var today = new Date();
today.setHours(0, 0, 0, 0); // 今日の日付の時間をリセット
var tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1); // 明日の日付を取得
var dataRange = sheet.getDataRange();
var data = dataRange.getValues();
var shipmentsToday = 0;
var shipmentsTomorrow = 0;
for (var i = 1; i < data.length; i++) { // ヘッダーをスキップ
var shipmentDateValue = data[i][8]; // 出荷予定日が入っている列(I列:インデックス8)
if (shipmentDateValue) { // 出荷予定日が存在する場合のみ処理
var shipmentDate = new Date(shipmentDateValue);
shipmentDate.setHours(0, 0, 0, 0); // 時間をリセット
if (shipmentDate.getTime() === today.getTime()) {
shipmentsToday++;
} else if (shipmentDate.getTime() === tomorrow.getTime()) {
shipmentsTomorrow++;
}
}
}
// 出荷件数がどちらもゼロでない場合のみSlackに送信
if (shipmentsToday > 0 || shipmentsTomorrow > 0) {
sendSlackShipmentCounts(shipmentsToday, shipmentsTomorrow);
}
}
function sendSlackShipmentCounts(shipmentsToday, shipmentsTomorrow) {
var webhookUrl = 'Slack Webhook URL'; // SlackのWebhook URLを指定
var message = '@channel\n' +
'本日の出荷件数: ' + shipmentsToday + ' 件\n' +
'明日の出荷件数: ' + shipmentsTomorrow + ' 件\n' +
'出荷リストを確認してください。\n' +
'SPREADSHEET_URL'; // スプレッドシートのリンク
var payload = JSON.stringify({
text: message,
link_names: 1 // メンションを有効にするためのオプション
});
var options = {
method: 'post',
contentType: 'application/json',
payload: payload
};
try {
UrlFetchApp.fetch(webhookUrl, options); // Slackにメッセージを送信
} catch (error) {
Logger.log('Error sending message to Slack: ' + error); // エラーログを記録
}
3-1. メインのスケジュールタスク
毎朝9時に「CSV取り込み → Slack通知」をまとめて実行する
Apps Script の「トリガー」画面で、
「関数の選択」
「イベントの種類を選択」→「時間主導型」→「日付ベースの毎日」
「時間」→「午前9時」
という形で設定しましょう。
3-2. CSV取込み
ポイント
「寄附受付番号」を軸に重複チェック
シートに既にある番号をチェックして、それ以外を追加
CSV の各行を読み込むときに「既にSetにあるか?」で判定
1行目(ヘッダ行)の扱い
もしさとふるのCSVもヘッダが1行目にあるなら、rows[0] をスキップしてそれ以降をデータとして扱う
ファイルの再取り込み対策
上記は「寄附受付番号」が同じならスキップするロジックなので、ファイルを移動/削除しなくても二重取り込みを防げます。
※私はフォルダ内に複数csvがあるのが気持ち悪いので、最新のcsvをアップ時に古いものは削除してます。
3-3. Slack通知
ここもAIに聞いたら設定方法から説明してくれました。SlackのWebhook URLさえ取得できれば、GASでSlack通知は可能です!
4. スプレッドシートでの色分け (条件付き書式)
ステータス列(A列/index=0) が「発送完了」であれば行をグレーアウト
シート上で「表示形式 → 条件付き書式」→「カスタム数式」
数式:=$A1="出荷済"
書式: 背景色をグレー
適用範囲: A:Z など必要に応じて
集荷予定日(I列/index=8) が TODAY() なら薄い赤
同様に「カスタム数式」で=$I1=TODAY()
適用範囲: 全列にして背景色を薄い赤
これでシートを開いたとき、
「今日発送」の行は赤く
「発送完了」はグレー
といったビジュアル管理ができるようになります。
5. 実際に運用してみた感想
「CSVをアップするだけ」でシートが最新になるので、あれこれ貼り付ける手間が消えた!
毎朝Slackに通知が飛ぶので、発送担当者は「今日何件?」を忘れないし、すぐ動き出せる。
ステータス管理もラクになり、「寄附受付番号」の重複はシステムで防止しているので安心。
最初は「Apps Scriptってハードル高いかな?」と思いましたが、意外とサンプルをコピペして少し書き換えるだけで動きます。
「もっと頻繁に取り込みたい」「ステータスが更新されたらSlack通知したい」など、応用も色々できますよ。
まとめ
寄附受付番号をキーに二重取り込み防止
毎朝9時に自動処理→Slack通知
シートは条件付き書式でビジュアル管理
これだけで大幅に手間が削減できました。
慣れないうちは「列番号や日付の取り扱いでハマる」ことがあるかもしれませんが、エラーが出たらログを見たり検索したりで解決できます。
ぜひみなさんも、業務の“ちょっと面倒”をGASとスプレッドシートで自動化してみてください。
きっと「これ自動化できるかも?」という目が養われて、他の業務にも波及していくはずです!
おわりに
2回にわたってお送りした「さとふる受注管理のGAS自動化」いかがでしたでしょうか?
「挑戦編」では構想やメリットをお伝えし、
「実践編」では実際のコード作成時のプロンプトと運用のコツを紹介しました。
ちょっとずつ試していけば、初心者でもきっとできると思います。
もし参考になったら、ぜひSNSなどでシェアやコメントをいただけると嬉しいです。
リストの自動更新とSlack自動通知は、これ以外にもかなり使えるのでは?と考えています!可能性かなりありますよね✨
最後まで読んでくださり、ありがとうございました!