Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change the font of an entire document without affecting formatting using Google Docs API

I am trying to change the font of an entire Google Doc using the API. The purpose is to let users of our application export documents with their company’s font.

This is what I am currently doing:

from googleapiclient.discovery import build

doc_service = build("docs", "v1")
document = self.doc_service.documents().get(documentId="[Document ID]").execute()
requests = []
for element in document["body"]["content"]:
    if "sectionBreak" in element:
        continue  # Trying to change the font of a section break causes an error
    requests.append(
        {
            "updateTextStyle": {
                "range": {
                    "startIndex": element["startIndex"],
                    "endIndex": element["endIndex"],
                },
                "textStyle": {
                    "weightedFontFamily": {
                        "fontFamily": "[Font name]"
                    },
                },
                "fields": "weightedFontFamily",
            }
        }
    )
doc_service.documents().batchUpdate(
    documentId=self.copy_id, body={"requests": requests}
).execute()

The code above changes the font, but it also removes any bold text formatting because it overrides the entire style of an element. Some options I have looked into:

DocumentStyle

Documents have a DocumentStyle property, but it does not contain any font information.

NamedStyles

Documents also have a NamedStyles property. It contains styles like NORMAL_TEXT and HEADING_1. I could loop through all these and change their textStyle.weightedFontFamily. This would be the ideal solution, because it would keep style information where it belongs. But I have not found a way to change NamedStyles using the API.

Deeper loop

I could continue with my current approach, looping through the elements list on each element, keeping everything but the font from textStyle (which contains things like bold: true). However, our current approach already takes too long to execute, and such an approach would be both slower and more brittle, so I would like to avoid this.

like image 803
Yngve Høiseth Avatar asked Oct 14 '25 07:10

Yngve Høiseth


1 Answers

Answer:

Extract the textStyle out of the current element and only change/add the weightedFontFamily/fontFamily object.

Code Example:

for element in document["body"]["content"]:
    if "sectionBreak" in element:
        continue  # Trying to change the font of a section break causes an error

    textStyle = element["paragraph"]["elements"][0]["textStyle"]
    textStyle["weightedFontFamily"]["fontFamily"] = "[Font name]"

    requests.append(
        {
            "updateTextStyle": {
                "range": {
                    "startIndex": element["startIndex"],
                    "endIndex": element["endIndex"],
                },
                "textStyle": textStyle,
                "fields": "weightedFontFamily",
            }
        }
    )
doc_service.documents().batchUpdate(
    documentId=self.copy_id, body={"requests": requests}
).execute()
like image 150
I hope this is helpful to you Avatar answered Oct 16 '25 22:10

I hope this is helpful to you



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!