GASとGemini APIで領収書を自動でスプレッドシートに記録する

目次
注意事項
- 本記事の内容は試験的な実装であり、アイデアベースの検証です
- 実務での利用を保証するものではありません
- 実装についての責任は負いかねます。自己責任でご利用ください
- AIの出力結果は常に検証が必要です
概要
領収書をスマホで撮影してGoogle Driveに保存するだけで、Gemini APIが内容を解析し、スプレッドシートに自動で記録する仕組みを作ります。
できること
- 領収書画像をGoogle Driveの指定フォルダに置く
- GASが定期的にフォルダをチェック
- Gemini APIで画像から情報を抽出(日付、金額、店名など)
- スプレッドシートに自動記録
- 処理済みの画像は別フォルダに移動
事前準備
1. Google Driveにフォルダを作成
以下の2つのフォルダを作成します。
| フォルダ名 | 用途 |
|---|---|
| 未処理 | 領収書画像を置くフォルダ |
| 処理済み | 処理完了した画像の移動先 |
フォルダIDはURLから取得できます:
https://drive.google.com/drive/folders/【ここがフォルダID】
2. Gemini APIキーの取得
Google AI Studio からAPIキーを取得します。
注意: APIキーは外部に漏れないよう厳重に管理してください
3. スプレッドシートの準備
新規スプレッドシートを作成し、1行目にヘッダーを設定します:
| A | B | C | D | E | F | G | H | I | J |
|---|---|---|---|---|---|---|---|---|---|
| 日付 | 科目 | 金額 | 税金 | 店名 | 仕入 | 参照先 | 支払い方法 | 会社名 | インボイス |
GASのコード
スプレッドシートの「拡張機能」→「Apps Script」を開き、以下のコードを貼り付けます。
// ==========================================
// 初期設定:以下の3箇所をご自身の環境に合わせて書き換えてください
// ==========================================
const GEMINI_API_KEY = PropertiesService.getScriptProperties().getProperty('GEMINI_API_KEY');
const UNPROCESSED_FOLDER_ID = 'ここに未処理フォルダのIDを貼り付けます';
const PROCESSED_FOLDER_ID = 'ここに処理済みフォルダのIDを貼り付けます';
// ==========================================
// メイン処理
// ==========================================
function processReceipts() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const sourceFolder = DriveApp.getFolderById(UNPROCESSED_FOLDER_ID);
const targetFolder = DriveApp.getFolderById(PROCESSED_FOLDER_ID);
// 未処理フォルダ内のファイルを取得
const files = sourceFolder.getFiles();
while (files.hasNext()) {
const file = files.next();
const mimeType = file.getMimeType();
// ★変更点: 画像ファイルとPDFファイルを対象にする
if (mimeType.startsWith('image/') || mimeType === 'application/pdf') {
try {
// Gemini APIでデータを解析
const receiptDataArray = analyzeReceiptWithGemini(file);
if (receiptDataArray && receiptDataArray.length > 0) {
for (let i = 0; i < receiptDataArray.length; i++) {
const receiptData = receiptDataArray[i];
const rowData = [
receiptData.date || "",
receiptData.category || "",
receiptData.amount || "",
receiptData.tax || "",
receiptData.storeName || "",
receiptData.purchase || "",
file.getUrl(),
receiptData.paymentMethod || "",
receiptData.companyName || "",
receiptData.invoiceNumber || ""
];
sheet.appendRow(rowData);
}
file.moveTo(targetFolder);
Utilities.sleep(2000);
}
} catch (e) {
console.error("ファイル " + file.getName() + " の処理中にエラーが発生しました: " + e.message);
}
}
}
}
// ==========================================
// Gemini API 呼び出し処理
// ==========================================
function analyzeReceiptWithGemini(file) {
const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${GEMINI_API_KEY}`;
// ★変更点: 変数名を画像とPDFの両方に合うように base64Data に変更
const base64Data = Utilities.base64Encode(file.getBlob().getBytes());
const mimeType = file.getMimeType();
// ★変更点: プロンプトに「PDF」という言葉を追加し、AIの認識精度を高める
const prompt = `
あなたは優秀な経理アシスタントです。添付された領収書または請求書のデータ(画像またはPDF)から、以下の情報を抽出し、JSON形式の「配列」で出力してください。
Markdownの装飾(バッククォートなど)は一切含めず、純粋なJSONテキストのみを返してください。
【重要な指示】
- 消費税率が10%のものと8%のものが混在している場合は、それぞれを分けて2つのオブジェクトとして配列に格納して返してください。
- 単一の税率しかない場合でも、1つのオブジェクトを含む配列として返してください。
【抽出する項目とJSONキー】各オブジェクトに以下のキーを含めてください。
- date: 日付 (YYYY/MM/DD形式)
- category: 科目 (例: 消耗品費、交通費、会議費、接待交際費など。内容から推測してください)
- amount: 対象となる税率の合計金額 (数字のみ)
- tax: 対象となる税率の消費税額 (数字のみ。記載がない場合は推測せず空白にする)
- storeName: 店名または発行者名
- purchase: 仕入かどうか (仕入に関わるものの場合は "対象"、それ以外は空白にする)
- paymentMethod: 支払い方法 (現金、クレジットカード、PayPayなど)
- companyName: 支払い方法がクレジットカードの場合、領収書に記載されているクレジットカード番号の「下4桁の数字」のみを入れてください。クレジットカード払いではない場合、または記載がない場合は空白にしてください。
- invoiceNumber: インボイス登録番号 (Tから始まる13桁の数字。記載がない場合は空白)
`;
const payload = {
"contents": [
{
"parts": [
{"text": prompt},
{
"inline_data": {
"mime_type": mimeType,
"data": base64Data
}
}
]
}
]
};
const options = {
"method": "post",
"contentType": "application/json",
"payload": JSON.stringify(payload),
"muteHttpExceptions": true
};
const response = UrlFetchApp.fetch(url, options);
const jsonResponse = JSON.parse(response.getContentText());
if (jsonResponse.error) {
throw new Error(jsonResponse.error.message);
}
try {
let text = jsonResponse.candidates[0].content.parts[0].text;
text = text.replace(/```json/g, "").replace(/```/g, "").trim();
return JSON.parse(text);
} catch (e) {
throw new Error("Geminiからの応答の解析に失敗しました。応答内容: " + (jsonResponse.candidates ? jsonResponse.candidates[0].content.parts[0].text : JSON.stringify(jsonResponse)));
}
}
APIキーの安全な管理
APIキーはコードに直接書かず、スクリプトプロパティに保存します。
- Apps Scriptエディタで「プロジェクトの設定」(歯車アイコン)を開く
- 「スクリプト プロパティ」セクションで「スクリプト プロパティを追加」
- プロパティ名: GEMINI_API_KEY、値: 取得したAPIキー
トリガーの設定
定期実行するためにトリガーを設定します。
- Apps Scriptエディタの左メニューから「トリガー」(時計アイコン)を選択
- 「トリガーを追加」をクリック
- 以下のように設定
| 項目 | 設定値 |
|---|---|
| 実行する関数 | processReceipts |
| イベントのソース | 時間主導型 |
| 時間ベースのトリガーのタイプ | 分ベースのタイマー(または時間ベース) |
| 間隔 | 任意(例: 1時間おき) |
使い方
- 領収書をスマホで撮影
- Google Driveの「未処理」フォルダにアップロード
- トリガーが実行されると自動でスプレッドシートに記録
- 処理済み画像は「処理済み」フォルダに移動
注意点
| 項目 | 内容 |
|---|---|
| AIの解析精度 | 手書きや不鮮明な領収書は正確に読み取れない場合があります |
| 必ず目視確認 | 自動記録された内容は必ず確認してください |
| API利用料 | Gemini APIには無料枠がありますが、大量処理時は料金を確認してください |
| 税率の分離 | 軽減税率(8%)と標準税率(10%)が混在する場合、別々の行として記録されます |
まとめ
GASとGemini APIを組み合わせることで、領収書処理の自動化が実現できます。 ただし、AIの解析結果を鵜呑みにせず、必ず人の目で確認することをお勧めします。