如何使用占位符从模板创建新文档

时间:2019-10-29 15:53:15

标签: google-apps-script google-sheets

我正在尝试创建一个脚本,该脚本将从模板文档中创建新文档。根据特定列中的关键字搜索,用工作表中的数据替换文档中的占位符。然后更改特定列中的行的值,以使该脚本在再次运行时不再处理。

我认为使用第一个关键字搜索并遍历行是正确的。但是最后一部分使数据“合并”到占位符,我不知道该怎么做。我只是在文档中获得了“对象对象”值和其他值。

var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet();
var lastColumn = s.getLastColumn();
function createDocFromSheet() {
  var headers = getUpsertHeaders(s);//function is defined outside of this function

  var statusColNum = headers.indexOf('Status')+1;

  var row = getRowsData(s); //The function is defined outside this function.
  for (var i=0; i<row.length; i++) {
     var jobStatus = '';
     if (row[i]['Status'] === '') {

//New: write the status to the correct row and column - this will be moved to the end when I get the rest right
      var jobStatus = "Created";
      s.getRange(i+2, statusColNum).setValue(jobStatus);

//Find the template and make a copy. Activate the body of the new file.
      var templateFile = DriveApp.getFileById('1lkfmqsJMjjPujHqDqKtcDmL-5GMIxpOWTyCOaK29d2A');
      var copyFile = templateFile.makeCopy()      
      var copyId = copyFile.getId()
      var copyDoc = DocumentApp.openById(copyId)
      var copyBody = copyDoc.getActiveSection()

//Find the rows Values as an object.
      var rows = s.getRange(i+2,1,1,lastColumn)
      var rowsValues = rows.getValues();
Logger.log(rowsValues)
//Until here I think it's okay but the last part?

//HOW TO replace the text???
      for (var columnIndex = 0; columnIndex < lastColumn; columnIndex++) {
        var headerValue = headerRow[columnIndex]
        var rowValues = s.getActiveRange(i,columnIndex).getValues()
        var activeCell = rowsValues[columnIndex]
        //var activeCell = formatCell(activeCell);
Logger.log(columnIndex);

        copyBody.replaceText('<<' + headerValue + '>>', activeCell)
}

模板doc:Link 模板:Link

2 个答案:

答案 0 :(得分:1)

您可以使用以下GAS代码来实现您的目标:

var DESTINATION_FOLDER_ID = 'YOUR_DESTINATION_FOLDER_ID';
var TEMPLATE_FILE_ID = 'YOUR_TEMPLATE_FILE_ID';

function fillTemplates() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var templateFile = DriveApp.getFileById(TEMPLATE_FILE_ID);
  var values = sheet.getDataRange().getDisplayValues();
  var destinationFolder = DriveApp.getFolderById(DESTINATION_FOLDER_ID);
  for (var i=1; i<values.length; i++) {
    var rowElements = values[i].length;
    var fileStatus = values[i][rowElements-1];
    if (fileStatus == 'Created') continue;
    var fileName = values[i][0];
    var newFile = templateFile.makeCopy(fileName, destinationFolder);
    var fileToEdit = DocumentApp.openById(newFile.getId());
    for (var j=1; j<rowElements-1; j++) {
      var header = values[0][j];
      var docBody = fileToEdit.getBody();
      var patternToFind = Utilities.formatString('<<%s>>', header);
      docBody.replaceText(patternToFind, values[i][j]); 
    }
    sheet.getRange(i+1, rowElements).setValue('Created');
  }
}

您只需要适当地替换第一行和第二行。请同时考虑代码将假定第一列为file name,最后一列为status。您可以在中间插入任意多的列。

答案 1 :(得分:1)

经过一些编码后,我最终得到了这段代码来自动处理所有内容。 再次感谢@ carlesgg97。

我现在唯一不知道的事情是如何使用带有动态占位符的模板(如文档中的模板)从模板生成电子邮件正文。如何生成var patternToFind-但针对电子邮件正文?

我已经尝试过for(var ....,就像文档中一样,但是输出不会替换占位符。

var DESTINATION_FOLDER_ID = '1inwFQPmUu1ekGGSB5OnWLc_8Ac80igK0';
var TEMPLATE_FILE_ID = '1lkfmqsJMjjPujHqDqKtcDmL-5GMIxpOWTyCOaK29d2A';

function fillTemplates() {
//Sheet variables
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data');
  var values = sheet.getDataRange().getDisplayValues();
//Header variables
  var headers = sheet.getDataRange().getValues().shift();
  var idIndex = headers.indexOf('ID');
  var nameIndex = headers.indexOf('Name');
  var emailIndex = headers.indexOf('Email');
  var subjectIndex = headers.indexOf('Subject');
  var statusIndex = headers.indexOf('Status');
  var fileNameIndex = headers.indexOf('File Name');
  var filerIndex = headers.indexOf('Filer');
  var birthIndex = headers.indexOf('Date of birth');
  //Logger.log(statusIndex)
//Document Templates ID
  var templateFile = DriveApp.getFileById(TEMPLATE_FILE_ID);
//Destination
  var destinationFolder = DriveApp.getFolderById(DESTINATION_FOLDER_ID);

var templateTextHtml = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Email').getRange('D11').getValue();

//Run through the variables
for (var i=1; i<values.length; i++) {
//If first column is empty then stop
  var index0 = values[i][0];
  if(index0 == "") continue;
    var rowElements = values[i].length;
    var fileStatus = values[i][statusIndex];
//If the row already processed then stop
  if (fileStatus == "Created") continue;
//If the row is not processed continue
//Define the new filename by the relevant Column
    var fileName = values[i][fileNameIndex];
    var newFile = templateFile.makeCopy(fileName, destinationFolder);
    var fileToEdit = DocumentApp.openById(newFile.getId());
//Replace placeholders in the new document
  for (var j=1; j<rowElements-1; j++) {
      var header = values[0][j];
      var docBody = fileToEdit.getBody();
      var patternToFind = Utilities.formatString('{{%s}}', header);
      docBody.replaceText(patternToFind, values[i][j]); 
     }

//Create the PDF file
      fileToEdit.saveAndClose();
      var newPdf = DriveApp.createFile(fileToEdit.getAs('application/pdf'));
      DriveApp.getFolderById(DESTINATION_FOLDER_ID).addFile(newPdf);
      DriveApp.getRootFolder().removeFile(newPdf);
      newFile.setTrashed(true);
      var newPdfUrl = newPdf.getUrl();

//Create the emailbody  
  var textBodyHtml = templateTextHtml.replace("{{Name}}",values[i][nameIndex]).replace("{{Date of birth}}",values[i][birthIndex]);
  var textBodyPlain = textBodyHtml.replace(/\<br>/mg,"");

//Will send email to email Column
    var email = values[i][emailIndex];
    var emailSubject = values[i][idIndex]+" - "+values[i][fileNameIndex]+" - "+values[i][nameIndex];
    MailApp.sendEmail(email,emailSubject,textBodyPlain,     
    {
    htmlBody: textBodyHtml+
              "<p>Automatic generated email</p>",
    attachments: [newPdf],
    });    

      sheet.getRange(i+1, filerIndex+1).setValue(newPdfUrl);
      sheet.getRange(i+1, statusIndex+1).setValue('Created');

  }//Close for (var i=1...

}