Search code examples
google-apps-scriptgoogle-docsgoogle-docs-api

Populate table cells in Google document with Google Apps Script


I want to add a 5x5 table to an empty document. Eventually I will want to add one on each of several pages. The documentation is cryptic but I found this nice example from Tanaike:

It works https://tanaikech.github.io/2019/05/22/creating-new-table-and-putting-values-to-cells-using-google-docs-api-with-google-apps-script/

  var resource = {
    requests: [
      { insertTable: { rows: 2, columns: 2, location: { index: 1 } } },
      { insertText: { text: "B2", location: { index: 12 } } },
      { insertText: { text: "A2", location: { index: 10 } } },
      { insertText: { text: "B1", location: { index: 7 } } },
      { insertText: { text: "A1", location: { index: 5 } } }
    ]
  };
  Docs.Documents.batchUpdate(resource, doc.getId());

So I tried to extend to a 5 x 5 table with the same pattern and got the following error: Error GoogleJsonResponseException: API call to docs.documents.batchUpdate failed with error: Invalid requests[5].insertText: The insertion index must be inside the bounds of an existing paragraph. You can still create new paragraphs by inserting newlines.

  var requests = []
  requests.push ({ insertTable: 
                   { rows: 5, columns: 5, 
                     location: { index: 1 } }  
                 });
  requests.push ( { insertText: { text: "E5", location: { index: 33 } } } );  // 2
  requests.push ( { insertText: { text: "D5", location: { index: 31 } } } );  // 3
  requests.push ( { insertText: { text: "C5", location: { index: 29 } } } );  // 4
  requests.push ( { insertText: { text: "B5", location: { index: 27 } } } );  // 5
  requests.push ( { insertText: { text: "A5", location: { index: 25 } } } );  // 6
  requests.push ( { insertText: { text: "E4", location: { index: 28 } } } );  // 7
  requests.push ( { insertText: { text: "D4", location: { index: 26 } } } );  // 8
  requests.push ( { insertText: { text: "C4", location: { index: 24 } } } );
  requests.push ( { insertText: { text: "B4", location: { index: 22 } } } );
  requests.push ( { insertText: { text: "A4", location: { index: 20 } } } );
  requests.push ( { insertText: { text: "E3", location: { index: 23 } } } );
  requests.push ( { insertText: { text: "D3", location: { index: 21 } } } );
  requests.push ( { insertText: { text: "C3", location: { index: 19 } } } );
  requests.push ( { insertText: { text: "B3", location: { index: 17 } } } );
  requests.push ( { insertText: { text: "A3", location: { index: 15 } } } );
  requests.push ( { insertText: { text: "E2", location: { index: 18 } } } );
  requests.push ( { insertText: { text: "D2", location: { index: 16 } } } );
  requests.push ( { insertText: { text: "C2", location: { index: 14 } } } );
  requests.push ( { insertText: { text: "B2", location: { index: 12 } } } );
  requests.push ( { insertText: { text: "A2", location: { index: 10 } } } );
  requests.push ( { insertText: { text: "E1", location: { index: 13 } } } );
  requests.push ( { insertText: { text: "D1", location: { index: 11 } } } );
  requests.push ( { insertText: { text: "C1", location: { index: 09 } } } );
  requests.push ( { insertText: { text: "B1", location: { index: 07 } } } );
  requests.push ( { insertText: { text: "A1", location: { index: 05 } } } );

  if (requests.length > 0)   {
    response = Docs.Documents.batchUpdate(
      { 'requests': requests }, doc.getId());
  }

Both appendParagraph(..) and appendTable() are valid methods for document body so I did not think I needed to add a paragraph with the table inside the paragraph?

More research and Tanaike also answered here

Unable to add text to new Google Doc via Docs API I added endOfSegmentLocation and got the following GoogleJsonResponseException: API call to docs.documents.batchUpdate failed with error: Invalid JSON payload received. Unknown name "endOfSegmentLocation" at 'requests[0]': Cannot find field.

  var requests = []
  requests.push ({ insertTable: 
                   { rows: 5, columns: 5, 
                     location: { index: 1 } },
                     endOfSegmentLocation: { segmentId: "" }   
                 });
  requests.push ( { insertText: { text: "E5", location: { index: 33 } } } );  // 2
  requests.push ( { insertText: { text: "D5", location: { index: 31 } } } );  // 3
  requests.push ( { insertText: { text: "C5", location: { index: 29 } } } );  // 4
  requests.push ( { insertText: { text: "B5", location: { index: 27 } } } );  // 5
  requests.push ( { insertText: { text: "A5", location: { index: 25 } } } );  // 6
  requests.push ( { insertText: { text: "E4", location: { index: 28 } } } );  // 7
  requests.push ( { insertText: { text: "D4", location: { index: 26 } } } );  // 8
  requests.push ( { insertText: { text: "C4", location: { index: 24 } } } );
  requests.push ( { insertText: { text: "B4", location: { index: 22 } } } );
  requests.push ( { insertText: { text: "A4", location: { index: 20 } } } );
  requests.push ( { insertText: { text: "E3", location: { index: 23 } } } );
  requests.push ( { insertText: { text: "D3", location: { index: 21 } } } );
  requests.push ( { insertText: { text: "C3", location: { index: 19 } } } );
  requests.push ( { insertText: { text: "B3", location: { index: 17 } } } );
  requests.push ( { insertText: { text: "A3", location: { index: 15 } } } );
  requests.push ( { insertText: { text: "E2", location: { index: 18 } } } );
  requests.push ( { insertText: { text: "D2", location: { index: 16 } } } );
  requests.push ( { insertText: { text: "C2", location: { index: 14 } } } );
  requests.push ( { insertText: { text: "B2", location: { index: 12 } } } );
  requests.push ( { insertText: { text: "A2", location: { index: 10 } } } );
  requests.push ( { insertText: { text: "E1", location: { index: 13 } } } );
  requests.push ( { insertText: { text: "D1", location: { index: 11 } } } );
  requests.push ( { insertText: { text: "C1", location: { index: 09 } } } );
  requests.push ( { insertText: { text: "B1", location: { index: 07 } } } );
  requests.push ( { insertText: { text: "A1", location: { index: 05 } } } );

  if (requests.length > 0)   {
    response = Docs.Documents.batchUpdate(
      { 'requests': requests }, doc.getId());
  }

I can use this over and over in a loop followed by appendPageBreak().


https://developers.google.com/apps-script/reference/document/table


Works but I will still probably need to use the API to style the tables and I want to know what is wrong with what I tried.

function loadTable(body, inArr) {
  var inArrIdx = 0;
  var cellArr = [], rowArr = [];
  for (var r = 0 ; r < 5 ; r++ )    {
   for (var c = 0 ; c < 5 ; c++ )    {
    rowArr.push( inArr[inArrIdx] );
    inArrIdx++;
   }
    cellArr.push( rowArr );
    rowArr = [];
  }
  console.log('cellArr: ', cellArr );
  
  // Build a table from the array.
  body.appendTable(cellArr);
}

Solution

  • The source is exclusive because it is only talking the indexing rule of a 2-column-table

    For the row, the index is required to set every 5 index. For the column, the index is required to set every 2 index.

    To generalize:

    • Index of first cell: 5
    • Index of column n: index + length of text of column n-1
    • Index of row n: index + length of text + 1 (row break) of last cell (column) of row n
      requests.push ( { insertText: { text: "E2", location: { index: 24 } } } );
      requests.push ( { insertText: { text: "D2", location: { index: 22 } } } );
      requests.push ( { insertText: { text: "C2", location: { index: 20 } } } );
      requests.push ( { insertText: { text: "B2", location: { index: 18 } } } );
      requests.push ( { insertText: { text: "A2", location: { index: 16 } } } );
      requests.push ( { insertText: { text: "E1", location: { index: 13 } } } );
      requests.push ( { insertText: { text: "D1", location: { index: 11 } } } );
      requests.push ( { insertText: { text: "C1", location: { index: 09 } } } );
      requests.push ( { insertText: { text: "B1", location: { index: 07 } } } );
      requests.push ( { insertText: { text: "A1", location: { index: 05 } } } );