使用RegEx将文档中的标记替换为电子表格中的列数据

时间:2015-10-21 00:45:04

标签: javascript regex google-apps-script google-sheets google-docs

我一直在寻找这个问题的答案,但到目前为止还没能把答案拼凑起来。请以非常简单的方式解释您的任何答案,因为我对GAS和RegEx相当新。我已经掌握了大部分语法,但在GAS中执行它会给我带来困难。

基本上,我想编写一个脚本,在编辑电子表格时,检查哪些行尚未合并。然后,在这些行上创建模板Google Doc的副本,并根据电子表格数据命名文档。从那里(这是困难的部分),我需要它用模板中的数据替换模板中的合并标签。

我将使用的模板中的代码如下所示:<<mergeTag>>

我的想法是匹配整个代码,并将其替换为列中存在的电子表格中的数据,其名称与&#34; <<>>&#34;中的内容相同。 。例如:<<FooBar>>将替换为名为FooBar的列中的数据。显然,它来自当前行需要合并。

之后,剩下的就是发送一封电子邮件(还有一些特定于行的个性化),附上该文件(有时是PDF格式),邮件正文来自其他地方的HTML文件该项目。

这是我到目前为止所做的全部事情(请注意我在这里和那里的占位符,我可以为我使用的每个电子表格进行个性化):

function onEdit() {
  //SPREADSHEET GLOBAL VARIABLES

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  //get only the merge sheet
  var sheet = ss.getSheetByName("Merge Data");
  //get all values for later reference
  var range = sheet.getActiveRange();
  var values = range.getValues();
  var lastRow = range.getLastRow();
  var lastColumn = range.getLastColumn();

  //get merge checker ranges
  var urlColumn = range.getLastColumn();
  var checkColumn = (urlColumn - 1);
  var checkRow = range.getLastRow();
  var checkRange = sheet.getRange(2, checkColumn, checkRow);
  var check = checkRange.getBackgrounds();

  //get template determination range (unique to each project)
  var tempConditionRange = sheet.getRange(row, column);
  var tempConditionCheck = tempConditionRange.getValues();

  //set color variables for status cell
  var red = "#FF0000";
  var yellow = "#FFCC00";
  var green = "#33CC33";

  //////////////////////////////////////////////////////////
  //DOC GLOBAL VARIABLES

  var docTemplate1 = DriveApp.getFileById(id);
  var docTemplate2 = DriveApp.getFileById(id);
  var docTemplate3 = DriveApp.getFileById(id);
  var folderDestination = DriveApp.getFolderById(id);

  //////////////////////////////////////////////////////////
  //EMAIL GLOBAL VARIABLES
  var emailTag = ss.getRangeByName("Merge Data!EmailTag");
  var personalizers = "";
  var subject = "" + personalizers;
  var emailBody = HtmlService.createHtmlOutputFromFile("Email Template");

  //////////////////////////////////////////////////////////
  // MERGE CODE

  for (i = 0; i < check.length; i++) {
    //for rows with data, check if they have already been merged
    if (check[i] == green) {
       continue;
    } else {
      var statusCell = sheet.getRange((i+2), checkColumn, 1, 1);
      var urlCell = sheet.getRange((i+2), urlColumn, 1, 1);
      var dataRow = sheet.getRange((i+2), 1, lastRow, (lastColumn - 2))
      statusCell.setBackground(red);
      //for rows with data, but not yet merged, perform the merge code

  //////////////////////////////////////////////////////////
  //DOC CREATION

  //Determine which template to use
  if (tempConditionCheck[i] == "") {
    var docToUse = docTemplate1;
  }
  if (tempConditionCheck[i] == "") {
    var docToUse = docTemplate2;
  }
  if (tempConditionCheck[i] == "") {
    var docToUse = docTemplate3;
  }

  //Create a copy of the template
  //Rename the document using data from specific columns, at specific rows
  //Move the doc to the correct folder
  var docName = "";
  var docCopy = docToUse.makeCopy(docName, folderDestination);
  var docId = docCopy.getId();
  var docURL = docCopy.getUrl();
  var docToSend = DriveApp.getFileById(docId);
  var docBody = DocumentApp.openById(docId).getBody();

这是我需要帮助的地方

  //Locate the Merge Tags
  //Match Merge Tags to the column headers of the same name
  //Replace the Merge Tags with the data from the matched column, from the correct row
  function tagReplace() {
    var tagMatch = "/(<{2}(\w+)>{2})/g";
  }


  statusCell.setBackground(yellow);
  urlCell.setValue(docURL);

其余的只是完成了这个过程

      //////////////////////////////////////////////////////////
      //EMAIL CREATION

      //Create an email using an HTML template
      //Use Merge Tags to personalize email
      //Attach the doc we created to the email
      //Send email to recipients based on data in the sheet
      MailApp.sendEmail(emailTag, subject, emailBody, {
        name: "Person McPerson",
        attachments: [docToSend], //[docToSend.getAs(MIME.PDF)],
        html: emailBody,
      });

      //////////////////////////////////////////////////////////
      //CHECK ROW UPDATE
      statusCell.setBackground(green);

    }
  }
}

我的工作表都有一个冻结的第一行作为标题行。我的所有列都将始终与标记完全相同(减去<<>>)。

如何将标签与数据匹配?

修改
```````````````````
当我将其插入到我的代码中时,解决方案无法正常工作,如下所示:

function formMerge() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("Merge Data");
  var urlColumn = sheet.getMaxColumns();
  var checkColumn = urlColumn - 1;
  var lastRow = ss.getSheetByName("Form Responses").getLastRow();
  var values = sheet.getDataRange().getValues();
  var headers = values[0];

  var urlRange = sheet.getRange(2, urlColumn, lastRow);
  var checkRange = sheet.getRange(2, checkColumn, lastRow);
  var check = checkRange.getBackgrounds();

  var red = "#ff0404";
  var yellow = "#ffec0a";
  var green = "#3bec3b";

  var docTemplate = DriveApp.getFileById(id);
  var folderDestination = DriveApp.getFolderById(id);

  // MERGE CODE
  for (i = 0; i < check.length; i++) {
    if (check[i] == green) {
      continue;
    } else {
      var statusCell = sheet.getRange((i+2), checkColumn, 1, 1);
      var urlCell = sheet.getRange((i+2), urlColumn, 1, 1);
      var dataRow = sheet.getRange((i+2), 1, 1, (urlColumn - 2)).getValues();
      var clientNameRange = sheet.getRange((i+2), 3);
      var clientName = clientNameRange.getValue();
      var dateRange = sheet.getRange((i+2), 2);
      var datePreFormat = dateRange.getValue();
      var timeZone = CalendarApp.getTimeZone();
      var date = Utilities.formatDate(new Date(datePreFormat), timeZone, "MM/dd/yyyy");
      statusCell.setBackground(red);

      //EMAIL VARIABLES
      var personalizers = clientName;
      var subject = "Post Intake Report for " + personalizers;
      var emailBody = "Please see the attached Google Doc for the Post Intake Report for " + clientName + ". The intake was performed on " + date + ".";
      var emailTagRange = sheet.getRange((i+2), 24);
      var emailTagValue = emailTagRange.getValue();
      var emailTag = emailTagValue.split(", ");

      //DOC CREATION
      var docToUse = docTemplate;
      var docName = "Post Intake Report - " + clientName + " [" + date + "]";
      var docCopy = docToUse.makeCopy(docName, folderDestination);
      var docId = docCopy.getId();
      var docURL = docCopy.getUrl();
      var docBody = DocumentApp.openById(docId).getBody().editAsText();

      for (var j=0; j<headers.length; j++) {
        var re = new RegExp("(<<"+headers[j]+">>)","g");
        docBody.replaceText(re, dataRow[j]);
      }
      statusCell.setBackground(yellow);
      urlCell.setValue(docURL);

      //EMAIL CREATION
      MailApp.sendEmail(emailTag, subject, emailBody, {
        name: "Christopher Anderson",
        attachments: [docCopy],
        html: emailBody
      });
      statusCell.setBackground(green);
    }
  }
}

1 个答案:

答案 0 :(得分:1)

使用电子表格中的标题值动态为每个标记构建RegExp。 使用Body.replaceText()执行替换。

var values = sheet.getDataRange().getValues();
var headers = values[0];

...

// Loop over all columns. Use header names to search for tags.
for (var col=0; col<headers.length; col++) {
  // Build RegExp using column header
  var re = new RegExp("(<{2}"+headers[col]+">{2})","g");
  // Replace tags with data from this column in dataRow
  body.replaceText(re, dataRow[col]);
}

此代码段将在单行上运行;前几个声明应出现在行循环之外。然后在创建并打开新文档后完成列循环,并获取body对象。

它遍历电子表格中的所有列,使用标题名称查找您定义的标记,并将其替换为当前行的相应单元格内容。