「毎月届く請求書を、手入力でExcelや会計ソフトに転記している」・・・そんな作業に悩まされていませんか?
紙やPDFで受け取った請求書から金額や日付を探し出し、スプレッドシートに入力するのは地味に時間がかかります。さらに転記ミスのリスクも避けられません。
そこで今回は、紙の請求書の画像から自動でデータを抽出し、スプレッドシートに入力する方法をご紹介します。使うのは、Google Workspaceに標準で備わっている Google Drive OCR(文字認識) 機能です。追加費用は不要で、すぐに試せるのが魅力です。
目次
Google Drive OCRとは?
Google Driveにアップロードした画像やPDFファイルから、自動的に文字を読み取り、テキストデータとしてGoogle ドキュメントを生成する機能です。
例えば、スキャンした請求書やスマホで撮影した紙の請求書をアップロードするだけで、中身の文字をテキストとして取得できます。
OCRで請求書から何ができるのか
- 請求日や支払期日の抽出
- 金額(合計・税額)の抽出
- 顧客名や品目の取得
もちろん完璧ではありませんが、ゼロから手入力するよりも大幅に工数を削減できます。
これらの機能を使えば、毎日忙しい経理担当者の作業時間を劇的に短縮し、より重要な業務に集中できるのです。
処理の概要
「請求書の画像 → スプレッドシートのデータ」 という自動化の流れは、次のとおりです。
- 請求書をスマホで撮影(JPEGやPDFにする)
- Google Driveにアップロード
- GAS(Google Apps Script)を使ってOCR結果を取得
- 正規表現で「金額」「日付」など必要な情報を抽出
- スプレッドシートの所定の列に自動入力
ただし、この自動化には少しだけプログラミング(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. 事前準備
- Google ドライブに「請求書画像」フォルダと「処理済み」フォルダを作成します。
- Google スプレッドシートを新規作成します。
・シート名を「請求データ」など分かりやすい名前に変更
・1行目に列タイトル(作業日、宛名、宛名・担当名、請求元、請求日、小計、消費税、合計金額、明細情報・項目、明細情報・数量、明細情報・単価、明細情報・金額)を入力しておきます
2. GAS(Google Apps Script)の設定
- スプレッドシートのメニューから 拡張機能 → Apps Script を開きます。
- 上述したサンプルコードを貼り付け、スプレッドシートIDやシート名、各フォルダIDを自分の環境に合わせて編集します。
- Advanced Drive Service を有効化します。
・エディタ左側のメニューで「サービス」を選択
・「+ 新しいサービスを追加」をクリック
・一覧から「Drive API」を探して追加
・バージョンが「v3」であることを確認
・追加後は必ずプロジェクトを保存してください(保存しないと反映されません)
3. 実行準備
- 請求書の画像ファイルを、先ほど作成した「画像保存用フォルダ」にアップロードします。
うまく活用するポイント
金額の抽出
金額は「¥マーク」や「カンマ」込みで抽出されるので、コード内でクリーニングしましょう。
フォーマットがバラバラな請求書
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から試してみるのがおすすめです。
弊社 株式会社システムエンジニアリング では、ご相談や実装サポートも行っております。
「うちの請求書フォーマットでも自動化できる?」「使っている会計ソフトに合わせたデータ化できる?」という方は、お気軽にお問い合わせください。
コメント