0

I'm trying to create a generic document using google docs API. I'm inserting images and dynamic tables whose borders are not visible.Tanaike's solution to create table by keeping borders invisible worked but here I'm appending all the requests in a single request then inserting into the document but I'm getting error after implementing the following code:

import io
from gdoctableapppy import gdoctableapp

SERVICE_FILENAME = 'C:/Users/XYZ/service_account.json'  # set path to service account filename

from googleapiclient.discovery import build
from google.oauth2 import service_account
from googleapiclient.http import MediaIoBaseDownload, MediaFileUpload

credentials = service_account.Credentials.from_service_account_file(SERVICE_FILENAME,
                                                                    scopes=['https://www.googleapis.com/auth/drive',
                                                                            'https://www.googleapis.com/auth/documents']
                                                                    )
docs = build('docs', 'v1', credentials=credentials)
drive = build('drive', 'v3', credentials=credentials)


def create_file(file_name):
    file_metadata = {
        "title": file_name,
        "body": {}
    }

    file = docs.documents().create(body=file_metadata).execute()
    print('File ID: %s' % file.get('documentId'))
    file_id = file.get('documentId')
    try:
        permission = {
            "role": "writer",
            "type": "user",
            'emailAddress': '[email protected]'
        }
        result = drive.permissions().create(fileId=file_id, body=permission).execute()
        print(result)
        return file_id
    except Exception as e:
        print('An error occurred:', e)
    return None


def insert_data(file_id):
    requests = []
    requests.append(insert_image())
    requests.append(insert_text(2, '\n'))
    requests.append(insert_text(3, 'text'))
    values = [['Name of the Client/Organization', 'XYZ'], ['Industry', 'Software']]
    requests.append(insert_table_data(file_id, values))

    result = docs.documents().batchUpdate(documentId=file_id, body={'requests': requests}).execute()


def insert_image():
    image_data = {
        'insertInlineImage': {
            'location': {
                'index': 1
            },
            'uri':
                'https://www.oberlo.com/media/1603970279-pexels-photo-3.jpg?fit=max&fm=jpg&w=1824',
            'objectSize': {
                'height': {
                    'magnitude': 350,
                    'unit': 'PT'
                },
                'width': {
                    'magnitude': 350,
                    'unit': 'PT'
                }
            }

        }
    }
    return image_data


def insert_text(index, text):
    text_data = {
        "insertText":
            {
                "text": text,
                "location":
                    {
                        "index": index
                    }
            }
    }

    return text_data


def insert_table_data(file_id, values):
    documentId = file_id
    resource = {
        "oauth2": credentials,
        "documentId": documentId,
        "rows": len(values),
        "columns": len(values[0]),
        "append": True,
        "values": values,
    }
    gdoctableapp.CreateTable(resource)
    resource = {
        "oauth2": credentials,
        "documentId": documentId,
    }
    res = gdoctableapp.GetTables(resource)
    obj = {"color": {"color": {}}, "dashStyle": "SOLID", "width": {"magnitude": 0, "unit": "PT"}}
    data = {
        "updateTableCellStyle": {
            "tableCellStyle": {
                "borderBottom": obj,
                "borderTop": obj,
                "borderLeft": obj,
                "borderRight": obj,
            },
            "tableStartLocation": {
                "index": res['tables'][-1]['tablePosition']['startIndex']
            },
            "fields": "borderBottom,borderTop,borderLeft,borderRight"
        }
    }
    # docs.documents().batchUpdate(documentId=documentId, body={'requests': requests}).execute()
    return data


def download_as_docx(file_id):
    results = drive.files().get(fileId=file_id, fields="id, name, mimeType, createdTime").execute()
    docMimeType = results['mimeType']
    mimeTypeMatchup = {
        "application/vnd.google-apps.document": {
            "exportType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docExt": "docx"
        }
    }
    exportMimeType = mimeTypeMatchup[docMimeType]['exportType']
    # docExt = mimeTypeMatchup[docMimeType]['docExt']
    docName = results['name']
    request = drive.files().export_media(fileId=file_id,
                                         mimeType=exportMimeType)  # Export formats : https://developers.google.com/drive/api/v3/ref-export-formats
    # fh = io.FileIO(docName + "." + docExt, mode='w')
    fh = io.FileIO(docName, mode='w')
    downloader = MediaIoBaseDownload(fh, request)
    done = False
    while done is False:
        status, done = downloader.next_chunk()
        print("Download %d%%." % int(status.progress() * 100))


def download_as_pdf(file_id, file_name):
    request = drive.files().export_media(fileId=file_id,
                                         mimeType='application/pdf')
    fh = io.BytesIO()
    downloader = MediaIoBaseDownload(fh, request)
    done = False
    while done is False:
        status, done = downloader.next_chunk()
        print("Download %d%%." % int(status.progress() * 100))
    fh.seek(0)
    filename = file_name.split('.docx')[0] + '.pdf'
    with open(filename, 'wb') as fx:
        fx.write(fh.getvalue())


def delete_gdrive_file(file_id):
    """Deleted file on Google Drive
    :param file_id: ID of Google Drive file
    """
    response = drive.files().delete(fileId=file_id).execute()
    print(response)


if __name__ == '__main__':
    file_name = 'Data.docx'
    file_id = create_file(file_name)
    insert_data(file_id)
    download_as_docx(file_id)
    download_as_pdf(file_id, file_name)
    delete_gdrive_file(file_id)

Error:

googleapiclient.errors.HttpError: <HttpError 400 when requesting https://docs.googleapis.com/v1/documents/1Qsf3CRKiIS9Ayjws1GEhg5oGiZbrTBAObMsifxdfre:b atchUpdate?alt=json returned "Invalid requests[3].updateTableCellStyle: The provided table start location is invalid.". Details: "Invalid requests[3].up dateTableCellStyle: The provided table start location is invalid.">

1 Answer 1

3

When I saw your script after the table was appended by gdoctableapp, the text and image are inserted from the top of the document, and the request for removing the borders is run. By this, the index of the appended table is different. So such an error occurs. I thought that this is the reason for your issue. In order to remove this issue, how about the following modification?

From:

def insert_data(file_id):
    requests = []
    requests.append(insert_image())
    requests.append(insert_text(2, '\n'))
    requests.append(insert_text(3, 'text'))
    values = [['Name of the Client/Organization', 'XYZ'], ['Industry', 'Software']]
    requests.append(insert_table_data(file_id, values))

    result = docs.documents().batchUpdate(documentId=file_id, body={'requests': requests}).execute()

To:

def insert_data(file_id):
    requests = []
    values = [['Name of the Client/Organization', 'XYZ'], ['Industry', 'Software']]
    requests.append(insert_table_data(file_id, values))
    requests.append(insert_image())
    requests.append(insert_text(2, '\n'))
    requests.append(insert_text(3, 'text'))

    result = docs.documents().batchUpdate(documentId=file_id, body={'requests': requests}).execute()
Sign up to request clarification or add additional context in comments.

9 Comments

my document would contain 10 to 12 pages and it should be in an order. I would want to insert that invisible table multiples time, then how this gonna help? I can't always put the table request at the top.
@Ask_Ashu Thank you for replying. I apologize for the inconvenience. From my document would contain 10 to 12 pages and it should be in an order. I would want to insert that invisible table multiples time, then how this gonna help? I can't always put the table request at the top., your showing script is different from your replying? If my understandin is correct, I have to apologize for my poor English skill. Unfortunately, I couldn't notice that your showing script is different from your tested script. Can I ask you about what you want to do? By this, I would like to try to understand it.
My script is just a sample script which is currently in progress. What I'm saying is, you put the table insertion requests.append(insert_table_data(file_id, values)) at the top in your script but I don't want it at the top. I want to insert images then text and a table. I want to follow an order. Your script works If I call the insert_table_data() first but If I'm calling this function after inserting some other stuffs in my document, it throws an error. I hope I'm able to clarify.
is this an indexing problem?
Thank you so much. This information is useful to me and hopefully it would be useful for others as well.
|

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.