デモ用モック
← 一覧に戻る
DBG部門 受発注業務自動化
Google Drive + GAS + Gemini AI を活用した野菜加工品 受発注業務の自動化
2つの自動化フロー
FAX受注の自動化 紙・FAX発注書の自動読み取り
帳合受注集計・発注書作成 Excelをフォルダに入れるだけ
1
撮影
2
アップロード
3
AI読み取り
4
自動転記
5
指示書出力
STEP 1 / 5
手作業

紙の発注書をスマートフォンで撮影する

FAX・紙で届いた発注書をスマートフォンで撮影します。シャッターボタンをタップしてください。

スマートフォン カメラアプリ
発 注 書
発注日:2026/10/06
紀の川青果㈱
カットキャベツ200袋
白菜カット150袋
千切りにんじん100袋
納期:10/8 午前中
📸
撮影完了
シャッターボタンをクリックして撮影してください
撮影(またはスキャン)が担当者の最初の手作業です。
手作業

共有フォルダ(FAX受注)にアップロードする

撮影した画像・PDFを「共有フォルダ > DBG > FAX受注」に保存します。手作業はここで終わりです。

drive.google.com / 共有フォルダ / DBG / FAX受注
共有フォルダ > DBG > FAX受注
📄
発注書_南紀青果_1003.pdf
処理済み
📄
発注書_オークワ橋本店_1005.jpg
処理済み
🖼️
発注書_紀の川青果_1006.jpg(撮影済み)
自動処理

GAS 起動 → Gemini が発注書を自動読み取り

GAS がファイルを検知し、Gemini API に画像・PDF を送信。AI が発注書の内容をテキスト化します。所要時間:約3〜5分。

GAS 実行ログ → Gemini OCR 読み取り結果
実行ログ
✓ 発注書_紀の川青果_1006.jpg を検知
✓ Gemini API に画像データを送信
✓ 画像解析完了(2.8秒)
→ 読み取り結果をスプレッドシートに転記中...
自動処理

スプレッドシートに自動転記される

読み取ったデータが FAX 受注管理シートに自動転記されます。新規データはハイライトされます。

スプレッドシート:FAX受注管理
受付日得意先商品名数量単位納期特記状態
110/3南紀青果きざみネギパック300袋10/5処理済
210/6紀の川青果カットキャベツ(200g)200袋10/8冷蔵便★新規
310/6紀の川青果白菜カット(300g)150袋10/8冷蔵便★新規
410/6紀の川青果千切りにんじん(150g)100袋10/8冷蔵便★新規
確認・出力

作業指示書を確認して出力する

内容を確認後、「PDF 出力」ボタンで指示書 PDF を生成します。

作業指示書 自動生成

作業指示書

出力日時:2026年10月6日 14:25 / 自動生成

2026年10月8日(木)
紀の川青果 株式会社
午前中指定(冷蔵便)
第1冷蔵加工室
商品名数量保管場所
カットキャベツ(200g)200袋第1冷蔵加工室
白菜カット(300g)150袋第1冷蔵加工室
千切りにんじん(150g)100袋第2冷蔵加工室
特記事項:午前中納品希望・冷蔵便指定
完了。 撮影→アップロードの2ステップだけで、作業指示書まで自動生成されました。
スプレッドシート列定義
列項目名型備考
A受付日日付GAS自動入力
B得意先名テキストGemini読み取り値
C商品名テキストGemini読み取り値
D数量数値Gemini読み取り値
E単位テキスト袋/本/ケース
F納期日付不明なら「要確認」
G特記事項テキスト冷蔵便・時間指定など
H状態テキストGASが「★新規」と入力
I元ファイル名テキストGAS自動入力(トレース用)
Gemini OCR プロンプト 
あなたは発注書の画像を読み取るOCRアシスタントです。 以下の発注書を解析し、必ずJSON形式のみで回答してください(説明・コードブロック不要)。 { "発注日": "YYYY/MM/DD 形式 または null", "得意先名": "会社名 または null", "担当者名": "名前 または null(読み取れない場合)", "納期": "YYYY/MM/DD 形式 または null", "特記事項": "配送指定・備考など または null", "商品リスト": [ { "商品名": "商品名(規格・サイズも含む)", "数量": 数値(整数・文字列不可), "単位": "袋/本/ケース/枚 など" } ] } 【必ず守ること】 ・読み取れない・不明な項目は必ず null とする ・数量は数値型(例: 100)で出力し、文字列にしないこと ・日付は YYYY/MM/DD 形式に統一すること ・JSON のみ返答すること(``` や説明文を含めない)
GAS コード(完全版) 
// =================================================== // FAX受注 自動処理スクリプト // Gemini Vision API を使って発注書画像を自動読み取り // =================================================== const CONFIG = { FAX_FOLDER_ID: '★ FAX受注フォルダのID(DriveのURLから取得)', SHEET_ID: '★ FAX受注管理スプレッドシートのID(URLから取得)', SHEET_NAME: 'FAX受注管理', GEMINI_API_KEY: '★ Google AI Studio で取得した APIキー', GEMINI_MODEL: 'gemini-1.5-flash', }; const PROMPT = `あなたは発注書の画像を読み取るOCRアシスタントです。 以下の発注書を解析し、必ずJSON形式のみで回答してください(説明不要)。 { "発注日": "YYYY/MM/DD または null", "得意先名": "会社名 または null", "担当者名": "名前 または null", "納期": "YYYY/MM/DD または null", "特記事項": "テキスト または null", "商品リスト": [{"商品名": "名前", "数量": 数値, "単位": "袋/本/ケース等"}] } 読み取れない項目はnull。JSONのみ返答。`; /** * ① メイン処理(トリガーで5分ごとに実行) */ function checkFaxFolder() { const folder = DriveApp.getFolderById(CONFIG.FAX_FOLDER_ID); const files = folder.getFiles(); const sheet = SpreadsheetApp .openById(CONFIG.SHEET_ID) .getSheetByName(CONFIG.SHEET_NAME); while (files.hasNext()) { const file = files.next(); if (file.getName().includes('_処理済み')) continue; try { const data = callGeminiOCR(file); writeToSheet(sheet, data, file.getName()); file.setName(file.getName() + '_処理済み'); console.log('処理完了:', file.getName()); } catch (e) { console.error('エラー:', file.getName(), e.message); } } } /** * ② Gemini Vision API 呼び出し → JSONを返す */ function callGeminiOCR(file) { const blob = file.getBlob(); const base64 = Utilities.base64Encode(blob.getBytes()); const mimeType = blob.getContentType(); const payload = { contents: [{ parts: [ { text: PROMPT }, { inline_data: { mime_type: mimeType, data: base64 } } ] }] }; const url = `https://generativelanguage.googleapis.com/v1beta/models/` + `${CONFIG.GEMINI_MODEL}:generateContent?key=${CONFIG.GEMINI_API_KEY}`; const res = UrlFetchApp.fetch(url, { method: 'post', contentType: 'application/json', payload: JSON.stringify(payload), }); const text = JSON.parse(res.getContentText()) .candidates[0].content.parts[0].text; return JSON.parse(text); } /** * ③ スプレッドシートへの書き込み(商品ごとに1行) */ function writeToSheet(sheet, data, fileName) { const today = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'MM/dd'); data.商品リスト.forEach(item => { sheet.appendRow([ today, data.得意先名 || '要確認', item.商品名, item.数量, item.単位 || '', data.納期 || '要確認', data.特記事項 || '', '★新規', fileName, ]); }); }
GAS トリガー設定手順
  1. GAS エディタ(script.google.com)を開き、上記コードを貼り付ける
  2. CONFIG の各 ID を実際の値に書き換える
    フォルダID:DriveのURLの「folders/」以降 / シートID:スプレッドシートURLの「/d/」以降
  3. 左メニューの「トリガー(時計アイコン)」→「トリガーを追加」
  4. 関数:checkFaxFolder / イベント:時間主導型 → 5分おき で保存
  5. 初回のみ「権限を確認」ダイアログを許可する
Gemini への質問テンプレート:
「GASでDriveの特定フォルダを監視し、新しい画像が追加されたらGemini APIで解析してスプレッドシートに書き込むコードを書いてください。CONFIG変数:[CONFIGの内容を貼り付け]」
手作業

得意先から Excel 受注書を受け取る

各得意先から届く Excel 形式の受注書を受け取ります。得意先ごとにフォーマットが異なっていても自動で読み取ります。

メール受信トレイ
オークワ各店舗から受信した Excel 受注書(クリックで選択)
📊
オークワ和歌山店
受注書_1006.xlsx
✓ 選択中
📊
オークワ奈良店
order_20261006.xlsx
✓ 選択中
📊
オークワ東海店
発注_10月.xlsx
✓ 選択中
得意先ごとに Excel のフォーマットが違っていても、GAS が自動で統一して取り込みます。
Excel ファイルを受け取ってフォルダに保存するだけで OK です。
手作業

指定フォルダ(帳合受注)に保存する

「共有フォルダ > DBG > 帳合受注」に Excel ファイルを保存します。手作業はここで終わりです。

drive.google.com / 共有フォルダ / DBG / 帳合受注
共有フォルダ > DBG > 帳合受注
自動処理

GAS が各受注書を取り込み・統合集計する

フォーマットが異なる 3 社分の Excel を読み込み、商品ごとに統合集計します。

GAS 自動実行ログ
📊
山田スーパー
処理中
📊
田中マート
処理中
📊
鈴木商店
処理中
実行ログ
✓ オークワ和歌山店_受注書_1006.xlsx 読み込み完了
✓ オークワ奈良店_order_20261006.xlsx 読み込み完了
✓ オークワ東海店_発注_10月.xlsx 読み込み完了
✓ 商品マスターと照合完了
✓ 得意先別・商品別に統合集計完了
→ 集計シートへの書き込み完了
確認

集計シートで数量・内容を確認する

得意先別・商品別の受注数量が自動集計されています。確認後、「発注書作成」ボタンを押します。

スプレッドシート:帳合受注 集計シート
✅ 3 店舗分を自動集計しました(10/6 15:10)
商品名和歌山店奈良店東海店合計数量仕入れ先
きざみネギパック(100g)4002803201,000袋淡路島ファーム
ケン付大根(刺身用)250–180430袋淡路島ファーム
炒め物野菜ミックス(200g)–350290640袋三重産直センター
グリーンサラダパック200150–350袋三重産直センター
数量に誤りがあればここで修正できます。確認後ボタンを押すだけです。
自動処理

仕入れ先別の発注書が自動生成される

複数得意先の注文を合算した仕入れ先ごとの発注書が自動生成されます。PDF 出力・メール送信も対応。

自動生成された発注書(仕入れ先別)
✅ 2 社分の発注書を自動生成しました

淡路島ファーム 発注書

発注日:2026年10月6日

商品名数量
きざみネギパック(100g)1,000袋
ケン付大根(刺身用)430袋
合計 1,430袋

三重産直センター 発注書

発注日:2026年10月6日

商品名数量
炒め物野菜ミックス(200g)640袋
グリーンサラダパック350袋
合計 990袋
完了。 オークワ 3 店舗分の受注 Excel をフォルダに保存するだけで、仕入れ先 2 社への発注書が自動生成されました。
実装ガイド:帳合受注フロー(Excel自動集計 GAS)
商品マスターシート 列定義
列項目名記入例備考
A商品名(キー)きざみネギパックExcelの商品名と前方一致で照合
B規格100g参考情報
C仕入れ先淡路島ファーム発注書の宛先として使用
D単位袋集計・発注書に使用
商品マスターは事前にすべての取扱商品を登録しておくこと。登録外の商品は「要確認」として集計されます。
GAS コード(完全版) 
// =================================================== // 帳合受注 自動集計スクリプト // Excelをフォルダに入れるだけで仕入れ先別に集計・発注書生成 // =================================================== const CHOGAI = { FOLDER_ID: '★ 帳合受注フォルダのID', SHEET_ID: '★ 帳合集計スプレッドシートのID', SUMMARY_SHEET: '帳合集計', MASTER_SHEET: '商品マスター', PO_SHEET: '発注書', }; /** ① メイン処理(トリガーで5分ごとに実行) */ function processChogaiFiles() { const folder = DriveApp.getFolderById(CHOGAI.FOLDER_ID); const ss = SpreadsheetApp.openById(CHOGAI.SHEET_ID); const master = ss.getSheetByName(CHOGAI.MASTER_SHEET) .getDataRange().getValues(); const summary = ss.getSheetByName(CHOGAI.SUMMARY_SHEET); const files = folder.getFiles(); while (files.hasNext()) { const file = files.next(); const name = file.getName(); if (!name.match(/\.xlsx?$/i)) continue; if (name.includes('_処理済み')) continue; try { const rows = readExcelFile(file); aggregateRows(summary, rows, master, name); file.setName(name + '_処理済み'); console.log('集計完了:', name); } catch (e) { console.error('エラー:', name, e.message); } } generatePurchaseOrders(ss); } /** ② ExcelをGoogleスプレッドシートに変換して読み込む */ function readExcelFile(file) { const tempId = Drive.Files.copy( { title: '_tmp_' + file.getName(), mimeType: MimeType.GOOGLE_SHEETS }, file.getId() ).id; const data = SpreadsheetApp.openById(tempId) .getSheets()[0].getDataRange().getValues(); DriveApp.getFileById(tempId).setTrashed(true); let hRow = 0; for (let i = 0; i < Math.min(15, data.length); i++) { if (data[i].some(c => /商品|品名|アイテム/.test(String(c)))) { hRow = i; break; } } const headers = data[hRow].map(c => String(c)); const nameCol = headers.findIndex(h => /商品|品名/.test(h)); const qtyCol = headers.findIndex(h => /数量|個数|発注数/.test(h)); const unitCol = headers.findIndex(h => /単位/.test(h)); return data.slice(hRow + 1) .filter(row => row[nameCol] && Number(row[qtyCol]) > 0) .map(row => ({ 商品名: String(row[nameCol]).trim(), 数量: Number(row[qtyCol]), 単位: unitCol >= 0 ? String(row[unitCol]) : '袋', })); } /** ③ 集計シートへの書き込み(商品マスターで仕入れ先を照合) */ function aggregateRows(sheet, rows, master, fileName) { const today = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'MM/dd'); const store = extractStoreName(fileName); rows.forEach(row => { const m = master.find(r => row.商品名.startsWith(String(r[0]).substring(0, 4))); const supplier = m ? m[2] : '要確認'; const existing = findRowByItem(sheet, row.商品名); if (existing > 0) { const col = getStoreColumn(sheet, store); const cell = sheet.getRange(existing, col); cell.setValue((Number(cell.getValue()) || 0) + row.数量); } else { sheet.appendRow([row.商品名, row.単位, supplier, today, 0, 0, 0, row.数量]); } }); } /** ④ 仕入れ先別の発注書シートを自動生成・更新 */ function generatePurchaseOrders(ss) { const summary = ss.getSheetByName(CHOGAI.SUMMARY_SHEET); const poSheet = ss.getSheetByName(CHOGAI.PO_SHEET) || ss.insertSheet(CHOGAI.PO_SHEET); const data = summary.getDataRange().getValues(); poSheet.clearContents(); poSheet.appendRow(['仕入れ先', '商品名', '数量', '単位', '発注日']); const today = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd'); data.slice(1).forEach(row => { const total = (row[4] || 0) + (row[5] || 0) + (row[6] || 0); if (total > 0) { poSheet.appendRow([row[2], row[0], total, row[1], today]); } }); }
GAS トリガー設定手順
  1. GAS エディタで新しいプロジェクトを作成し、上記コードを貼り付ける
  2. 「サービス」→「Drive API」を追加する(Excel読み込みに必要)
  3. CHOGAI の各 ID を実際の値に書き換える
  4. 「トリガー」→「トリガーを追加」→ 関数:processChogaiFiles / タイプ:5分おきタイマー で保存
  5. 初回のみ権限を許可する
よくある質問
質問対処法
Excelのフォーマットが店舗ごとに違うヘッダー行の自動検出ロジックが対応。「商品」「品名」を含む行を自動で探します
処理完了をSlack/LINEに通知したいUrlFetchApp.fetch() でWebhook URLにPOSTするだけで通知できます
マスターにない商品が来た場合「要確認」として集計。GmailApp.sendEmail() でメール通知も追加可能
このガイドを読めば、Gemini × GAS で同じ自動化システムを自分たちで構築できます。
Gemini に質問しながら進めれば、プログラミング経験がなくても実装可能です。
1. 事前準備・必要なもの
アカウント・API
  • ★
    Google アカウント(組織の Google Workspace 推奨)個人アカウントでも動作しますが、共有ドライブが使える Workspace 推奨
  • ★
    Gemini API キーGoogle AI Studio(aistudio.google.com)にアクセスし「Get API Key」から無料取得。月100万トークン無料枠あり
  • ★
    Google Drive Advanced Service の有効化GAS エディタ → 「サービス」→「Drive API」を追加。Excel読み込みに必要
Google Drive フォルダ構成
共有ドライブ(または マイドライブ)/ └── DBG/ ├── FAX受注/ ← 発注書画像をここにアップロード ├── FAX受注_処理済み/ ← 処理後に自動移動(任意) └── 帳合受注/ ← Excel受注書をここに保存
Google スプレッドシート(2つ作成)
  • ★
    FAX受注管理シート ― 受付日・得意先・商品名・数量・納期・状態 などの列を準備
  • ★
    帳合集計シート ― 商品名・店舗別数量・合計・仕入れ先 の列を準備
  • ★
    商品マスターシート(帳合シートのタブとして追加) ― 商品名・規格・仕入れ先 を事前登録
2. FAX受注フロー — Gemini OCR + GAS 実装
スプレッドシート 列定義(FAX受注管理)
列項目名型備考
A受付日日付GASが自動入力
B得意先名テキストGemini読み取り値。不明なら「要確認」
C商品名テキストGemini読み取り値
D数量数値Gemini読み取り値
E単位テキスト袋/本/ケース など
F納期日付Gemini読み取り値。不明なら「要確認」
G特記事項テキスト冷蔵便・時間指定など
H状態テキストGASが「★新規」と入力。処理後に担当者が更新
I元ファイル名テキストGASが自動入力(トレーサビリティ用)
Gemini OCR プロンプト 
あなたは発注書の画像を読み取るOCRアシスタントです。 以下の発注書を解析し、必ずJSON形式のみで回答してください(説明・コードブロック不要)。 { "発注日": "YYYY/MM/DD 形式 または null", "得意先名": "会社名 または null", "担当者名": "名前 または null(読み取れない場合)", "納期": "YYYY/MM/DD 形式 または null", "特記事項": "配送指定・備考など または null", "商品リスト": [ { "商品名": "商品名(規格・サイズも含む)", "数量": 数値(整数・文字列不可), "単位": "袋/本/ケース/枚 など" } ] } 【必ず守ること】 ・読み取れない・不明な項目は必ず null とする ・数量は数値型(例: 100)で出力し、文字列にしないこと ・日付は YYYY/MM/DD 形式に統一すること ・JSON のみ返答すること(``` や説明文を含めない)
GAS コード(完全版) 
// =================================================== // FAX受注 自動処理スクリプト // Gemini Vision API を使って発注書画像を自動読み取り // =================================================== const CONFIG = { FAX_FOLDER_ID: '★ FAX受注フォルダのID(DriveのURLから取得)', SHEET_ID: '★ FAX受注管理スプレッドシートのID(URLから取得)', SHEET_NAME: 'FAX受注管理', GEMINI_API_KEY: '★ Google AI Studio で取得した APIキー', GEMINI_MODEL: 'gemini-1.5-flash', }; const PROMPT = `あなたは発注書の画像を読み取るOCRアシスタントです。 以下の発注書を解析し、必ずJSON形式のみで回答してください(説明不要)。 { "発注日": "YYYY/MM/DD または null", "得意先名": "会社名 または null", "担当者名": "名前 または null", "納期": "YYYY/MM/DD または null", "特記事項": "テキスト または null", "商品リスト": [{"商品名": "名前", "数量": 数値, "単位": "袋/本/ケース等"}] } 読み取れない項目はnull。JSONのみ返答。`; /** * ① メイン処理(トリガーで5分ごとに実行) */ function checkFaxFolder() { const folder = DriveApp.getFolderById(CONFIG.FAX_FOLDER_ID); const files = folder.getFiles(); const sheet = SpreadsheetApp .openById(CONFIG.SHEET_ID) .getSheetByName(CONFIG.SHEET_NAME); while (files.hasNext()) { const file = files.next(); if (file.getName().includes('_処理済み')) continue; try { const data = callGeminiOCR(file); writeToSheet(sheet, data, file.getName()); file.setName(file.getName() + '_処理済み'); console.log('処理完了:', file.getName()); } catch (e) { console.error('エラー:', file.getName(), e.message); } } } /** * ② Gemini Vision API 呼び出し → JSONを返す */ function callGeminiOCR(file) { const blob = file.getBlob(); const base64 = Utilities.base64Encode(blob.getBytes()); const mimeType = blob.getContentType(); const payload = { contents: [{ parts: [ { text: PROMPT }, { inline_data: { mime_type: mimeType, data: base64 } } ] }] }; const url = `https://generativelanguage.googleapis.com/v1beta/models/` + `${CONFIG.GEMINI_MODEL}:generateContent?key=${CONFIG.GEMINI_API_KEY}`; const res = UrlFetchApp.fetch(url, { method: 'post', contentType: 'application/json', payload: JSON.stringify(payload), }); const text = JSON.parse(res.getContentText()) .candidates[0].content.parts[0].text; return JSON.parse(text); } /** * ③ スプレッドシートへの書き込み(商品ごとに1行) */ function writeToSheet(sheet, data, fileName) { const today = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'MM/dd'); data.商品リスト.forEach(item => { sheet.appendRow([ today, data.得意先名 || '要確認', item.商品名, item.数量, item.単位 || '', data.納期 || '要確認', data.特記事項 || '', '★新規', fileName, ]); }); }
GASトリガー設定手順(FAX受注)
  1. GAS エディタ(script.google.com)を開き、上記コードを貼り付ける
  2. CONFIG の各 ID を実際の値に書き換える
    フォルダID:DriveのURLの「folders/」以降の文字列 / シートID:スプレッドシートURLの「/d/」以降の文字列
  3. 左メニューの「トリガー(時計アイコン)」→「トリガーを追加」をクリック
  4. 実行する関数:checkFaxFolder / イベントのソース:時間主導型 / タイプ:5分おきタイマー を選択して保存
  5. 初回のみ「権限を確認」ダイアログが出るので許可する(Googleアカウントのアクセス許可)
3. 帳合受注フロー — Excel自動集計 GAS 実装
商品マスターシート 列定義
列項目名記入例備考
A商品名(キー)きざみネギパックExcelの商品名と前方一致で照合
B規格100g参考情報
C仕入れ先淡路島ファーム発注書の宛先として使用
D単位袋集計・発注書に使用
商品マスターは事前にすべての取扱商品を登録しておくこと。登録外の商品は「要確認」として集計されます。
GAS コード(完全版) 
// =================================================== // 帳合受注 自動集計スクリプト // Excelをフォルダに入れるだけで仕入れ先別に集計・発注書生成 // =================================================== const CHOGAI = { FOLDER_ID: '★ 帳合受注フォルダのID', SHEET_ID: '★ 帳合集計スプレッドシートのID', SUMMARY_SHEET: '帳合集計', MASTER_SHEET: '商品マスター', PO_SHEET: '発注書', }; /** * ① メイン処理(トリガーで5分ごとに実行) */ function processChogaiFiles() { const folder = DriveApp.getFolderById(CHOGAI.FOLDER_ID); const ss = SpreadsheetApp.openById(CHOGAI.SHEET_ID); const master = ss.getSheetByName(CHOGAI.MASTER_SHEET) .getDataRange().getValues(); const summary = ss.getSheetByName(CHOGAI.SUMMARY_SHEET); const files = folder.getFiles(); while (files.hasNext()) { const file = files.next(); const name = file.getName(); if (!name.match(/\.xlsx?$/i)) continue; if (name.includes('_処理済み')) continue; try { const rows = readExcelFile(file); aggregateRows(summary, rows, master, name); file.setName(name + '_処理済み'); console.log('集計完了:', name); } catch (e) { console.error('エラー:', name, e.message); } } generatePurchaseOrders(ss); // 仕入れ先別発注書を更新 } /** * ② ExcelファイルをGoogleスプレッドシートに変換して読み込む * ヘッダー行を自動検出し、商品名・数量列を特定する */ function readExcelFile(file) { // ExcelをGスプレッドシートとして一時コピー const tempId = Drive.Files.copy( { title: '_tmp_' + file.getName(), mimeType: MimeType.GOOGLE_SHEETS }, file.getId() ).id; const data = SpreadsheetApp.openById(tempId) .getSheets()[0].getDataRange().getValues(); DriveApp.getFileById(tempId).setTrashed(true); // 一時ファイルを削除 // ヘッダー行を検出(「商品」「品名」を含む行を探す) let hRow = 0; for (let i = 0; i < Math.min(15, data.length); i++) { if (data[i].some(c => /商品|品名|アイテム/.test(String(c)))) { hRow = i; break; } } const headers = data[hRow].map(c => String(c)); const nameCol = headers.findIndex(h => /商品|品名/.test(h)); const qtyCol = headers.findIndex(h => /数量|個数|発注数/.test(h)); const unitCol = headers.findIndex(h => /単位/.test(h)); return data.slice(hRow + 1) .filter(row => row[nameCol] && Number(row[qtyCol]) > 0) .map(row => ({ 商品名: String(row[nameCol]).trim(), 数量: Number(row[qtyCol]), 単位: unitCol >= 0 ? String(row[unitCol]) : '袋', })); } /** * ③ 集計シートへの書き込み(商品マスターで仕入れ先を照合) */ function aggregateRows(sheet, rows, master, fileName) { const today = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'MM/dd'); const store = extractStoreName(fileName); // ファイル名から店舗名を取得 rows.forEach(row => { // 商品マスターと照合して仕入れ先を特定 const m = master.find(r => row.商品名.startsWith(String(r[0]).substring(0, 4))); const supplier = m ? m[2] : '要確認'; // 既存行があれば数量を加算、なければ新規追加 const existing = findRowByItem(sheet, row.商品名); if (existing > 0) { const col = getStoreColumn(sheet, store); const cell = sheet.getRange(existing, col); cell.setValue((Number(cell.getValue()) || 0) + row.数量); } else { sheet.appendRow([row.商品名, row.単位, supplier, today, 0, 0, 0, row.数量]); } }); } /** * ④ 仕入れ先別の発注書シートを自動生成・更新 */ function generatePurchaseOrders(ss) { const summary = ss.getSheetByName(CHOGAI.SUMMARY_SHEET); const poSheet = ss.getSheetByName(CHOGAI.PO_SHEET) || ss.insertSheet(CHOGAI.PO_SHEET); const data = summary.getDataRange().getValues(); poSheet.clearContents(); poSheet.appendRow(['仕入れ先', '商品名', '数量', '単位', '発注日']); const today = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd'); data.slice(1).forEach(row => { const total = (row[4] || 0) + (row[5] || 0) + (row[6] || 0); // 各店舗の合計 if (total > 0) { poSheet.appendRow([row[2], row[0], total, row[1], today]); } }); }
GASトリガー設定手順(帳合受注)
  1. GAS エディタで新しいプロジェクトを作成し、上記コードを貼り付ける
  2. 「サービス」→「Drive API」を追加する(Excel読み込みに必要)
  3. CHOGAI の各 ID を実際の値に書き換える
  4. 左メニューの「トリガー」→「トリガーを追加」→ 関数:processChogaiFiles / タイプ:5分おきタイマー で保存
  5. 初回のみ権限を許可する
4. よくある質問・カスタマイズポイント
質問回答・対処法
Gemini の読み取り精度が低い場合は?プロンプトに「商品名の候補リスト」を追加するとマッチング精度が大幅に向上します。例:
取り扱い商品例:きざみネギパック、ケン付大根、カットキャベツ...
PDFが読み取れない場合は?GAS の getBlob() は PDF も対応しています。Gemini 1.5 Flash/Pro は PDF をネイティブで解析できます
Excelのフォーマットが店舗ごとに全然違う場合は?ヘッダー行の自動検出ロジックを調整してください。または Gemini に Excel を解析させる方法(PDF化して送信)も有効です
処理完了を Slack や LINE に通知したいGAS には UrlFetchApp.fetch() があるので、Webhook URL に POST するだけで通知できます
商品マスターに登録していない商品が来た場合現在のコードは「要確認」として書き込みます。GAS からメール通知するよう GmailApp.sendEmail() を追加することも可能です
Gemini に相談する際の質問例
Gemini への質問テンプレート 「Google Apps Script で Google Drive の特定フォルダを監視し、 新しいファイルが追加されたら Gemini API で画像解析して スプレッドシートに書き込むコードを書いてください。 以下の CONFIG 変数を使ってください:[CONFIGの内容を貼り付け]」 「このGASコードでエラーが出ています。原因を教えてください:[エラー文を貼り付け]」 「Excel の列構成が以下のようになっています。商品名と数量を 正しく取得するにはどう修正すればいいですか:[列構成を貼り付け]」