Googleドキュメントへタブを追加した後、GASで取得した本文に一部の資料が入らなくなった場合は、読み取り対象を確認します。従来のDocumentの本文取得は、アクティブなタブや最初のタブを扱うため、全タブの取得と同じではありません。
各タブの本文を読むには、最上位のタブだけでなく、その下の子タブもたどります。本文だけを連結すると、どのタブから読んだかが分からなくなるので、タブIDとタイトルを一緒に残します。
タブの一覧は階層になっている
公式のGoogle Docsのタブガイドでは、getTabsで取得するタブと、getChildTabsで取得する子タブが説明されています。最上位の配列だけを読んでも、子タブの本文は取り出せません。
例として「概要」「手順」の2つのタブがあり、「手順」の下に「補足」という子タブがある文書を考えます。読み取る本文は3つですが、最上位のタブの数は2つです。画面の見た目だけで取得件数を決めないようにします。
タブの本文にはasDocumentTab().getBody()を使います。タブ型を確認してから内容を扱うと、取得したTabと本文のオブジェクトを混同せずに済みます。
子タブまでたどるコード
以下は本文を読み取り、タブごとの情報を配列へ入れます。文書やタブの名前、本文は変更しません。結果の表示では本文を出さず、取得文字数だけを確認します。
function collectDocumentTabTexts(doc) {
const result = [];
function visit(tabs, parentId) {
tabs.forEach(function (tab) {
if (tab.getType() === DocumentApp.TabType.DOCUMENT_TAB) {
result.push({
tabId: tab.getId(), title: tab.getTitle(), parentId: parentId,
text: tab.asDocumentTab().getBody().getText()
});
}
visit(tab.getChildTabs(), tab.getId());
});
}
visit(doc.getTabs(), null);
return result;
}
function previewAllDocumentTabs() {
const doc = DocumentApp.openById('練習用ドキュメントID');
const summary = collectDocumentTabTexts(doc).map(function (row) {
return {tabId: row.tabId, title: row.title,
parentId: row.parentId, characters: row.text.length};
});
console.log(JSON.stringify(summary));
}
練習用に上の3タブを作り、それぞれへ短い本文を入れて実行します。ログが3件になり、「補足」のparentIdが「手順」のタブIDと一致することを確認してください。タイトルが同じタブでも、IDで区別して結果へ残します。
全文という言葉の範囲を決める
この例で読むのは、各DocumentTabのBodyにある文字です。ヘッダー、フッター、コメント、画像の中の文字などをすべて抽出する処理ではありません。表や段落の見た目を、同じレイアウトで再現するものでもありません。
文書の内容を別の形式へ変換する場合、文字列として読めたことと、元の情報が全部移ったことを同じ確認にしないようにします。表の列構造やリンク先が必要なら、その要素を別に読む処理も検討します。
本文の取得方法はDocumentTab、階層とIDはTabで確認できます。古いコードのgetBody()を一律に置き換える前に、1つのタブを読む目的なのか、全部読む目的なのかを確かめます。
取得結果を外部へ出す前に
全タブを読むようにすると、以前は対象外だった下書きや補足資料まで入力へ入る場合があります。AIへ送る、共有フォルダへ保存するなどの後続処理では、取得範囲の変更に合わせて情報の共有範囲も見直してください。
ローカルでは親子関係を持つ代用タブで、最上位と子・孫タブの取得、親ID、空の本文、別のタブ型を確認しました。Google上の文書や画像の抽出は未実行です。GASの権限確認と関数の分割を基に、本文の取得と外部への送信は別の処理にしておきます。
