【问题标题】:Add page break before text in Apps Script在 Apps 脚本中的文本前添加分页符
【发布时间】:2021-01-15 05:42:02
【问题描述】:

我正在尝试在某些文本之前插入分页符。

我在这篇文章中尝试了解决方案:Replace a text keyword with a "Page Break" element in Apps Script

在文本之后添加分页符,玩弄代码并且无法让它在之前添加它。作为一种解决方法,我尝试在附加分页符后附加段落文本,但无法正常工作。

【问题讨论】:

  • 当您说before text时,您是指将文本所在的段落拆分并将该段落的这一部分拆分到下一页,还是在您的文本所在的段落之前添加分页符?
  • 我有一个名为第 X 章的文本,我希望在该文本之前添加分页符。

标签: javascript google-apps-script google-docs google-docs-api


【解决方案1】:

我相信你的目标如下。

  • 您想使用 Google Apps 脚本在 Google 文档中的文本词之前插入分页符。

在这种情况下,我想提出以下使用 Google Docs API 的示例脚本。在 Google Docs API 中,可以使用 index 将页面插入到文本的中间。所以我觉得这个方向可能有点简单,工艺成本也可能会降低。该脚本的流程如下。

  1. 使用 Docs API 中的“documents.get”方法从 Google Document 中检索所有内容。
  2. 使用Docs API中的“documents.batchUpdate”方法创建请求体。
  3. 向Docs API中的“documents.batchUpdate”方法请求请求体。

示例脚本:

请将以下脚本复制粘贴到谷歌文档的脚本编辑器中,并设置searchPattern。并且,请在高级 Google 服务中启用 Google Docs API。

function myFunction() {
  const searchText = "{{page break}}";  // Please set text. This script inserts the pagebreak before this text.
  
  // 1. Retrieve all contents from Google Document using the method of "documents.get" in Docs API.
  const docId = DocumentApp.getActiveDocument().getId();
  const res = Docs.Documents.get(docId);
  
  // 2. Create the request body for using the method of "documents.batchUpdate" in Docs API.
  let offset = 0;
  const requests = res.body.content.reduce((ar, e) => {
    if (e.paragraph) {
      e.paragraph.elements.forEach(f => {
        if (f.textRun) {
          const re = new RegExp(searchText, "g");
          let p = null;
          while (p = re.exec(f.textRun.content)) {
            ar.push({insertPageBreak: {location: {index: p.index + offset}}});
          }
        }
      })
    }
    offset = e.endIndex;
    return ar;
  }, []).reverse();
  
  // 3. Request the request body to the method of "documents.batchUpdate" in Docs API.
  Docs.Documents.batchUpdate({requests: requests}, docId);
}
  • 在此示例脚本中,const searchPattern = "{{page break}}" 用作插入分页符的文本。请根据您的实际情况进行修改。

结果:

上面的脚本运行时,得到如下结果。

从:

到:

参考资料:

补充:

我确认google-docs-api 也包含在您的问题标签中。所以我提出了一个使用 Google Docs API 的示例脚本。但是从您的以下回复来看,您似乎想使用 Google Docs API 而不在 Advanced Google 服务中启用 Google Docs API。我无法从您的问题和标签中注意到这一点。

有没有一种无需在 Apps 脚本环境中启用 Google Docs API 的方法?如果不这样做,我会收到 Docs.Documents.get(docId) 的参考错误。

关于您的回复,我再添加一个示例脚本。在此示例脚本中,Google Docs API 与 UrlFetchApp 一起使用。因此不使用高级 Google 服务的 Google Docs API。但是,在这种情况下,需要在 API 控制台启用 Google Docs API。所以我为此提出了两种模式。

  1. 请将 GCP 链接到 GAS 项目并在 API 控制台启用 Google Docs API。

  2. 请在高级 Google 服务中启用一次 Google Docs API 并保存 GAS 项目。在这里,请等待几分钟。然后,请在高级 Google 服务中禁用 Google Docs API。在当前阶段,似乎即使在高级 Google 服务中禁用了 Google Docs API,也没有在 API 控制台中禁用 Google Docs API。但我不确定这是否是永久性的情况。但是,现在,我认为这可能可以用于您的这种情况。

示例脚本:

在使用此脚本之前,请按照我上面建议的方式在 API 控制台中启用 Google Docs API 并运行该脚本。

function myFunction() {
  const searchText = "{{page break}}";  // Please set text. This script inserts the pagebreak before this text.
  
  // 1. Retrieve all contents from Google Document using the method of "documents.get" in Docs API.
  const accessToken = ScriptApp.getOAuthToken();
  const docId = DocumentApp.getActiveDocument().getId();
  const url1 = "https://docs.googleapis.com/v1/documents/" + docId;
  const response1 = UrlFetchApp.fetch(url1, {headers: {authorization: "Bearer " + accessToken}});
  const res = JSON.parse(response1.getContentText());

  // 2. Create the request body for using the method of "documents.batchUpdate" in Docs API.
  let offset = 0;
  const requests = res.body.content.reduce((ar, e) => {
    if (e.paragraph) {
      e.paragraph.elements.forEach(f => {
        if (f.textRun) {
          const re = new RegExp(searchText, "g");
          let p = null;
          while (p = re.exec(f.textRun.content)) {
            ar.push({insertPageBreak: {location: {index: p.index + offset}}});
          }
        }
      })
    }
    offset = e.endIndex;
    return ar;
  }, []).reverse();
  
  // 3. Request the request body to the method of "documents.batchUpdate" in Docs API.
  const url2 = `https://docs.googleapis.com/v1/documents/${docId}:batchUpdate`;
  UrlFetchApp.fetch(url2, {method: "post", payload: JSON.stringify({requests: requests}), contentType: "application/json", headers: {authorization: "Bearer " + accessToken}});

  // DocumentApp.getActiveDocument(); // This is used for automatically adding a scope of https://www.googleapis.com/auth/documents by the script editor.
}

注意:

  • 当出现与 Google Docs API 相关的错误时,请在 API 控制台重新启用 Google Docs API。

【讨论】:

  • 这个答案很棒。谢谢!顺便说一句,有没有办法做到这一点而无需在 Apps 脚本环境中启用 Google Docs API?如果我不这样做,我会收到 Docs.Documents.get(docId) 的参考错误。
  • @Diego 感谢您的回复。在我提出的答案中,使用了 Google 高级服务的 Google Docs API。因此,在这种情况下,需要在高级 Google 服务中启用 Google Docs API。我认为没有在高级谷歌服务中启用谷歌文档 API 的情况下使用高级谷歌服务的谷歌文档 API 的方法。当 Google Docs API 未在 Advanced Google services 中启用时,会发生此类错误。对于这种情况,我深表歉意。
  • @Diego 例如,在高级 Google 服务中启用了 Google Docs API 后,即使在高级 Google 服务中禁用了 Google Docs API,似乎在 API 控制台中也没有启用 Google Docs API。但我不确定这是否是永久性的情况。当这种情况永久存在时,我认为您可以在不启用 Docs API 的情况下将 Docs API 与 UrlFetchApp 一起使用。或者,通过将 GCP 链接到 GAS 项目,您还可以通过在 API 控制台启用 Docs API 来使用 UrlFetchApp 的 Docs API。但我不确定这是否是你所期望的方向,我为我糟糕的英语水平道歉。
  • 无需道歉,非常感谢您的回复。当您使用 UrlFetchApp 时,这是否意味着通过它调用 API 端点:“docs.googleapis.com”?那么调用它的方法会不会很简单?
  • @Diego 感谢您的回复。我认为是的。
猜你喜欢
  • 2011-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-14
  • 2021-09-18
  • 2020-06-21
  • 2015-07-10
  • 2021-06-03
相关资源
最近更新 更多