0

I have a challenge to insert a template, which is a HTML template, to a Google Docs programmatically using python. I know there is no native/built-in features to solve my problem in Google Docs Editor or Google Docs API, but I tried a few tricks to reach my objetive. Here we're ignoring "where" on document we should insert, just successfully insert is enough for now.

My approach was:

  1. Upload a HTML file in Google Drive as application/vnd.google-apps.document, because Google Docs convert the HTML to Docs automatically. (Not perfect, but works)
  2. Get the file content using Google Docs API get(), which is the Google Docs JSON format.
  3. Update the new content on target file using Google Docs batchUpdate().
def insert_template_to_file(target_file_id, content):
    media = MediaIoBaseUpload(BytesIO(content.encode('utf-8')), mimetype='text/html', resumable=True)
    body = {
        'name': 'document_test_html',
        'mimeType': 'application/vnd.google-apps.document',
        'parents': [DOC_FOLDER_ID]
    }

    try:
        # Create HTML as docs because it automatically convert html to docs
        content_file = driver_service.files().create(body=body, media_body=media).execute()
        content_file_id = content_file.get('id')

        # Collect html content from Google Docs after created
        doc = docs_service.documents().get(documentId=content_file_id, fields='body').execute()
        request_content = doc.get('body').get('content')

        # Insert the content from html to target file
        result = docs_service.documents().batchUpdate(documentId=target_file_id, body={'requests': request_content}).execute()
        print(result)

        # Delete html docs
        driver_service.files().delete(fileId=content_file_id).execute()
        print("Content inserted successfuly")
    except HttpError as error:
        # Delete html docs even if failed
        driver_service.files().delete(fileId=content_file_id).execute()
        print(f"An error occurred: {error}")

The problem is: The content which I collect from step 2 doesn't match what the batchUpdate() requires. I'm trying to adapt the content from step 2 to match the step 3, but no success yet.

The targeted solution: Get a string with a HTML code, insert the HTML rendered into a target file on Google Docs. The objective is append the HTML with the existing content of target file, not overwrite.

Did my approach make sense? Do you have any other idea to reach my goal?

3
  • It's crucial to consider the specific location for insertion when using the batchUpdate method in the Docs API. Ignoring the "where" aspect may hinder its effectiveness, as stated in the batchUpdate API request body. To assist you better, could you clarify which content from your HTML template you're trying to update in the existing Docs file? Also, providing a Minimal, Reproducible Example would greatly aid in offering a targeted solution. Commented Jan 12, 2024 at 21:56
  • Although I'm not sure whether I could correctly understand your expected result, I proposed an answer. Please confirm it. If I misunderstood your expected result, I apologize. Commented Jan 13, 2024 at 1:35
  • @SputnikDrunk2 I understand that is crucial consider the location for insertion, but for now I couldn't even insert anything yet. If I could append the rendered HTML at the end of target_file_id should be enough to me for now. Also, I updated my ask to be more clearly about my targeted solution. Commented Jan 14, 2024 at 2:37

1 Answer 1

1

I believe your goal is as follows.

  • You want to append HTML data to a Google Document by rendering the HTML.
  • You want to achieve this using googleapis for Python.

Unfortunately, in the current stage, it seems that the JSON object retrieved by "Method: documents.get" cannot be directly used as the request body of "Method: documents.batchUpdate".

But, if you want to append HTML to the existing Google Document, I thought that it could be achieved using only Drive API. When this is reflected in a sample script, how about the following sample script?

Sample script:

def insert_template_to_file(target_file_id, content):
    request = drive_service.files().export(fileId=target_file_id, mimeType="text/html")
    file = BytesIO()
    downloader = MediaIoBaseDownload(file, request)
    done = False
    while done is False:
        status, done = downloader.next_chunk()
        print("Download %d%%" % int(status.progress() * 100))
    file.seek(0)
    current_html = file.read()

    media = MediaIoBaseUpload(BytesIO(current_html + content.encode('utf-8')), mimetype='text/html', resumable=True)
    body = {'mimeType': 'application/vnd.google-apps.document'}

    try:
        result = drive_service.files().update(fileId=target_file_id, body=body, media_body=media).execute()
        print(result)
        print("Content inserted successfuly")
    except HttpError as error:
        print(f"An error occurred: {error}")
  • In this modified script, HTML data is retrieved from the existing Google Document, and the new HTML is appended to the retrieved HTML. And, the Google Document is updated by updated HTML. In your situation, it seems that the original data is HTML. So, I thought that this method might be able to be used.

Note:

  • This script overwrites the Google Document of target_file_id. So, when you test this script, I would like to recommend using a sample Google Document.

References:

Sign up to request clarification or add additional context in comments.

3 Comments

Hello @Tanaike, thanks for the reply, but the idea is to insert/append the content of HTML file into the target_file, not overwrite the whole target_file. I added a target solution on my ask to try be more clearly, sorry if was confusing.
@dfop02 Thank you for replying. From request_content = doc.get('body').get('content') and body={'requests': request_content} of your showing script, I thought that you might want to overwrite the existing Document as HTML. But, from your reply, I understood that I misunderstood your expected result. I apologize for my poor English skill. From your reply, I updated my answer. Please confirm it. If that was not useful, I apologize again.
Hello @tanaike! Your solution don't exactly solve my problem, but you give me a very good hint to find a better solution! Definitely update the file itself is a better way than trying using a Google API's that lack my needs. For this reason, I'll accept your question, thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.