使用 Google Docs API 在不影响格式的情况下更改整个文档的字体

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

我正在尝试使用 API 更改整个 Google 文档的字体。目的是让我们应用程序的用户使用他们公司的字体导出文档。

这是我目前正在做的事情:

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()

上面的代码更改了字体,但它也删除了所有粗体文本格式,因为它覆盖了元素的整个样式。我研究过的一些选项:

DocumentStyle

文档有DocumentStyle属性,但不包含任何字体信息。

NamedStyles

文档还有一个NamedStyles属性。它包含 NORMAL_TEXTHEADING_1 等样式。我可以遍历所有这些并更改它们的 textStyle.weightedFontFamily。这将是理想的解决方案,因为它将样式信息保留在它所属的位置。但是我还没有找到使用 API.

更改 NamedStyles 的方法

更深层次的循环

我可以继续我目前的方法,循环遍历每个 element 上的 elements 列表,保留 textStyle 中的字体以外的所有内容(其中包含 bold: true).但是,我们目前的方法执行时间已经太长,而且这样的方法会更慢,更脆弱,所以我想避免这种情况。

答案:

从当前元素中提取 textStyle,仅提取 change/add weightedFontFamily/fontFamily 对象。

代码示例:

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()

这似乎对我有用,即使在文档之间和末尾有分节符。您可能想探索更多极端案例..

这基本上是在尝试模仿 SelectAll 选项

document = service.documents().get(documentId=doc_id).execute()
endIndex = sorted(document["body"]["content"], key=lambda x: x["endIndex"], reverse=True,)[0]["endIndex"]
service.documents().batchUpdate(
    documentId=doc_id,
    body={
        "requests": {
            "updateTextStyle": {
                "range": {
                    "endIndex": endIndex,
                    "startIndex": 1,
                },
                "fields": "fontSize",
                "textStyle": {"fontSize": {"magnitude": 100, "unit": "pt"}},
            }
        }
    },
).execute()

同样适用于其他领域。

但是,如果您只想与所有客户端共享一个 docx 文件,您可以保留一份 PDF/DOCX 的本地副本,然后对其进行修改。在 DOCX 中处理样式相当容易(它是一堆 xml 文件)

使用它来浏览和更新 DOCX 文件OOXML Tools Chrome Extension

同样,PDF 是作为记录存储的键值对。检查这个:ReportLab