从模板 Google 文档中获取 Header 和页脚,并应用于 Google Drive 文件夹中的所有文档

Get Header and Footer from template Google Doc, and apply to all docs in a Google Drive folder

我需要帮助在 Google 驱动器文件夹中的所有 Google 文档中应用包含表格、段落和图像(品牌 content/letterhead)的 header 和页脚.

目标:

  1. Get/Copy header 来自包含表格、段落和图像的源文档。
  2. Paste/Apply/Replace header 复制到 Google 驱动器文件夹中的所有文档
  3. 对页脚执行相同操作。
  4. 不需要程序化“附加”到现有页脚。

我希望有一种方法可以为模板做 CSS 或类似的事情,可以应用于一批 google 文档...但我相信脚本是唯一的方法。

这是对 post 的补充:Find and Replace text in entire Google Drive folder, headers, footers, google docs using a script

function replaceHeaderAndFooter() {
  
 const headerToCopyandPaste = DocumentApp.openById("<SourceDocID>").getHeader().getTables().toString();  // ID contains source header
 const footerToCopyandPaste = DocumentApp.openById("<SourceDocID>").getHeader().copy();  // ID contains source footer
  
  
  var files = DriveApp.getFolderById("<FolderID>").getFiles();  //ID contains folder that has Google Docs that will have Header and Footer Replaced
  while (files.hasNext()) {
    var file = files.next();
    var doc = DocumentApp.openById(file.getId());
    
  var headerSectionToBeReplaced = doc.getHeader()
  var footerSectionToBeReplaced = doc.getFooter()
    
  headerSectionToBeReplaced.clear();
footerSectionToBeReplaced.clear();

 headerSectionToBeReplaced.appendTable(headerToCopyandPaste); //This does not work
 footerSectionToBeReplaced = footerToCopyandPaste    // This does not work
    
  }
}

我相信你的目标和情况如下。

  • 根据您的情况,目标文档有多个页面,并且已经设置了文本,您希望将模板文档的header和页脚复制到每个目标文档的所有页面作为覆盖.
  • 从您的共享文档中,
    • 我确认在模板文档的 header 中,图像作为内嵌图像放在 table 单元格中。
    • 我确认在模板文档的页脚中使用了图片。
  • 当图像在table中使用时,即使复制了table,图像似乎也没有被复制。
    • 我认为这可能是您遇到问题的原因。
  • 根据大家的回复,我可以确认如下。
    • 您要使用的 Google 个文档文件有数百个。
    • 但是你会运行每几个文档的脚本。

为了实现您的目标,在此示例脚本中,我想提出以下流程。

流量:

  1. 从特定文件夹中检索 Google 文档文件。
    • 在这种情况下,不检查子文件夹就从特定文件夹下检索文档文件。
    • 因为从您的回复评论来看,虽然有数百个 Google 文档文件要使用,但您会 运行 每几个文档的脚本。
  2. 将 header 从模板文档复制到目标文档。
  3. 将页脚从模板文档复制到目标文档。

重要提示:

作为重要的一点,在当前阶段,不幸的是,当 header 和页脚被 Google 文档服务的 getHeader()getFooter() 检索时无法识别第 1 页 header 的检查是否启用和禁用。因此,在此示例脚本中,headers 和页脚无论是否检查第一页 header 都会被覆盖。

示例脚本:

请将以下脚本复制粘贴到脚本编辑器,并设置templateDocumentIdfolderId的值,然后运行main().

function getObjs(dstDoc, key) {
  if (!dstDoc.getHeader()) dstDoc.addHeader();  // Added
  if (!dstDoc.getFooter()) dstDoc.addFooter();  // Added

  var dd = dstDoc.getHeader().getParent();
  var cc = dd.getNumChildren();
  const objs = [];
  for (let i = 0; i < cc; i++) {
    if (dd.getChild(i).getType() == DocumentApp.ElementType[key == "header" ? "HEADER_SECTION" : "FOOTER_SECTION"]) {
      objs.push(dd.getChild(i)[key == "header" ? "asHeaderSection" : "asFooterSection"]());
    }
  }
  return objs;
}

function copyFooter(tempDoc, dstDoc) {
  getObjs(dstDoc, "footer").forEach(dstFooter => {
    dstFooter.clear();
    const d = tempDoc.getFooter();
    const c = d.getNumChildren();
    for (let i = 0; i < c; i++) {
      const child = d.getChild(i);
      const type = child.getType();
      if (type == DocumentApp.ElementType.PARAGRAPH) {
        dstFooter.insertParagraph(i, child.copy().asParagraph());
      } if (type == DocumentApp.ElementType.TABLE) {
        dstFooter.insertTable(i, child.copy().asTable());
      }
    }
  });
}

function copyHeader(tempDoc, dstDoc) {
  getObjs(dstDoc, "header").forEach(dstHeader => {
    dstHeader.clear();
    const d = tempDoc.getHeader();
    const c = d.getNumChildren();
    for (let i = 0; i < c; i++) {
      const child = d.getChild(i);
      const type = child.getType();
      if (type == DocumentApp.ElementType.PARAGRAPH) {
        dstHeader.insertParagraph(i, child.copy().asParagraph());
      } if (type == DocumentApp.ElementType.TABLE) {
        const table = child.copy().asTable();
        let imgObj = [];
        for (let r = 0, rows = table.getNumRows(); r < rows; r++) {
          const row = table.getRow(r);
          for (let c = 0, cols = row.getNumCells(); c < cols; c++) {
            const cell = row.getCell(c);
            for (let ce = 0, cc = cell.getNumChildren(); ce < cc; ce++) {
              if (cell.getChild(ce).getType() == DocumentApp.ElementType.PARAGRAPH) {
                const cp = cell.getChild(ce).asParagraph();
                for (let cee = 0, cpn = cp.getNumChildren(); cee < cpn; cee++) {
                  const ceec = cp.getChild(cee);
                  if (ceec.getType() == DocumentApp.ElementType.INLINE_IMAGE) {
                    const img = ceec.asInlineImage();
                    imgObj.push({child: cee, img: img, row: r, col: c, blob: img.getBlob(), width: img.getWidth(), height: img.getHeight()});
                    ceec.removeFromParent();
                  }
                }
              }
            }

          }
        }
        const dstTable = dstHeader.insertTable(i, table);
        if (imgObj.length > 0) {
          imgObj.forEach(({row, col, child, blob, width, height}) => dstTable.getCell(row, col).insertImage(child, blob).setWidth(width).setHeight(height));
        }
      }
    }
  });
}

// Please run this function.
function main() {
  const templateDocumentId = "###";  // Please set the template Document ID.
  const folderId = "###";  // Please set the folder ID.

  const tempDoc = DocumentApp.openById(templateDocumentId);
  const docs = DriveApp.getFolderById(folderId).getFilesByType(MimeType.GOOGLE_DOCS);
  while (docs.hasNext()) {
    const docId = docs.next().getId();
    const dstDoc = DocumentApp.openById(docId);
    copyHeader(tempDoc, dstDoc);
    copyFooter(tempDoc, dstDoc);
  }
}

注:

  • 此示例脚本假设根据您的回复评论,尽管您要使用数百个 Google 文档文件,但您将为每几个文档 运行 该脚本。请注意这一点。
  • 此示例脚本用于您的示例模板文档。因为我只有您的示例模板文档中的信息。当您更改模板文档的结构时,此脚本可能无法使用。请注意这一点。

参考文献: