OCR技術とGASで名刺データ化をスムーズに!スプレッドシート入力の手間を削減
- 手動での名刺情報の入力に時間がかかっている方
- 名刺データ入力を自動化して業務を効率化したい方
紙の名刺が増えてきて管理が大変になることありませんか?
ファイリングして管理するにもスペースが必要だったり、必要な時に名刺を探し出すのも手間がかかったりします。
そのため、名刺をデータ化すれば管理しやすくなりますが、手作業で入力となると時間がかかってしまいます。
そんなデータ化の手間をなくしたい時に役立つのがGoogle Apps Script(GAS)です。
GoogleにはOCR機能(画像から文字を読み取る技術)を使えるツールとしてCloud Vision APIがあり、GASと組み合わせることで画像から文字情報を抽出することが可能です。
この記事では、GASとGoogle Cloud Vision APIを使って、名刺の情報を自動でスプレッドシートに入力する方法をご紹介します。
なお、GAS実行の事前準備として Google Cloud Vision APIキー が必要となります。
APIキーの取得方法はこちらの記事でご説明します。
完成イメージ
- 名刺画像をGoogle Driveの「名刺」フォルダにアップロード
- GASを実行して、名刺画像からテキストを抽出し、スプレッドシートに転記
- 転記済みの名刺画像ファイルは「登録済み」フォルダに移動 ←今回の記事ではここまで
- ChatGPT APIを使って、各項目(会社名、部署名、氏名など)にデータを振り分け。 ←別記事にてご説明
今回の例では、Google Driveにアップロードした名刺画像から、GASとGoogle Cloud Vision APIで画像内の文字を読み取り、各項目をスプレッドシートに整理して転記する方法となります。
今回の記事では、名刺画像を取り込んでスプレッドシートに転記するところまでをご紹介します。
転記後のデータを整理するためには、さらにChatGPT APIを使うことで各項目(会社名、部署名、氏名など)の列にデータを自動で振り分けられるようになります。
手順
Google Drive に名刺画像をアップロード
Google Drive内に、名刺画像を保存するためのフォルダを作成します。
(例:「名刺」フォルダ)
作成した名刺フォルダの中に「登録済み」フォルダを作成します。
スプレッドシートへの転記が終わった画像ファイルの移動先にします。
作成した名刺フォルダの中に名刺画像をアップロードします。
(JPEG、PDFどちらも可)
GASスクリプトの作成・実行
名刺のデータを保存するためのスプレッドシートを作成します。
スプレッドシートの見出しには「会社名」「部署名」「役職」「氏名」「電話番号」など、名刺から抽出する情報に対応する項目を設定します。
また、今回の例ではシート名を「名刺管理」としてGAS実行の際に参照します。
列の記入例
A列 | 会社名 |
B列 | 部署名 |
C列 | 役職 |
D列 | 氏名 |
E列 | 電話番号 |
F列 | 携帯番号 |
G列 | FAX番号 |
H列 | メールアドレス |
I列 | 会社住所 |
J列 | ウェブサイト |
K列 | SNS情報 |
L列 | 備考 |
Googleスプレッドシートを開き、メニューの「拡張機能」から「Apps Script」をクリックしてGASエディタを開きます。
前回の記事で取得したAPIキーを使用して、スクリプトプロパティに設定します。
function myFunction(){
}
が最初から入っているため、消去して以下のスクリプトを貼り付けます。
function processBusinessCards() {
const folderId = "名刺フォルダのIDをここに入れる";
const folder = DriveApp.getFolderById(folderId);
const processedFolder = folder.getFoldersByName("登録済み").next();
const files = folder.getFiles();
const visionApiKey = PropertiesService.getScriptProperties().getProperty("VISION_API_KEY");
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート名をここに入れる");
Logger.log("Starting to process files in folder: " + folderId);
while (files.hasNext()) {
const file = files.next();
const imageBlob = file.getBlob();
Logger.log("Processing file: " + file.getName());
// Google Vision APIを呼び出してOCR処理
const ocrText = callGoogleVisionApi(visionApiKey, imageBlob);
// OCR結果をスプレッドシートに転記
if (ocrText) {
Logger.log("OCR Text: " + ocrText);
appendToSheet(sheet, ocrText);
// 処理後に画像を"登録済み"フォルダに移動
processedFolder.addFile(file);
folder.removeFile(file);
Logger.log("File moved to processed folder: " + file.getName());
} else {
Logger.log("No text detected for file: " + file.getName());
}
}
Logger.log("Processing completed for all files in folder: " + folderId);
}
function callGoogleVisionApi(apiKey, imageBlob) {
const url = `https://vision.googleapis.com/v1/images:annotate?key=${apiKey}`;
const requestBody = {
"requests": [
{
"image": {
"content": Utilities.base64Encode(imageBlob.getBytes())
},
"features": [
{
"type": "TEXT_DETECTION"
}
]
}
]
};
const options = {
"method": "post",
"contentType": "application/json",
"payload": JSON.stringify(requestBody)
};
try {
const response = UrlFetchApp.fetch(url, options);
const json = JSON.parse(response.getContentText());
Logger.log("Vision API response: " + response.getContentText());
const textAnnotations = json.responses[0].textAnnotations;
if (textAnnotations && textAnnotations.length > 0) {
return textAnnotations[0].description;
}
} catch (e) {
Logger.log("Error during Vision API call: " + e.message);
}
return null;
}
function appendToSheet(sheet, ocrText) {
const rows = ocrText.split('\n');
const newRow = Array(12).fill(""); // 12列分の空の配列を作成
// OCR結果全体をシートに追加(デバッグ用)
sheet.appendRow([ocrText]);
// スプレッドシートの項目に対応するデータを抽出
rows.forEach(row => {
if (row.includes("氏名")) {
newRow[0] = row.split(":")[1]?.trim() || "";
} else if (row.includes("会社名")) {
newRow[1] = row.split(":")[1]?.trim() || "";
}
// 他の項目も必要に応じて追加
});
// 新しい行をスプレッドシートに追加(空でない場合のみ)
if (newRow.some(cell => cell !== "")) {
sheet.appendRow(newRow);
}
}
スクリプトの説明
processBusinessCards()
関数-
この関数が、名刺の画像をGoogle Driveから取り出し、Google Vision APIを利用してテキストを抽出し、それをGoogleスプレッドシートに転記する一連の流れを制御します。
function processBusinessCards() { const folderId = "名刺フォルダのIDをここに入れる"; const folder = DriveApp.getFolderById(folderId);
folderId
: 名刺画像が保存されているフォルダのIDを指定します。- DriveのURLからIDを取得して入力します。
folder = DriveApp.getFolderById(folderId)
:DriveApp
を使用して、指定したフォルダを取得します。
const processedFolder = folder.getFoldersByName("登録済み").next();
processedFolder
: 「登録済み」という名前のフォルダを取得します。- このフォルダには処理が完了した名刺ファイルを保存します。
next()
:getFoldersByName()
はIteratorを返すため、next()
を使って最初のフォルダを取得します。
const files = folder.getFiles();
files = folder.getFiles()
: 処理するフォルダ内に含まれているすべてのファイルを取得します。- このファイルには名刺の画像が含まれています。
const visionApiKey = PropertiesService.getScriptProperties().getProperty("VISION_API_KEY");
visionApiKey
: スクリプトのプロパティに保存してあるGoogle Vision APIのAPIキーを取得します。このキーは、Google Vision APIを呼び出す際に必要です。
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート名をここに入れる");
sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(...)
: Googleスプレッドシートから指定された名前のシートを取得し、データを入力します。(例:名刺管理)
while (files.hasNext()) { const file = files.next(); const imageBlob = file.getBlob();
while (files.hasNext())
:files
オブジェクトにファイルが存在する限り、繰り返し処理を行います。file = files.next()
: 次のファイルを取得します。imageBlob = file.getBlob()
: ファイルをBlob形式に変換します。Blob形式はAPIにデータを送信するためのバイナリデータです。
const ocrText = callGoogleVisionApi(visionApiKey, imageBlob);
ocrText = callGoogleVisionApi(...)
:callGoogleVisionApi
関数を呼び出し、画像からテキスト情報を取得します。
if (ocrText) { appendToSheet(sheet, ocrText); processedFolder.addFile(file); folder.removeFile(file); }
if (ocrText)
: OCR処理が成功し、テキストが検出された場合のみ実行します。appendToSheet(sheet, ocrText)
: 抽出したテキストをシートに追加します。processedFolder.addFile(file)
とfolder.removeFile(file)
: 処理が終わったファイルを「登録済み」フォルダに移動します。
callGoogleVisionApi(apiKey, imageBlob)
関数-
この関数は、Google Vision APIを使って画像からテキストを抽出する部分です。
function callGoogleVisionApi(apiKey, imageBlob) { const url = `https://vision.googleapis.com/v1/images:annotate?key=${apiKey}`;
url
: Google Vision APIのエンドポイントURLです。APIキーを含めてリクエストを送信します。
const requestBody = { "requests": [ { "image": { "content": Utilities.base64Encode(imageBlob.getBytes()) }, "features": [ { "type": "TEXT_DETECTION" } ] } ] };
requestBody
: Vision APIへのリクエストボディです。"image"
:imageBlob
をBase64でエンコードして含めます。画像データをAPIで扱える形式に変換します。"features"
: 画像から検出する機能を指定します。この場合は"TEXT_DETECTION"
を使ってテキストを抽出します。
const options = { "method": "post", "contentType": "application/json", "payload": JSON.stringify(requestBody) };
options
:UrlFetchApp.fetch()
メソッドに渡すリクエストの設定です。"method"
:POST
メソッドを使います。"contentType"
: リクエストのコンテンツタイプはapplication/json
です。"payload"
: リクエストボディをJSONに変換します。
try { const response = UrlFetchApp.fetch(url, options); const json = JSON.parse(response.getContentText()); const textAnnotations = json.responses[0].textAnnotations; if (textAnnotations && textAnnotations.length > 0) { return textAnnotations[0].description; } } catch (e) { Logger.log("Error during Vision API call: " + e.message); } return null; }
try-catch
ブロックでAPIリクエストを行います。UrlFetchApp.fetch(url, options)
: Vision APIにリクエストを送信し、結果を取得します。JSON.parse(response.getContentText())
: レスポンスをJSON形式に変換します。textAnnotations[0].description
: テキスト認識の結果から最初のエントリを取得し、テキストを返します。- エラーが発生した場合は、
catch
ブロックでエラーメッセージをログに記録します。
appendToSheet(sheet, ocrText)
関数-
この関数は、OCRの結果をGoogleスプレッドシートに書き込む部分です。
function appendToSheet(sheet, ocrText) { const rows = ocrText.split('\n'); const newRow = Array(12).fill(""); // 12列分の空の配列を作成
rows = ocrText.split('\n')
: OCRで取得したテキストを改行で分割し、配列に格納します。newRow = Array(12).fill("")
: スプレッドシートの各列に対応する空の配列を作成します(12列分)。
sheet.appendRow([ocrText]);
sheet.appendRow([ocrText])
: 抽出したテキスト全体をデバッグ用にスプレッドシートに追加します。後から確認がしやすいように全体を1行に保存します。
rows.forEach(row => { if (row.includes("氏名")) { newRow[0] = row.split(":")[1]?.trim() || ""; } else if (row.includes("会社名")) { newRow[1] = row.split(":")[1]?.trim() || ""; } // 他の項目も必要に応じて追加 });
rows.forEach(row => {...})
: 各行についてキーワード(例: “氏名”, “会社名”)を探し、データを抽出します。row.split(":")[1]?.trim() || ""
: コロンを区切り文字として分割し、必要な情報を取得します。?.
は安全に値を取り出すためのオプショナルチェーンで、見つからない場合は空の文字列を返します。
if (newRow.some(cell => cell !== "")) { sheet.appendRow(newRow); } }
newRow.some(cell => cell !== "")
:newRow
の中に空でない値が1つでもあれば、appendRow()
で新しい行としてスプレッドシートに追加します。
スクリプト2行目のconst folderId = "名刺フォルダのIDをここに入れる";
の部分に、名刺画像が保存されているフォルダのIDを入力します。
Google Drive内の対象フォルダを開きます。(例:名刺フォルダ)
フォルダを開いた状態で、ブラウザのアドレスバーに表示されているURLを確認します。
このURLのうち、「folders/
」の後に続く一連の英数字がフォルダIDです。
スクリプト7行目のconst sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート名をここに入れる");
の部分に、スプレッドシートのシート名を入力します。(例:名刺管理)
コードを書いたら、名前をつけて保存します。
(例:「名刺データ入力」)
スクリプトを実行して、名刺画像からスプレッドシートに情報を転記します。
初めてそのスクリプトを実行する場合は権限の確認が必要です。
そのため、『権限を確認』を押します。
許可の詳細手順
「詳細」をクリックします。
「無題のプロジェクト(安全ではないページ)に移動」をクリックします。
「許可」をクリックします。
今回のスクリプトでは名刺の情報がA列に転記されます。
このA列に入った名刺の情報を、次の記事でChatGPT APIを使って各項目に分けていきます。
また、読み取った名刺の画像は「登録済み」フォルダに移動されます。
スクリプト実行時の注意事項
Google Apps Script(GAS)は最大で6分間実行できますが、それを超えるとタイムアウトエラーが発生します。
そのため、一度に大量の名刺画像を処理するよりも、まずは10〜15枚程度で処理にどのくらい時間がかかるか確認するとスムーズです。
まとめ
今回は、Google Apps Script(GAS)とGoogle Vision APIを利用して名刺データをスプレッドシートに自動で入力する方法を紹介しました。
これにより、名刺データの入力作業の手間を減らすことができます。
次の記事では、取得した名刺情報のテキストをChatGPT APIを活用して各項目に振り分ける方法をご紹介します。
弊社では、Google Apps Script(GAS)を活用した業務効率化のサポートを提供しております。
GASのカスタマイズやエラー対応にお困りの際は、ぜひお気軽にご相談ください。
また、ITツールの導入支援やIT導入補助金の申請サポートも行っております。
貴方の業務改善を全力でサポートいたします。
コメント