みやもとメモ

「Notion」「Google Apps Script」「ブログカスタマイズ」などについて書いていきます。

目次
目次

【GAS】OCR処理された複数のGoogleドキュメントを結合する(マージする)

この記事をシェアする

今回はGAS(Google Apps Script)に関して書いていきます。

以前もGASに関する記事を書いています(以下リンク)。

miya-moto-memo.hatenablog.com

上記の記事で、指定フォルダ内の画像ファイルをまとめてOCR処理するように対応しました。
そこに追加対応をしてみました。

例えば画像ファイルが3つあった場合、GASを実行するとOCR処理されたGoogleドキュメントが新たに3つ作成されます。
このOCR処理されたGoogleドキュメント3つをマージする処理を追加してみました。

Googleドキュメントを1つ1つ開くのも面倒なので、1つのGoogleドキュメントにまとめてしまおう」という対応です。

それでは本題へ。

やりたいこと

記事の冒頭でも触れましたが、以下記事の追加対応となります。

miya-moto-memo.hatenablog.com

上記記事の段階では、画像ファイルを基にOCR処理されたGoogleドキュメントが作成されます。

画像ファイルを基にOCR処理されたGoogleドキュメントが作成される

上記の画像を見てもらえれば分かる通り、画像ファイルの数だけGoogleドキュメントが作成されます。
OCR処理されたGoogleドキュメントを1つ1つ開くのも面倒なので、作成されたGoogleドキュメントを1つにまとめてみます。

プログラム

ということで、プログラムです。

// フォルダID
const FOLDER_ID = PropertiesService.getScriptProperties().getProperty('FOLDER_ID');

/**
 * メイン処理
 */
function main() {
  // OCR対象のファイルをArrayで取得
  const files = getOcrTargetFileArray(FOLDER_ID);
  for (const file of files) {
    // 画像ファイルを基にGoogleドキュメントを作成
    const doc = createDocFromImg(file.id, file.title);
    // Googleドキュメントの中身を調整
    adjustFileContent(doc.id);
    // ログ出力
    console.log(file.title);
  }
  // OCRされたGoogleドキュメントをマージ
  createMergeDoc(); // ★追加
}

/**
 * OCR対象のファイルをArrayで取得
 * ・フォルダID配下のファイルを取得
 * ※画像ファイル以外は除外
 */
function getOcrTargetFileArray(id) {
  const retArray = [];
  const folder = DriveApp.getFolderById(id);
  const files = folder.getFiles();
  while (files.hasNext()) {
    const file = files.next();
    if (file.getMimeType().indexOf("image") === -1) continue;
    retArray.push({
      id: file.getId(),
      title: file.getName(),
    });
  }
  return retArray;
}

/**
 * 画像ファイルを基にGoogleドキュメントを作成
 * ※copyするとGoogleドキュメントが作成される
 * ※copy時にOCRする
 */
function createDocFromImg(id, title) {
  const resource = {
    title: "OCR_" + title,
  };
  const option = {
    "ocr": true,
    "ocrLanguage": "ja",
  }
  return Drive.Files.copy(resource, id, option);
}

/**
 * Googleドキュメントの中身を調整
 * ・文字サイズを10にする
 * ・文字色を黒にする
 * ・半角スペースを除去する
 */
function adjustFileContent(id) {
  const body = DocumentApp.openById(id).getBody();
  body.setFontSize(10);
  body.setForegroundColor("#111111");
  const replaceText = body.getText().replaceAll(" ", "");;
  body.setText(replaceText);
}

/**
 * ★追加
 * OCRされたGoogleドキュメントをマージ
 */
function createMergeDoc() {
  // マージ用のGoogleドキュメントを作成
  const mergeDoc = DocumentApp.create('MERGE_OCR');
  // マージ対象のファイルをArrayで取得
  const mergeFiles = getMergeTargetFileArray(FOLDER_ID);
  for (const file of mergeFiles) {
    // OCRされたGoogleドキュメントをマージしていく
    const doc = DocumentApp.openById(file.id);
    mergeOcrDoc(mergeDoc, doc);
    // ログ出力
    console.log(file.title);
  }
  // マージ用のGoogleドキュメントを移動
  const mergeFile = DriveApp.getFileById(mergeDoc.getId());
  const mergeFolder = DriveApp.getFolderById(FOLDER_ID);
  mergeFile.moveTo(mergeFolder);
  // ログ出力
  console.log(mergeFile.getName());
}

/**
 * ★追加
 * マージ対象のファイルをArrayで取得
 * ・フォルダID配下のファイルを取得
 * ・取得後、ファイル名の昇順でソート
 * ※ファイル名に"OCR_"を含むものが対象
 */
function getMergeTargetFileArray(id) {
  const retArray = [];
  const folder = DriveApp.getFolderById(id);
  const files = folder.getFiles();
  while (files.hasNext()) {
    const file = files.next();
    if (file.getName().indexOf("OCR_") === -1) continue;
    retArray.push({
      id: file.getId(),
      title: file.getName(),
    });
  }
  retArray.sort((a,b) => {
    return a.title > b.title ? 1 : -1;
  });
  return retArray;
}

/**
 * ★追加
 * マージ用のGoogleドキュメントに1ファイルずつ追記していく
 * ・画像
 * ・テキスト
 * ・改ページ
 */
function mergeOcrDoc(mergeDoc, doc) {
  const mergeBody = mergeDoc.getBody();
  const docBody = doc.getBody();
  mergeBody.appendImage(docBody.getImages()[0].copy());
  mergeBody.appendParagraph(docBody.getText());
  mergeBody.appendPageBreak();
}

なお、”FOLDER_ID”の部分はスクリプトプロパティから取得するように変更しています。
スクリプトプロパティに関しては以下記事で詳しく書いています。
こちらも良ければぜひ。

miya-moto-memo.hatenablog.com

また、前回の記事との差分を分かりやすくするため、プログラムコメントに「★追加」と書いています。
追加した処理を挙げると、

  • createMergeDoc
  • getMergeTargetFileArray
  • mergeOcrDoc

の3つです。

プログラム実行

上記のプログラムを実行すると、マージされたGoogleドキュメントが作成されます。

プログラム実行
3つのGoogleドキュメントがマージされる

マージされたファイルの中身は以下のような感じです。

マージされたファイル(1ファイル目)(1ページ目)
マージされたファイル(2ファイル目)(2ページ目)
マージされたファイル(3ファイル目)(3ページ目)

3ファイル分がマージされています。

プログラムのポイント

プログラムの中からポイントとなる部分をピックアップして説明していきます。

マージ対象のリストをファイル名の昇順でソート

retArray.sort((a,b) => {
  return a.title > b.title ? 1 : -1;
});

マージする前に、マージ対象のリストをソートさせています。
ファイルをどの順番でマージさせるか、一定の規則を持たせたいためです。
ちなみにソートキーは「ファイル名の昇順」です。

参考リンクは以下です。
GASはJavaScriptベースとのことで、JavaScriptのリンクとなります。
developer.mozilla.orgqiita.com

マージ用のGoogleドキュメントを新規作成

// マージ用のGoogleドキュメントを作成
const mergeDoc = DocumentApp.create('MERGE_OCR');

// マージ用のGoogleドキュメントを移動
const mergeFile = DriveApp.getFileById(mergeDoc.getId());
const mergeFolder = DriveApp.getFolderById(FOLDER_ID);
mergeFile.moveTo(mergeFolder);

DocumentApp.create
「DocumentApp.create」でGoogleドキュメントを新規作成できます。
ただ、作成場所がルートフォルダになってしまうようです。
画像ファイルをアップロードしたフォルダと同じ場所に配置したいので、「File.moveTo」で移動させます(後述)。
developers.google.com


DriveApp.getFileById
「DriveApp.getFileById」でマージ用Googleドキュメントのファイル情報を取得します。
※「DocumentApp.create」で返却されるのは”Document”、「DriveApp.getFileById」で返却されるのは”File”です。
※今回必要なのは”File”です。
developers.google.com


DriveApp.getFolderById
「DriveApp.getFolderById」でフォルダ情報を取得します。
developers.google.com


File.moveTo
「File.moveTo」でファイルを指定フォルダに移動します。
developers.google.com

Googleドキュメントを新規作成する時に、どのフォルダに作成するか指定できたら良いのですが、どうやら指定できないようです。
もしかしたらもっとシンプルな方法があるのかもしれませんが、今回はこういった方法としました。

どうマージしているか

/**
 * ★追加
 * マージ用のGoogleドキュメントに1ファイルずつ追記していく
 * ・画像
 * ・テキスト
 * ・改ページ
 */
function mergeOcrDoc(mergeDoc, doc) {
  const mergeBody = mergeDoc.getBody();
  const docBody = doc.getBody();
  mergeBody.appendImage(docBody.getImages()[0].copy());
  mergeBody.appendParagraph(docBody.getText());
  mergeBody.appendPageBreak();
}

マージ元のGoogleドキュメント(docBody)の内容を丸ごと取り出して、マージ用のGoogleドキュメント(mergeBody)に追記していきたかったのですが、それらしい機能がありませんでした。

色々と調べてみたところ、Googleドキュメントの「画像」を取り出す機能、「テキスト」を取り出す機能がそれぞれありました。
なので、別々に取り出して追記しています。

「画像」と「テキスト」

Body.getImages
「Body.getImages」でGoogleドキュメント内の画像を取得します。
※docBodyの画像を取得
developers.google.com

画像は1つしかないはずなので、”[0]”で決め打ちしています。

また、”copy”しないとエラーになってしまうようでした。
ちょっと謎は残りますが”copy”しています。


Body.appendImage
「Body.appendImage」でGoogleドキュメントに画像ファイルを追記します。
※mergeBodyに画像を追記
developers.google.com


Body.getText
「Body.getText」でGoogleドキュメント内のテキストを取得します。
※docBodyのテキストを取得
developers.google.com


Body.appendParagraph
「Body.appendImage」でGoogleドキュメントにテキストを追記します。
※mergeBodyにテキストを追記
developers.google.com


Body.appendPageBreak
「Body.appendPageBreak」で改ページできます。
複数のファイルをマージするわけですが、各ファイルの区切りとして改ページしています。
developers.google.com

おわりに

ということで、「【GAS】複数のGoogleドキュメントを結合する(マージする)」に関してアレコレ書いてみました。

GoogleドライブでOCR処理している人がどのくらい居るのか分かりませんが、少なくとも自分は前回の対応と今回の対応でOCR処理がラクになりました。

この記事が参考になれば幸いです。

関連記事

GAS(Google Apps Script)に関してはいくつか記事にしています。
気になる記事があればぜひ。

GASの活用事例


GASを活用してGoogle DriveでのOCR処理を効率化 - 派生記事

TOPへ戻る HOMEへ