Google Docs API を使用すると、ドキュメント内の任意のタブからコンテンツにアクセスできます。
タブとは
Google ドキュメントには、タブという組織レイヤがあります。ドキュメントでは、スプレッドシートのタブと同様に、1 つのドキュメント内に 1 つ以上のタブを作成できます。各タブには独自のタイトルと ID(URL に追加)があります。タブには子タブを設定することもできます。子タブとは、別のタブの下にネストされたタブです。
ドキュメント リソース内でドキュメント コンテンツが表現される方法の構造的な変更
以前のドキュメントにはタブの概念がないため、Document
リソースには次のフィールドを通じてすべてのテキスト コンテンツが直接含まれていました。
document.body
document.headers
document.footers
document.footnotes
document.documentStyle
document.suggestedDocumentStyleChanges
document.namedStyles
document.suggestedNamedStylesChanges
document.lists
document.namedRanges
document.inlineObjects
document.positionedObjects
タブの構造階層が追加されたため、これらのフィールドは、ドキュメント内のすべてのタブのテキスト コンテンツを意味的に表すものではありません。テキストベースのコンテンツが別のレイヤで表現されるようになりました。Google ドキュメントのタブのプロパティとコンテンツには、document.tabs
でアクセスできます。これは、Tab
オブジェクトのリストであり、各オブジェクトには前述のテキスト コンテンツ フィールドがすべて含まれています。以降のセクションでは、概要について説明します。タブの JSON 表現でも詳細を確認できます。
タブのプロパティにアクセスする
tab.tabProperties
を使用してタブのプロパティにアクセスします。タブのプロパティには、タブの ID、タイトル、配置などの情報が含まれます。
タブ内のテキスト コンテンツにアクセスする
タブ内の実際のドキュメント コンテンツは tab.documentTab
として公開されます。上記のテキスト コンテンツ フィールドにはすべて tab.documentTab
を使用してアクセスできます。たとえば、document.body
ではなく document.tabs[indexOfTab].documentTab.body
を使用する必要があります。
タブの階層
子タブは、API では Tab
の tab.childTabs
フィールドとして表されます。ドキュメント内のすべてのタブにアクセスするには、子タブの「ツリー」を走査する必要があります。たとえば、次のようなタブ階層を含むドキュメントについて考えてみましょう。
タブ 3.1.2 から Body
を取得するには、document.tabs[2].childTabs[0].childTabs[1].documentTab.body
にアクセスします。後のセクションのサンプルコード ブロックをご覧ください。ドキュメント内のすべてのタブを反復処理するサンプルコードが示されています。
メソッドの変更
タブの導入に伴い、各ドキュメント メソッドにいくつかの変更が加えられ、コードの更新が必要になる場合があります。
documents.get
デフォルトでは、すべてのタブの内容が返されるわけではありません。デベロッパーは、すべてのタブにアクセスできるようにコードを更新する必要があります。documents.get
メソッドは includeTabsContent
パラメータを公開します。これにより、すべてのタブのコンテンツをレスポンスで提供するかどうかを構成できます。
includeTabsContent
がtrue
に設定されている場合、documents.get
メソッドは、document.tabs
フィールドが入力されたDocument
リソースを返します。document
に直接関連付けられているテキスト フィールド(document.body
など)はすべて空のままになります。includeTabsContent
が指定されていない場合、Document
リソースのテキスト フィールド(document.body
など)には、最初のタブのコンテンツのみが入力されます。document.tabs
フィールドは空になり、他のタブのコンテンツは返されません。
documents.create
documents.create
メソッドは、作成された空のドキュメントを表す Document
リソースを返します。返された Document
リソースにより、ドキュメントのテキスト コンテンツ フィールドと document.tabs
の両方に空のドキュメント コンテンツが入力されます。
document.batchUpdate
各 Request
には、更新を適用するタブを指定する方法が含まれています。デフォルトでは、タブが指定されていない場合、ほとんどの場合、Request
はドキュメントの最初のタブに適用されます。ReplaceAllTextRequest
、DeleteNamedRangeRequest
、ReplaceNamedRangeContentRequest
の 3 つの特別なリクエストは、デフォルトですべてのタブに適用されます。
詳細については、Request
のドキュメントをご覧ください。
内部リンクの変更
ドキュメント内のタブ、ブックマーク、見出しへの内部リンクを作成できます。タブ機能の導入により、Link
リソースの link.bookmarkId
フィールドと link.headingId
フィールドは、ドキュメント内の特定のタブのブックマークまたは見出しを表すことができなくなりました。
デベロッパーは、読み取りオペレーションと書き込みオペレーションで link.bookmark
と link.heading
を使用するようにコードを更新する必要があります。BookmarkLink
オブジェクトと HeadingLink
オブジェクトを使用して内部リンクを公開します。それぞれに、ブックマークまたは見出しの ID と、そのタブの ID が含まれています。また、link.tabId
はタブへの内部リンクを公開します。
documents.get
レスポンスのリンク コンテンツは、includeTabsContent
パラメータによって異なる場合もあります。
includeTabsContent
がtrue
に設定されている場合、すべての内部リンクはlink.bookmark
とlink.heading
として公開されます。以前のフィールドは使用されなくなります。includeTabsContent
が指定されていない場合、単一のタブを含むドキュメントでは、その単一のタブ内のブックマークまたは見出しへの内部リンクは引き続きlink.bookmarkId
とlink.headingId
として公開されます。複数のタブを含むドキュメントでは、内部リンクはlink.bookmark
とlink.heading
として公開されます。
document.batchUpdate
で、以前のフィールドのいずれかを使用して内部リンクが作成された場合、ブックマークまたは見出しは Request
で指定されたタブ ID のものであるとみなされます。タブが指定されていない場合は、ドキュメントの最初のタブから取得されたものと見なされます。
リンクの JSON 表現には、より詳細な情報が記載されています。
タブの一般的な使用パターン
次のコードサンプルは、タブを操作するさまざまな方法を示しています。
ドキュメント内のすべてのタブからタブの内容を読み取る
タブ機能の前にこれを行っていた既存のコードは、includeTabsContent
パラメータを true
に設定し、タブツリー階層を走査し、Document
ではなく Tab
と DocumentTab
からゲッター メソッドを呼び出すことで、タブをサポートするように移行できます。次のコードサンプルの一部は、ドキュメントからテキストを抽出するのスニペットに基づいています。ドキュメント内のすべてのタブのテキスト コンテンツをすべて印刷する方法を示しています。このタブ トラバース コードは、タブの実際の構造を気にしない他の多くのユースケースに適応できます。
Java
/** Prints all text contents from all tabs in the document. */ static void printAllText(Docs service, String documentId) throws IOException { // Fetch the document with all of the tabs populated, including any nested // child tabs. Document doc = service.documents().get(documentId).setIncludeTabsContent(true).execute(); List<Tab> allTabs = getAllTabs(doc); // Print the content from each tab in the document. for (Tab tab: allTabs) { // Get the DocumentTab from the generic Tab. DocumentTab documentTab = tab.getDocumentTab(); System.out.println( readStructuralElements(documentTab.getBody().getContent())); } } /** * Returns a flat list of all tabs in the document in the order they would * appear in the UI (top-down ordering). Includes all child tabs. */ private List<Tab> getAllTabs(Document doc) { List<Tab> allTabs = new ArrayList<>(); // Iterate over all tabs and recursively add any child tabs to generate a // flat list of Tabs. for (Tab tab: doc.getTabs()) { addCurrentAndChildTabs(tab, allTabs); } return allTabs; } /** * Adds the provided tab to the list of all tabs, and recurses through and * adds all child tabs. */ private void addCurrentAndChildTabs(Tab tab, List<Tab> allTabs) { allTabs.add(tab); for (Tab tab: tab.getChildTabs()) { addCurrentAndChildTabs(tab, allTabs); } } /** * Recurses through a list of Structural Elements to read a document's text * where text may be in nested elements. * * <p>For a code sample, see * <a href="https://developers.google.com/docs/api/samples/extract-text">Extract * the text from a document</a>. */ private static String readStructuralElements(List<StructuralElement> elements) { ... }
ドキュメントの最初のタブからタブの内容を読み取る
これは、すべてのタブを読み取るのと同様です。
Java
/** Prints all text contents from the first tab in the document. */ static void printAllText(Docs service, String documentId) throws IOException { // Fetch the document with all of the tabs populated, including any nested // child tabs. Document doc = service.documents().get(documentId).setIncludeTabsContent(true).execute(); List<Tab> allTabs = getAllTabs(doc); // Print the content from the first tab in the document. Tab firstTab = allTabs.get(0); // Get the DocumentTab from the generic Tab. DocumentTab documentTab = firstTab.getDocumentTab(); System.out.println( readStructuralElements(documentTab.getBody().getContent())); }
最初のタブを更新するリクエストを送信する
次のコードサンプルの一部は、Request
で特定のタブをターゲットにする方法を示しています。このコードは、テキストの挿入、削除、移動ガイドのサンプルに基づいています。
Java
/** Inserts text into the first tab of the document. */ static void insertTextInFirstTab(Docs service, String documentId) throws IOException { // Get the first tab's ID. Document doc = service.documents().get(documentId).setIncludeTabsContent(true).execute(); Tab firstTab = doc.getTabs().get(0); String tabId = firstTab.getTabProperties().getTabId(); List<Request>requests = new ArrayList<>(); requests.add(new Request().setInsertText( new InsertTextRequest().setText(text).setLocation(new Location() // Set the tab ID. .setTabId(tabId) .setIndex(25)))); BatchUpdateDocumentRequest body = new BatchUpdateDocumentRequest().setRequests(requests); BatchUpdateDocumentResponse response = docsService.documents().batchUpdate(DOCUMENT_ID, body).execute(); }