使用存储在 Google Drive 中的特定命名图像和电子表格中的数据自动填充 Google Docs 文档

问题描述 投票:0回答:2

我有一个基于 Apps Script 的订阅表格,它允许我收集订阅者的个人数据和签名。当用户提交表单时,数据被发送到电子表格,签名存储在特定文件夹中,并以提交 ID 命名,该 ID 与 Google 表格中导入的数据的 ID 相同。

我需要使用从 Google 表格电子表格中提取的数据和从 Google Drive 中指定名称的图像自动填充 Google Docs 文档。然后,Google Docs 文档将转换为 PDF。

这是spreadsheet的截图。

这是signature folder的截图。

这是Google Docs template document的截图。

以下是我用来从 Google Docs 文件生成 PDF 的代码,该文件填充了从 Google Sheets 电子表格中提取的数据。

function createBulkPDFs() {

const docFile = DriveApp.getFileById("1ZxvyViklifScfOt90YX4R-NgOTbO044rUSeyQfVCzds");
const tempFolder = DriveApp.getFolderById("1yFLVyTtb6tW-UGdf1hkKHdzGIKG7qg2W");
const pdfFolder = DriveApp.getFolderById("1YGG1Y_u2jOMbfSIh3Ajb4kKGU-tg2oWK");
const currentSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Responses");

const data = currentSheet.getRange(2, 1,currentSheet.getLastRow()-1,15).getDisplayValues();

let errors = [];
data.forEach(row => {
  try{
  createPDF (row[2],row[3],row[7],row[8],row[4],row[9],row[12],row[10],row[11],row[5],row[6],row[13],row[1],row[0],row[2],docFile,tempFolder,pdfFolder);
  errors.push(["Completata"]);
  } catch(err){
    errors.push(["Fallita"]);
  }
});

currentSheet.getRange(2, 16,currentSheet.getLastRow()-1,1).setValues(errors);

}

function createPDF (name,surname,placebirth,daybirth,gender,street,zipcode,city,province,email,phone,instagram,id,timestamp,pdfName,docFile,tempFolder,pdfFolder) {
 
// ID Template Modulo di Iscrizione: 1ZxvyViklifScfOt90YX4R-NgOTbO044rUSeyQfVCzds
// ID tempFolder: 1yFLVyTtb6tW-UGdf1hkKHdzGIKG7qg2W
// ID pdfFolder: 1YGG1Y_u2jOMbfSIh3Ajb4kKGU-tg2oWK

const tempFile = docFile.makeCopy(tempFolder);
const tempDocFile = DocumentApp.openById(tempFile.getId());
const body = tempDocFile.getBody();
body.replaceText("{name}", name);
body.replaceText("{surname}", surname);
body.replaceText("{placebirth}", placebirth);
body.replaceText("{daybirth}", daybirth);
body.replaceText("{gender}", gender);
body.replaceText("{street}", street);
body.replaceText("{zipcode}", zipcode);
body.replaceText("{city}", city);
body.replaceText("{province}", province);
body.replaceText("{email}", email);
body.replaceText("{phone}", phone);
body.replaceText("{instagram}", instagram);
body.replaceText("{timestamp}", timestamp);
body.replaceText("{id}", id);
tempDocFile.saveAndClose();
const pdfContentBlob = tempFile.getAs(MimeType.PDF);
pdfFolder.createFile(pdfContentBlob).setName(pdfName);
tempFile.setTrashed(true);

}

现在我还需要检索签名图像文件并将其放入 Google Docs 文件中。

想法是,脚本应该搜索以特定 ID 命名的图像,并将其放在 Google 文档文件中,替换文本占位符 {signature}。

有办法实现吗?

非常感谢!

编辑:

在实施 Tanaike 的代码建议后,脚本现在成功编辑 Doc 文件并用数据和签名图像填充它。

然而,它并没有将文件转换为 PDF。

这是当前状态下的代码。

function createBulkPDFs() {

const docFile = DriveApp.getFileById("1ZxvyViklifScfOt90YX4R-NgOTbO044rUSeyQfVCzds");
const tempFolder = DriveApp.getFolderById("1yFLVyTtb6tW-UGdf1hkKHdzGIKG7qg2W");
const pdfFolder = DriveApp.getFolderById("1YGG1Y_u2jOMbfSIh3Ajb4kKGU-tg2oWK");
const currentSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Responses");

const data = currentSheet.getRange(2, 1,currentSheet.getLastRow()-1,15).getDisplayValues();

let errors = [];
data.forEach(row => {
  try{
  createPDF (row[2],row[3],row[7],row[8],row[4],row[9],row[12],row[10],row[11],row[5],row[6],row[13],row[1],row[0],row[0]+" "+row[2]+" "+row[3],docFile,tempFolder,pdfFolder);
  errors.push(["Completata"]);
  } catch(err){
    errors.push(["Fallita"]);
  }
});

currentSheet.getRange(2, 16,currentSheet.getLastRow()-1,1).setValues(errors);

}

function createPDF (name,surname,placebirth,daybirth,gender,street,zipcode,city,province,email,phone,instagram,id,timestamp,pdfName,docFile,tempFolder,pdfFolder) {
 
// ID Template Modulo di Iscrizione: 1ZxvyViklifScfOt90YX4R-NgOTbO044rUSeyQfVCzds
// ID tempFolder: 1yFLVyTtb6tW-UGdf1hkKHdzGIKG7qg2W
// ID pdfFolder: 1YGG1Y_u2jOMbfSIh3Ajb4kKGU-tg2oWK

const tempFile = docFile.makeCopy(tempFolder);
const tempDocFile = DocumentApp.openById(tempFile.getId());
const body = tempDocFile.getBody();

body.replaceText("{name}", name);
body.replaceText("{surname}", surname);
body.replaceText("{placebirth}", placebirth);
body.replaceText("{daybirth}", daybirth);
body.replaceText("{gender}", gender);
body.replaceText("{street}", street);
body.replaceText("{zipcode}", zipcode);
body.replaceText("{city}", city);
body.replaceText("{province}", province);
body.replaceText("{email}", email);
body.replaceText("{phone}", phone);
body.replaceText("{instagram}", instagram);
body.replaceText("{timestamp}", timestamp);
body.replaceText("{id}", id);

const imageFolderId = "1mdJbbG_0aF8wjEIuVPsMr9jV31wPINRk"; // Please set the folder ID of your "signatureFolder".
const filename = id; // or id
const files = DriveApp.getFolderById(imageFolderId).getFilesByName(filename);
let image;
if (files.hasNext()) {
  image = files.next().getBlob();
} else {
  throw new Error(`No file of "${filename}"`);
}
do {
  const width = 200;
  const next = body.findText("{signature}");
  if (!next) break;
  const r = next.getElement();
  r.asText().setText("");
  var img = r.getParent().asParagraph().insertInlineImage(0, image);
  if (width && typeof width == "number") {
    img.setWidth(width);
    img.setHeight(width * img.getHeight() / img.getWidth());
  }
} while (next);


tempDocFile.saveAndClose();
const pdfContentBlob = tempFile.getAs(MimeType.PDF);
pdfFolder.createFile(pdfContentBlob).setName(pdfName);
tempFile.setTrashed(true);




}
google-apps-script google-sheets pdf-generation google-docs
2个回答
0
投票

我相信你的目标如下。

  • 您想用从 Google 文档中“signatureFolder”文件夹中检索到的图像替换
    {sigunature}
    的文本。

当你的脚本被修改时,下面的修改怎么样?在这种情况下,请修改函数

createPDF
如下。

来自:

body.replaceText("{id}", id);
tempDocFile.saveAndClose();

致:

body.replaceText("{id}", id);

// --- I added below script.
const imageFolderId = "###"; // Please set the folder ID of your "signatureFolder".
const filename = id; // or `${id}.png`;
const files = DriveApp.getFolderById(imageFolderId).getFilesByName(filename);
let image;
if (files.hasNext()) {
  image = files.next().getBlob();
} else {
  throw new Error(`No file of "${filename}"`);
}
let next;
do {
  const width = 200;
  next = body.findText("{signature}");
  if (!next) break;
  const r = next.getElement();
  r.asText().setText("");
  var img = r.getParent().asParagraph().insertInlineImage(0, image);
  if (width && typeof width == "number") {
    var w = img.getWidth();
    var h = img.getHeight();
    img.setWidth(width);
    img.setHeight(width * h / w);
  }
} while (next);
// ---

tempDocFile.saveAndClose();

注:

  • 使用本脚本前,请先设置

    imageFolderId
    。这是您的“signatureFolder”的文件夹 ID。

  • 另外,请检查每个图像的文件名。不幸的是,我不知道您的实际文件名。所以,从你的显示图像,我猜你的文件名可能是

    id1.png
    id1
    。所以,请根据您的实际情况修改
    const filename = `${id}.png`; // or id

    • 如果文件名是
      id1.png
      ,请使用
      const filename = `${id}.png`;
      .
    • 如果文件名是
      id1
      ,请使用
      const filename = id;
      .
  • 如果出现类似

    No file of ###
    的错误,请再次检查文件名。

  • 并且,

    const width = 200;
    是插入图像的图像大小。请根据您的实际情况进行修改。


0
投票

@alecanc @Tanaike

请协助,我是 App Script 的新手。

电子表格截图:enter image description here

签名文件夹截图:enter image description here

Google Docs模板文档截图:enter image description here

我试过下面的代码。将文本数据传输到文档工作正常。我尝试嵌入您的代码以复制图像和转换 pdf 但不幸的是,它在保存/运行时向我显示错误。

  function onOpen() {
  const ui = SpreadsheetApp.getUi();
  const menu = ui.createMenu('AutoFill Google Docs');
  menu.addItem('Create New Document', 'createNewGoogleDocs')
  menu.addToUi();
}
function createNewGoogleDocs() {
  //This value should be the id of your document template that we created in the last step
  const googleDocTemplate = DriveApp.getFileById('1PebaPawQZLDJEDk08k7jBwzhuMhb3bV8MnPlRqt00ic');
  
  //This value should be the id of the folder where you want your completed documents stored
  const destinationFolder = DriveApp.getFolderById('1AloGBEiLMAZP-eTzgutbU6jRVOJH2szV')
  //Here we store the sheet as a variable
  const sheet = SpreadsheetApp
    .getActiveSpreadsheet()
    .getSheetByName('Sheet1')
  
  //Now we get all of the values as a 2D array
  const rows = sheet.getDataRange().getValues();
  
  //Start processing each spreadsheet row
  rows.forEach(function(row, index){
    //Here we check if this row is the headers, if so we skip it
    if (index === 0) return;
    //Here we check if a document has already been generated by looking at 'Document Link', if so we skip it
    if (row[11]) return;
    //Using the row data in a template literal, we make a copy of our template document in our destinationFolder
    const copy = googleDocTemplate.makeCopy(`${row[0]} Employee Details` , destinationFolder)
    //Once we have the copy, we then open it using the DocumentApp
    const doc = DocumentApp.openById(copy.getId())
    //All of the content lives in the body, so we get that for editing
    const body = doc.getBody();
    //In this line we do some friendly date formatting, that may or may not work for you locale
    const friendlyDate = new Date(row[3]).toLocaleDateString();
    
    //In these lines, we replace our replacement tokens with values from our spreadsheet row
    body.replaceText('{{Name}}', row[0]);
    body.replaceText('{{Email}}', row[1]);
}

请让我知道我怎样才能达到同样的效果。如果可能的话,请提及我需要创建的额外文件夹。因为,使用上面的代码,我只在名为“DEMO”的文件夹上创建以保存 docx 文件。如果驱动器有像 id.png 这样的图像,在代码中使用 const filename 的内容。非常感谢。

© www.soinside.com 2019 - 2024. All rights reserved.