NotebookLM用向け複数のPDF→Doc変換をSpreadSheet上で管理する

NotebookLM用向け複数のPDF→Doc変換をSpreadSheet上で管理する

NotebookLM用同期更新向けのPDF→Doc変換を複数ファイル対象にする場合、SpreadSheet上での管理とファイル生成時のエラー処理が肝になってきます。GoogleDrive特有の仕様を踏まえつつやってみました。
Clock Icon2025.04.02

NotebookLM向けに複数のPDFをDocに変換し始めると、色々融通効かせたい点がでてきます。

GASでGoogle Drive内にある複数のPDFをDocに変換しつつ、アクセスしやすいようにURLを管理してみました。

複数のPDFをDocに変換する

OCR処理にて行います。大筋は以下の記事通り。

先の記事による処理は複数回の実行や途中で処理が止まった場合に不要なファイルが残ったりします。今回の手続きはそれら起こり得る問題点解消も含めたものとなります。

  1. PDFから一時Docファイルに変換する
  2. NotebookLM用Docファイルを開く(なければ作成する)
  3. 一時Docファイル内のテキストをNotebookLM用Docに写す
  4. 一時Docファイルを削除する
const tempName = '本文取得用一時ファイル';
const directory_id = '...................';
const directory_name = 'NotebookLM';
const spreadsheet = SpreadsheetApp.openById("...................");

function pdfToDocsWithBuiltInOCR(source) {
  Logger.log("変換対象:" + source + ".pdf")
  let fileId = getFileIdByName(source + ".pdf")
  let lmdoc = null
  let docs = null
  try {
    const resource = { title: tempName, parents: [{id: directory_id}]};
    const options = {
      ocr: true,
      ocrLanguage: "ja",
      fields: "id,title,parents",
      supportsTeamDrives: true, 
    };
    const tempFile = Drive.Files.copy(resource, fileId, options);
    docs = DocumentApp.openById(tempFile.getId());

    var files = DriveApp.getFilesByName(source);
    if (!files.hasNext() || files.next().getParents().next().getName() != directory_name) {
      Logger.log(source + "の作成を開始します。")
      let doc = DocumentApp.create(source);
      let file = DriveApp.getFileById(doc.getId());
      let destFolder = DriveApp.getFolderById(directory_id);
      file.moveTo(destFolder);
    }
    Logger.log(source + " DocにPDF内を転写します")
    lmdoc = DocumentApp.openById(getFileIdByName(source))
    lmdoc.getBody().setText(docs.getBody().getText())
    Logger.log(source + '.pdfをDocsに変換しました: ' + docs.getUrl());

    DriveApp.getFileById(docs.getId()).setTrashed(true)
  } catch (e) {
    if (docs != null) DriveApp.getFileById(docs.getId()).setTrashed(true)
    Logger.log('エラー: ' + e);
  }
  return lmdoc;
}

function getFileIdByName(fileName) {
  var files = DriveApp.getFilesByName(fileName);
  let fileId = null;
  try {    
    // ファイルが存在するか確認
    while (files.hasNext()) {
      var file = files.next();
      if (file.getName() != fileName) continue
      if (file.getParents().next().getName() == directory_name) {
        fileId = file.getId();
        Logger.log('ファイルID取得対象:' + file.getName())
        Logger.log('ファイルID: ' + fileId);
        break;
      }
    }
  } catch (e) {
    Logger.log('エラー: ' + e);
  }
  if (fileId == null) {
    Logger.log('ファイルが見つかりませんでした: ' + fileName);
  }
  return fileId;
}

function flattenArray(arr) {
  return arr.reduce((flat, toFlatten) => {
    return flat.concat(Array.isArray(toFlatten) ? flattenArray(toFlatten) : toFlatten);
  }, []);
}

function getSourceList() {
  let converter = spreadsheet.getSheetByName("Convert");
  let data_range = converter.getDataRange();
  const file_list = converter.getRange(2,1,data_range.getLastRow() - 1).getValues();
  return flattenArray(file_list);
}

function main() {
  let index = 1
  getSourceList().forEach(source => {
    let lmdoc = pdfToDocsWithBuiltInOCR(source)
    let converter = spreadsheet.getSheetByName("Convert");
    converter.getRange(index + 1, 2).setValue(lmdoc.getUrl());
    index += 1;
  });
}

function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('カスタムメニュー')
      .addItem('Doc変換', 'main')
      .addToUi();
}

Drive.Files.copyで生成したファイルはマイフォルダに追加されます。マイフォルダにコピー生成後、処理用ディレクトリに移動させないとファイルが見つからず、エラーとなります。

シート上は2列を用い、A列に入力したファイル名が変換の対象となります。変換完了後にB列へURLが追記されるので、開いて確認します。

スクリーンショット 2025-04-02 19.57.47

あとがき

PDF→Doc変換のネックとしての文章構造崩れは相変わらず避けられません。本文テキストは取得可能なため、必要に応じて整形したうえでPDFへ追記するとよいでしょう。なお、NotebookLMはある程度の文章構造崩れが起きていても問題なく解釈してくれます。一番の課題は文字化けかもしれません。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.