業務効率化・自動化
もう、手入力に悩まない。紙の請求書、自動でデータ化。

手入力からの解放!Google Drive OCRで請求書を自動入力

「毎月届く請求書を、手入力でExcelや会計ソフトに転記している」・・・そんな作業に悩まされていませんか?
紙やPDFで受け取った請求書から金額や日付を探し出し、スプレッドシートに入力するのは地味に時間がかかります。さらに転記ミスのリスクも避けられません。

そこで今回は、紙の請求書の画像から自動でデータを抽出し、スプレッドシートに入力する方法をご紹介します。使うのは、Google Workspaceに標準で備わっている Google Drive OCR(文字認識) 機能です。追加費用は不要で、すぐに試せるのが魅力です。

Google Drive OCRとは?

Google Driveにアップロードした画像やPDFファイルから、自動的に文字を読み取り、テキストデータとしてGoogle ドキュメントを生成する機能です。
例えば、スキャンした請求書やスマホで撮影した紙の請求書をアップロードするだけで、中身の文字をテキストとして取得できます。

OCRで請求書から何ができるのか

  • 請求日や支払期日の抽出
  • 金額(合計・税額)の抽出
  • 顧客名や品目の取得

もちろん完璧ではありませんが、ゼロから手入力するよりも大幅に工数を削減できます。
これらの機能を使えば、毎日忙しい経理担当者の作業時間を劇的に短縮し、より重要な業務に集中できるのです。

処理の概要

「請求書の画像 → スプレッドシートのデータ」 という自動化の流れは、次のとおりです。

  1. 請求書をスマホで撮影(JPEGやPDFにする)
  2. Google Driveにアップロード
  3. GAS(Google Apps Script)を使ってOCR結果を取得
  4. 正規表現で「金額」「日付」など必要な情報を抽出
  5. スプレッドシートの所定の列に自動入力

ただし、この自動化には少しだけプログラミング(GAS)の知識が必要になります。ご安心ください、難しいものではありません。

機能ごとのGAS(Google Apps Script)コード

使用する機能ごとにGASのコードをご紹介します。

ステップ1. Google Drive OCRでテキスト化する

Google Drive に保存された画像をGoogleドキュメントに変換し、そのテキストを抽出します。
これで紙や画像データからも「読み取り可能なテキスト」として扱えるようになります。

Apps Scriptからこの機能を呼び出すコード例がこちらです。

/**
 * Google Drive OCRで画像ファイルをテキスト化する
 */
function ocrInvoice(file) {

  // ファイルをOCR処理します(Googleドキュメントに変換)
  const resource = {
    title: file.getName(),
    mimeType: MimeType.GOOGLE_DOCS
  };
  const options = {
    ocr: true,
    ocrLanguage: 'ja'
  };
  const doc = Drive.Files.create(
    resource, // 新しいドキュメントのメタデータ
    file.getBlob(), // 元の画像ファイルの中身 (Blob)
    options // OCR設定
  );
  const doc = Drive.Files.copy(resource, file.getId(), options);

  // 変換したGoogleドキュメントからテキストを取得します
  const text = DocumentApp.openById(doc.id).getBody().getText(); 

  // テキスト情報を返却します
  return text;
}

ステップ2. 正規表現で「金額」と「日付」を抽出

OCRで得られたテキストから、請求書でよく使われるパターンを探していきます。たとえば、次のようなルールです。

  • 金額 → 「¥」「¥」「,」「数字」を含む表記
  • 日付 → 「YYYY/MM/DD」「YYYY年MM月DD日」など

Apps Scriptでのサンプルコードは以下の通りです。

function extractInvoiceData(text) {
  var data = {};

  // 金額を抽出(例: ¥123,456)
  var amountMatch = text.match(/¥\s?[\d,]+/);
  if (amountMatch) {
    data.amount = amountMatch[0].replace(/[¥,\s]/g, '');
  }

  // 日付を抽出(例: 2025/09/02 や 2025年9月2日)
  var dateMatch = text.match(/(\d{4}[\/年]\d{1,2}[\/月]\d{1,2})/);
  if (dateMatch) {
    data.date = dateMatch[0]
      .replace(/[年月]/g, '/')
      .replace(/[日]/, '');
  }

  return data;
}

たとえば「ご請求金額:¥123,456」「請求日:2025年9月2日」といったOCR結果から、次のような形でデータ化できます。

  • 金額 → 123456
  • 日付 → 2025/9/2

ステップ3. スプレッドシートに自動転記

最後に、この抽出データをGoogleスプレッドシートへ転記します。毎回の作業を自動で記録できるようになります。

function saveToSheet(data) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('請求書一覧');
  sheet.appendRow([new Date(), data.date, data.amount]);
}

このようにすれば、 処理日付(ログ用)、OCRした日付(請求日)、 金額 が1行ずつ蓄積されていきます。

実際に試してみよう

次のような請求書を処理してみましょう。

GAS(Google Apps Script)サンプルコード

今回ご紹介するサンプルコードでは、Google ドライブに保存した請求書の画像をまとめて処理します。
指定したフォルダ内の画像ファイルを OCR にかけてテキスト化し、結果をスプレッドシートに自動で書き出します。
さらに、処理が完了した画像ファイルは「処理済みフォルダ」へ自動的に移動するので、どのファイルが終わっているのか一目で分かります。
請求書の明細情報(項目・数量・単価・金額など)もスプレッドシートに整理されて書き込まれるため、そのまま管理や確認に活用できます。

/**
 * 各種設定
 */
const SPREADSHEET_ID       = "YOUR_SPREADSHEET_ID";  //スプレッドシートのID
const SHEET_NAME           = "YOUR_SHEET_NAME";      // 請求書情報を書き込むスプレッドシートのシート名

const SOURCE_FOLDER_ID     = "YOUR_FOLDER_ID";       // 請求書画像を置くフォルダのフォルダID
const DOC_FOLDER_ID        = "YOUR_FOLDER_ID2 or ''";//GoogleDocファイルを出力するフォルダのID、空欄時はファイルは保存しない
const PROCESSED_FOLDER_ID  = "YOUR_FOLDER_ID3 or ''";//処理済みの請求書画像を移動させるフォルダのID、空欄時は移動しない
const SUPPORTED_MIME_TYPES = [MimeType.PNG, MimeType.JPEG, MimeType.GIF, MimeType.BMP, MimeType.PDF];

/**
 * カスタムメニューを追加
 */
function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu("請求書取込")
    .addItem("▼ 実行", "ocrInvoiceToSheet")
    .addToUi();
}

/**
 * 請求書画像をOCR処理し、情報を抽出してスプレッドシートに書き込む
 */
function ocrInvoiceToSheet() {

  const sourceFolder = DriveApp.getFolderById(SOURCE_FOLDER_ID);

  for (let mimeType of SUPPORTED_MIME_TYPES) {
    const files = sourceFolder.getFilesByType(mimeType);

    while (files.hasNext()) {
      const file = files.next();

      // OCR処理して、ドキュメントに変換、テキスト情報を取得
      const text = ocrInvoice(file);

      // 取得したテキスト情報を解析(正規表現等)して各項目の情報を抜き出す
      const data = extractInvoiceData(text);

      // シートに追記
      saveToSheet(data);

      // 後処理:処理が完了した画像ファイルを「processed」フォルダに移動します。
      if (PROCESSED_FOLDER_ID) {
        const processedFolder = DriveApp.getFolderById(PROCESSED_FOLDER_ID);
        file.moveTo(processedFolder)

      }
    }

  }

}

/**
 * Google Drive OCRで画像ファイルをテキスト化する
 */
function ocrInvoice(file) {
  // ファイルをOCR処理します(Googleドキュメントに変換)
  // ☆Drive Api v2 の場合
  // const resource = {
  //   title: file.getName()
  // };
  // const options = {
  //   "ocr": true,
  //   "ocrLanguage": "ja",
  // };
  // const doc = Drive.Files.copy(resource, file.getId(), options);

  // ☆Drive Api v3 の場合
  const resource = {
    title: file.getName(),
    mimeType: MimeType.GOOGLE_DOCS
  };
  const options = {
    ocr: true,
    ocrLanguage: 'ja'
  };
  const doc = Drive.Files.create(
    resource, // 新しいドキュメントのメタデータ
    file.getBlob(), // 元の画像ファイルの中身 (Blob)
    options // OCR設定
  );

  // 変換したGoogleドキュメントからテキストを取得します
  const text = DocumentApp.openById(doc.id).getBody().getText(); 

  // 後処理:作成したGoogleドキュメントを移動または削除します
  if ( DOC_FOLDER_ID ) {
    const docFolder = DriveApp.getFolderById(DOC_FOLDER_ID);
    // docをDOC_FOLDER_IDのフォルダに移動します。
    DriveApp.getFileById(doc.id).moveTo(docFolder);
  } else {
    // docを削除します
    DriveApp.getFileById(doc.id).setTrashed(true);
  }

  // テキスト情報を返却します
  return text;
}

/**
 * 正規表現で「金額」と「日付」を抽出
 */
function extractInvoiceData(text) {
  var data = {};

  // 1. 宛名の社名を抽出
  // 「ご担当:」の前にある社名を取得
  var recipientCompanyMatch = text.match(/^(.*?)\nご担当:/m);
  if (recipientCompanyMatch) {
    data.recipientCompany = recipientCompanyMatch[1].trim();
  }

  // 2. 宛名の担当者を抽出
  // 「ご担当:」と「様」の間にある名前を取得
  var recipientNameMatch = text.match(/ご担当:(.*?)様/);
  if (recipientNameMatch) {
    data.recipientName = recipientNameMatch[1].trim();
  }
  
  // 3. 合計金額を抽出
  var amountMatch = text.match(/¥\s?[\d,]+/);
  if (amountMatch) {
    data.amount = amountMatch[0].replace(/[¥,\s]/g, '');
  }

  // 4. 請求日付を抽出
  var dateMatch = text.match(/請求日:\s*(\d{4}[年\/\-]\d{1,2}[月\/\-]\d{1,2}日?)/);
  if (dateMatch) {
    data.date = dateMatch[1]
      .replace(/[\u200b\s]/g, '') // ゼロ幅スペースや空白を除去
      .replace(/[年月]/g, '/')
      .replace(/[日]/g, '');
  }

  // 6. 請求元の社名を抽出
  const claimantMatch = text.match(/^(.*)\n〒/m);
  if (claimantMatch) {
    data.claimant = claimantMatch[1];
  }

  // 7. 小計・消費税を抽出
  const subtotalMatch = text.match(/小計\s*\n.*\n(¥[\d,]+)/);
  if (subtotalMatch) {
    data.subtotal = subtotalMatch[1].replace(/[¥,\s]/g, '');
  }
  const taxMatch = text.match(/消費税額\s*\n.*\n(¥[\d,]+)/);
  if (taxMatch) {
    data.tax = taxMatch[1].replace(/[¥,\s]/g, '');
  }

  // 8. 明細情報を抽出
  // 明細表の開始と終了を特定し、その間のテキストを処理
  var lines = text.split('\n');
  var startLineIndex = -1;
  var endLineIndex = -1;
  var startLineIndex2 = -1;
  var endLineIndex2 = -1;

  // 明細表の開始行(No., 項目)を特定
  for (var i = 0; i < lines.length; i++) {
    if (lines[i] && lines[i].includes('No.') && lines[i].includes('項目')) {
      startLineIndex = i + 1;
      break;
    }
  }
  // 明細表の終了行(No., 項目)を特定
  for (var i = startLineIndex; i < lines.length; i++) {
    if (lines[i] && lines[i].includes('数量')) {
      endLineIndex = i-1;
      break;
    }
  }

  // 明細表の開始行(数量, 単価, 金額)を特定
  for (var i = startLineIndex; i < lines.length; i++) {
    if (lines[i] && lines[i+1] && lines[i+2] 
        && lines[i].includes('数量') && lines[i+1].includes('単価') && lines[i+2].includes('金額')) {
      startLineIndex2 = i+2 +1;
      break;
    }
  }
  // 明細表の終了行(数量, 単価, 金額)を特定
  for (var i = startLineIndex2; i < lines.length; i++) {
    if (lines[i] && lines[i].includes('小計')) {
      endLineIndex2 = i-1;
      break;
    }
  }
  data.details = [];
  if (startLineIndex !== -1 && endLineIndex !== -1) {
    for (var i = startLineIndex; i < endLineIndex; i++) {
      var no = lines[i].trim();
      i++;
      if (!lines[i]) {
        break;
      }
      var item = lines[i].trim();
      if (/^\d+$/.test(item)) {
        break;
      }
      data.details.push({
        no: no, 
        item: item, 
        quantity: "",
        unitPrice: "",
        price: "",
      });
    }
  }
  if (startLineIndex2 !== -1 && endLineIndex2 !== -1) {
    var detailsRow = 0;
    for (var i = startLineIndex2; i < endLineIndex2; i++) {
      var quantity = lines[i].trim();
      i++;
      if (!lines[i]) {
        break;
      }
      var unitPrice = lines[i].trim().replace(/[¥,\s]/g, '');
      i++;
      if (!lines[i]) {
        break;
      }
      var price = lines[i].trim().replace(/[¥,\s]/g, '');
      if ( !data.details[detailsRow] ) {
        data.details.push({
          no: "", 
          item: "", 
          quantity: "",
          unitPrice: "",
          price: "",
        });
      }
      data.details[detailsRow].quantity = quantity;
      data.details[detailsRow].unitPrice = unitPrice;
      data.details[detailsRow].price = price;
      detailsRow++;
    }
  }
  return data;
}

/**
 * スプレッドシートに自動転記
 */
function saveToSheet(data) {
  const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SHEET_NAME);

  // 請求ヘッダ情報
  sheet.appendRow([
    new Date(), 
    data.recipientCompany ?? "",//宛名
    data.recipientName ?? "",   //宛名・担当者
    data.claimant ?? "",        //請求者
    data.date ?? "",            //請求日
    data.subtotal ?? "",        //小計
    data.tax ?? "",             //消費税
    data.amount ?? "",          //合計金額
  ]);
  // 請求明細情報
  if (data.details) {
    for (const detail of data.details) {
      sheet.appendRow([
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        detail.item ?? "",        //明細情報・項目
        detail.quantity ?? "",    //明細情報・数量
        detail.unitPrice ?? "",   //明細情報・単価
        detail.price ?? "",       //明細情報・金額
      ]);
    }
  }
}

手順

1. 事前準備

  1. Google ドライブに「請求書画像」フォルダと「処理済み」フォルダを作成します。
  2. Google スプレッドシートを新規作成します。
    ・シート名を「請求データ」など分かりやすい名前に変更
    ・1行目に列タイトル(作業日、宛名、宛名・担当名、請求元、請求日、小計、消費税、合計金額、明細情報・項目、明細情報・数量、明細情報・単価、明細情報・金額)を入力しておきます

2. GAS(Google Apps Script)の設定

  1. スプレッドシートのメニューから 拡張機能 → Apps Script を開きます。
  2. 上述したサンプルコードを貼り付け、スプレッドシートIDやシート名、各フォルダIDを自分の環境に合わせて編集します。
  3. Advanced Drive Service を有効化します。
    ・エディタ左側のメニューで「サービス」を選択
    ・「+ 新しいサービスを追加」をクリック
    ・一覧から「Drive API」を探して追加
    ・バージョンが「v3」であることを確認
    ・追加後は必ずプロジェクトを保存してください(保存しないと反映されません)

3. 実行準備

  1. 請求書の画像ファイルを、先ほど作成した「画像保存用フォルダ」にアップロードします。

4. OCRの実行

  1. スプレッドシートを開くと、新しく「請求書取込」というメニューが追加されています。
  2. メニューから 請求書取込 → 実行 をクリックすると、OCR処理が開始されます。
  3. 結果がスプレッドシートに自動で反映されます。

処理実行すると、スプレッドシートには請求書のデータが自動入力されました。


なお、今回サンプルで使用した請求書画像をOCR処理すると、次のようなGoogleドキュメントが作成されました。

請求書サンプル画像をOCR処理して作成されたGoogleドキュメント
請求書のサンプル画像をOCR処理して作成されたGoogleドキュメント(PDFに変換しています)

うまく活用するポイント

金額の抽出

金額は「¥マーク」や「カンマ」込みで抽出されるので、コード内でクリーニングしましょう。

フォーマットがバラバラな請求書

OCRで取得したテキストに合わせて、正規表現やキーワードで補正しましょう。

OCRは100%正確ではない

OCRには限界もあります。
たとえば「手書き文字は認識精度が低い」「レイアウトが複雑な請求書は想定通りに抽出されないこともある」といった課題があります。
抽出結果を人が最終確認する仕組みを残しましょう。
とはいえ「毎回ゼロから入力するよりは格段に効率的」なのは間違いありません。

発展:さらに精度を高める方法

Cloud Vision APIを使う

有料ですが精度が高く、複雑なレイアウトの請求書も対応しやすいです。
※Cloud Vision API に関しては、Google Cloud Vision AIの公式サイトでご確認ください。

Googleフォーム連携

「請求書の画像をアップロード」するフォームを作れば、簡単に画像をGoogole Driveに保存できます。

まとめ

  • Google Drive OCRを使えば、紙の請求書からスプレッドシートへの入力を自動化できる
  • 正規表現と組み合わせることで「日付」「金額」など実務に必要なデータを抽出可能
  • 将来的にはCloud Vision APIやGoogleフォーム連携でさらに業務効率化が進む

これにより、手入力によるミスを減らし、処理時間を大幅に短縮できます。
小規模な業務フローでもすぐに導入可能なので、「請求書入力を少しでもラクにしたい」と思っている方は、まずGoogle Drive OCRから試してみるのがおすすめです。

弊社 株式会社システムエンジニアリング では、ご相談や実装サポートも行っております。
「うちの請求書フォーマットでも自動化できる?」「使っている会計ソフトに合わせたデータ化できる?」という方は、お気軽にお問い合わせください。

関連記事

スプレッドシートにデータが入力できたら、内容のチェックをAIに任せてみませんか?チェック業務の効率化につながります。次の記事で詳しくご紹介していますので、ぜひご覧ください。

この記事は役に立ちましたか?

参考になりましたら、下のボタンで教えてください。

コメント

この記事へのコメントはありません。

PAGE TOP
ログイン