使用 Google 脚本创建和/或更新邮件合并 Google 文档
Posted
技术标签:
【中文标题】使用 Google 脚本创建和/或更新邮件合并 Google 文档【英文标题】:Creating and/or update mail merge Google document using Google Script 【发布时间】:2021-03-11 21:21:16 【问题描述】:(Continuation of another thread)
我目前有一个 Google 表格,其中包含要使用模板文件合并到 Google 文档中的数据行。每行都将根据模板的布局生成一个新的 Google 文档。我当前正在运行的脚本将检查是否已经存在与 Google 表格行相关的文件(使用标题单元格进行匹配)。如果是这样,那么它将被删除,并在其位置创建一个新文档,其中包含在 Google 表格中所做的所有更改。如果它不存在,将创建一个新文档。
但是,我现在需要从外部网站链接到这些 Google 文档。使用当前脚本,这意味着如果对电子表格中的一行进行了更改,则相应的文档将被删除并重新创建,连同它的 URL,从而使网站链接无用,需要手动更改。
因此,理想情况下,我想要实现的不是删除和重新创建文档,而是更新同一个文档(如果它已经存在)。这样,文档会得到更新,并且 URL 将始终保持不变。
目前的脚本是这样的
/*###################################################################
* Create multiple versions of a document based on Google Sheet Data
* and a Google Doc Template (Mailmerge)
*###################################################################
*/
/*###################################################################
* Main run file sets up variables for insertion into the mailMerge()
* function.
*/
function mergeSheetDoc()
const TEMPLATE_ID = '16YfyeDjGDp-88McAtLCQQyZ1xz4QX5zEKAS09SaLkJI';//Add your Google Doc template ID
const SS_ID = '1C5gtJCSzHMuSz-oVWEItl2EUVRDwF5iH_RVr6BxLkOU'; // Add your Google Sheet ID
const SHEET_NAME = "data"; // Add your Google Sheet Tab name
const MAPPED = mappedDocToSheet; // Go to Map.gs to update
const FILE_NAME = ["Titre de la formation"] // Header IDs from your Sheet. Change to make your own file name.
docMerge(TEMPLATE_ID,SS_ID,SHEET_NAME,MAPPED, FILE_NAME);
/** ###################################################################
* Merges data from a Google Sheet into a newly created doc based on a
* Google Doc template.
*
* param string templateID: The id from the Google Doc template.
* param string ssID: The id of the Google Sheet.
* param string sheetName: the name of the sheet tab you are referencing.
* param object mapped: Object array of data you mapped from your Doc template against your Google Sheet headers
* param array fileNameDara: An array of data used to generate the file name.
* param string rowLen: (optional) If you want to add a number rows to create your merged documents.
*/
function docMerge(templateID,ssID, sheetName, mapped, fileNameData, rowLen = "auto")
//Get the Spreadsheet and sheet tab
const ss = SpreadsheetApp.openById(ssID);
const sheet = ss.getSheetByName(sheetName);
//Get number of rows to process
rowLen = (rowLen = "auto") ? getRowLen() : rowLen;
//Gets the range of data in the sheet then grabs the values of the range
const range = sheet.getRange(1,1,rowLen,sheet.getDataRange().getNumColumns());
const matrix = range.getValues();
// Searches the file mapped object and finds the corresponding number returns the column number in an array.
const fileNameRows = getFileNameRows()
//Loops through each row of the sheet grabbing the data from each row and putting it into a new doc.
for(let i = 1; i < rowLen; i++)
let row = matrix[i];
//Get the title for the file.
let fileName = buildFileName(row);
//This query parameter will search for an exact match of the filename with Doc file type
let params = "title='"+fileName+"' and mimeType = 'application/vnd.google-apps.document'"
let files = DriveApp.searchFiles(params);
if(files.hasNext())
while (files.hasNext())
//Filename exist
var file = files.next();
//Create a new file
var tmpDoc = DriveApp.getFileById(templateID).makeCopy("tempfile");
//Update the file
updateFileData(row, tmpDoc.getId());
//Copy contents of the new file to the existing file
copyFileData(tmpDoc.getId(), file.getId());
//Delete temporary file
tmpDoc.setTrashed(true);
else
//Create a new file
let newDoc = DriveApp.getFileById(templateID).makeCopy(fileName);
updateFileData(row, newDoc.getId());
;
function copyFileData(sourceDoc, destinationDoc)
var srcParagraph = DocumentApp.openById(sourceDoc).getBody().getParagraphs();
var dstParagraph = DocumentApp.openById(destinationDoc).getBody().getParagraphs();
for(var i = 0; i<dstParagraph.length; i++)
//Paragraph Index of description and suivantes information
if(i==5||i==21)
dstParagraph[i].editAsText().setText(srcParagraph[i].editAsText().getText());
dstParagraph[i].setAttributes(srcParagraph[i].getAttributes());
dstParagraph[i].setLeftToRight(true);
dstParagraph[i].setIndentFirstLine(srcParagraph[i].getIndentFirstLine());
dstParagraph[i].setIndentStart(srcParagraph[i].getIndentStart());
dstParagraph[i].editAsText().setFontSize(srcParagraph[i].editAsText().getFontSize());
此代码还引用了一个映射脚本,可在此处找到
https://textuploader.com/18xic
【问题讨论】:
【参考方案1】:解决方法总结:
如果文件名已经存在,则创建一个临时文档,用于替换模板文档中的 textId 标签 将临时文档的段落文本和属性复制到现有文档中。示例修改代码:
仅包含修改/新功能。
function docMerge(templateID,ssID, sheetName, mapped, fileNameData, rowLen = "auto")
//Get the Spreadsheet and sheet tab
const ss = SpreadsheetApp.openById(ssID);
const sheet = ss.getSheetByName(sheetName);
//Get number of rows to process
rowLen = (rowLen = "auto") ? getRowLen() : rowLen;
//Gets the range of data in the sheet then grabs the values of the range
const range = sheet.getRange(1,1,rowLen,sheet.getDataRange().getNumColumns());
const matrix = range.getValues();
// Searches the file mapped object and finds the corresponding number returns the column number in an array.
const fileNameRows = getFileNameRows()
//Loops through each row of the sheet grabbing the data from each row and putting it into a new doc.
for(let i = 1; i < rowLen; i++)
let row = matrix[i];
//Get the title for the file.
let fileName = buildFileName(row);
//This query parameter will search for an exact match of the filename with Doc file type
let params = "title='"+fileName+"' and mimeType = 'application/vnd.google-apps.document'"
let files = DriveApp.searchFiles(params);
if(files.hasNext())
while (files.hasNext())
//Filename exist
var file = files.next();
//Create a new file
var tmpDoc = DriveApp.getFileById(templateID).makeCopy("tempfile");
//Update the file
updateFileData(row, tmpDoc.getId());
//Copy contents of the new file to the existing file
copyFileData(tmpDoc.getId(), file.getId());
//Delete temporary file
tmpDoc.setTrashed(true);
else
//Create a new file
let newDoc = DriveApp.getFileById(templateID).makeCopy(fileName);
updateFileData(row, newDoc.getId());
;
function copyFileData(sourceDoc, destinationDoc)
var srcParagraph = DocumentApp.openById(sourceDoc).getBody().getParagraphs();
var dstParagraph = DocumentApp.openById(destinationDoc).getBody().getParagraphs();
for(var i = 0; i<dstParagraph.length; i++)
//Paragraph Index of description and suivantes information
if(i==5||i==21)
dstParagraph[i].editAsText().setText(srcParagraph[i].editAsText().getText());
dstParagraph[i].setAttributes(srcParagraph[i].getAttributes());
dstParagraph[i].setLeftToRight(true);
dstParagraph[i].setIndentFirstLine(srcParagraph[i].getIndentFirstLine());
dstParagraph[i].setIndentStart(srcParagraph[i].getIndentStart());
dstParagraph[i].editAsText().setFontSize(srcParagraph[i].editAsText().getFontSize());
它有什么作用?
-
如果找到文件名,请根据电子表格中的更新信息创建一个临时文档
将临时文档中的特定段落复制到现有文档中
使用setTrashed()方法删除临时文档。
【讨论】:
我似乎遇到了 docMerge 或 mergeSheetDoc 的以下错误“ReferenceError: getRowLen is not defined”。我已经修改了我的初始帖子以显示脚本我的结束 你需要包括你所有的功能,我没有把完整的代码放在答案中。我刚刚修改了 docMerge() 并定义了一个新函数 copyFileData() 我明白了,我可以看到它在工作,这太棒了。我现在将测试多行并进行测试,以便它为新行创建文档 注意,如果您遇到任何其他问题,请告诉我 似乎为新行创建新文档并使用更新的内容更新现有文档。它完全按照我的需要工作。再次感谢你。我非常感激。很高兴看到它工作。赞成并接受回答:)以上是关于使用 Google 脚本创建和/或更新邮件合并 Google 文档的主要内容,如果未能解决你的问题,请参考以下文章
Google网络应用/脚本,用于自动将文件上传到特定的g-drive文件夹
如何使用 Google Apps 脚本将 PDF 正文格式化为看起来像电子邮件?
发送个性化的Google应用脚本电子邮件导致我的电子邮件被禁用