I'm trying to automate some document creation in Google Docs via a Python script, and I think I haven't quite wrapped my head around how the Google Docs API's batchUpdate() method works.
I have my own JSON-based config file that my script reads in and generates some content in a corresponding Google Doc document. I'm essentially iterating over a dictionary of various sections destined for the document. My hope is to have a document structure like the following:
-- snip --
Section A
- placeholder
Section B
- placeholder
etc...
-- snip --
I have no issues creating some section headers (HEADING_2s), and I've been doing so in reverse order because it seems easier:
requests = []
curr_item = {}
for section in reversed(user_config["sections"]):
# section text
curr_item = {"insertText": {"location": {"index": 1}, "text": "{section_name}\n".format(section_name=i["name"])}}
requests.append(curr_item)
# section formatting (as an H2)
curr_item = {"updateParagraphStyle": {"range": {"startIndex": 1, "endIndex": len(i["name"])}, "paragraphStyle": {"namedStyleType": "HEADING_2", "fields": "namedStyleType,spaceAbove,spaceBelow"}}
requests.append(curr_item)
result = svc.documents().batchUpdate(documentId=doc_id, body={'requests': requests}).execute()
So far, so good 🙂
But adding placeholder bulleted lists into the mix has been causing me problems:
requests = []
curr_item = {}
bullet_placeholder = "placeholder"
for section in reversed(user_config["sections"]):
# section text
curr_item = {"insertText": {"location": {"index": 1}, "text": "{section_name}\n".format(section_name=i["name"])}}
requests.append(curr_item)
# section formatting (as an H2)
curr_item = {"updateParagraphStyle": {"range": {"startIndex": 1, "endIndex": len(i["name"])}, "paragraphStyle": {"namedStyleType": "HEADING_2", "fields": "namedStyleType,spaceAbove,spaceBelow"}}
requests.append(curr_item)
# placeholder list
curr_item = {"insertText": {"location": {"index": len(i["name"]) + 2}, "text": "placeholder"}, "createParagraphBullets": { "range": { "startIndex": len(i["name"]) + 2, "endIndex": len(bullet_placeholder) + 2 }, "bulletPreset": "BULLET_ARROW_DIAMOND_DISC" } }
requests.append(curr_item)
result = svc.documents().batchUpdate(documentId=doc_id, body={'requests': requests}).execute()
This results in the following error response:
<HttpError 400 when requesting https://docs.googleapis.com/v1/documents/foo-document-id:batchUpdate?alt=json returned "Invalid value at 'requests[2]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'
Invalid value at 'requests[5]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'
Invalid value at 'requests[8]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'
Invalid value at 'requests[11]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'
Invalid value at 'requests[14]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'
Invalid value at 'requests[17]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'
Invalid value at 'requests[20]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'". Details: "[{'@type': 'type.googleapis.com/google.rpc.BadRequest', 'fieldViolations': [{'field': 'requests[2]', 'description': "Invalid value at 'requests[2]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'"}, {'field': 'requests[5]', 'description': "Invalid value at 'requests[5]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'"}, {'field': 'requests[8]', 'description': "Invalid value at 'requests[8]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'"}, {'field': 'requests[11]', 'description': "Invalid value at 'requests[11]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'"}, {'field': 'requests[14]', 'description': "Invalid value at 'requests[14]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'"}, {'field': 'requests[17]', 'description': "Invalid value at 'requests[17]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'"}, {'field': 'requests[20]', 'description': "Invalid value at 'requests[20]' (oneof), oneof field 'request' is already set. Cannot set 'createParagraphBullets'"}]}]">
I've tried a few other approaches, like keeping track of the index based on the length of all text written up to a given point in time, calling batch update at the end of each iteration of the for loop but all to no avail.
I'd be interested to know what I'm missing or misunderstanding about the APIs for inserting + formatting text and creating lists.
