Google Apps 脚本 - 回调 webapp 中使用的 class 方法

Google Apps Script - Callback for class methods used in webapp

我有一个 GAS,我要在我的网络应用程序中向其提交表格。它执行以下操作:

  1. 打开一个包含占位符(格式为##form_field_name##)的模板文档,对应于表单上的表单域名称
  2. 复制模板并将其保存到适当的位置
  3. 遍历提交的值并执行 body.replaceText('##' + key + '##', val); 将值填充到文档中
  4. body.replaceText('##.*##', ''); 删除任何留空字段的占位符字符串(因为它们当前未与表单一起提交)

我最终得到一份文档,该文档看起来用户根本没有提交任何数据。我的猜测是,这是因为 #4 在 #3 完成之前 运行ning。有没有办法将#4 指定为回调?类似于:

body.replaceText('##' + key + '##', val, () => {
    body.replaceText('##.*##', '');
});

这是执行 replaceText()ing 的函数的代码:

/**
 * Iterate through obj of keys/values and replace ##key## 
 * with value in doc 
**/
function doFindAndReplace(obj, doc) {
  try {
    //body = doc.getBody();
    var id = doc.getId();
    var _doc = DocumentApp.openById(id);
    var body = _doc.getBody();
    //var doc = _doc;
    //Logger.log(body);
    for (var prop in obj) {
      if(obj.hasOwnProperty(prop)) {
        var val = obj[prop];
        var key = prop.indexOf('intake') === 0 ? prop.toUpperCase() : '';
        //Logger.log(key + ' = ' + val);
        //Logger.log(typeof val);
        body.replaceText('##' + key + '##', val);
        _doc.saveAndClose();
        var _doc2 = DocumentApp.openById(id);
        body = _doc2.getBody();
        body.replaceText('##.*##', '');
      }
    }
  } catch(e) {
    Logger.log('doFindAndReplace() | ' + e);
    errors.push({ 
      fxn: 'doFindAndReplace', 
      msg: e, 
      custom: 'id=' + id
    });
    return false;
  }
  return doc;
}

参数 obj 是一个包含提交的表单数据的对象,doc 是对新创建的文档的引用,在该文档中进行查找和替换。

如果没有那样的可能,我正在考虑添加一个 运行 #4 (body.replaceText('##.*##', '');) 的 onOpen 触发器。这将要求用户在在线时首次打开文档,并且大部分用例是离线使用新创建的文档。

任何人都可以提出另一种解决方法吗?


** **编辑** **
我将我的代码(如上所示)更新为 `saveAndClose()`,然后在 运行 执行第二个 `replaceText()` 之前重新打开。我收到以下错误:

Document is closed, its contents cannot be updated

我知道,您会认为它会在 saveAndClose() 之后出现。但是错误指向的那一行,即使我删除了它之后的其余行,也会发生同样的错误。

如果我按原样删除带有代码的 saveAndClose() 行,我又会遇到原来的问题。

我认为这与

不是同一个问题
** **编辑 2** **
这是传递给函数的对象的示例:
{
intake_activity_level: "Normal",
intake_assessment_comments: "",
intake_client_addr: "1600 Fake St XXXX, XX 12345",
intake_client_email: "xxx@gmail.com",
intake_client_name: "Dan Tester",
intake_client_phone: "(917) 555-1212", 
intake_consent: "yes", 
intake_consent_owner: "Jim David",
intake_food_intake: "Decreased",
intake_gen_food: "",
intake_gen_health: "sit dolam amet",
intake_gen_meds: "re et sapien et, consectetur rhoncus lacus. Aliqua Vivamus ipsum diam, venenatis a turpis eget, volu",
intake_gen_reasons: "Lorem ipsum",
intake_gen_vaccine: "Yes",
intake_misc_comments: "",
intake_misc_descriptor: "wood",
intake_panting: "Increased",
intake_pet_breed: "Pug",
intake_pet_dob: "8/11/2015",
intake_pet_name: "FLuffy",
intake_pet_sex: "Spayed Female",
intake_pet_species: "Dog",
intake_pet_weight: "140lbs",
intake_sleep: "Increased",
intake_source: "Sally Balls",
intake_stiffness: "Normal",
intake_symptoms: "coughing, belching or gas",
intake_vet: "Urban Vet",
intake_voice: "Increased",
intake_water_intake: "Decreased"
}

并且可以访问文档的简化版本 here

  • 您想使用 obj'##' + key + '##' 替换为 va;body.replaceText('##' + key + '##', val);
  • 您想将 ##.*## 替换为 ''body.replaceText('##.*##', '');
  • 你想要 运行 body.replaceText('##.*##', ''); 毕竟 body.replaceText('##' + key + '##', val); 是 运行.

如果我的理解是正确的,这个答案怎么样?

在您当前的脚本中,body.replaceText('##.*##', ''); 被放入 for 循环中。这样,只使用 intake_activity_level: "Normal", ,不使用其他对象。在这种情况下,在第一个 body.replaceText('##' + key + '##', val); 是 运行 之后,所有 ##key## 值都被 body.replaceText('##.*##', ''); 删除。我认为这可能是您遇到问题的原因。

修改后的脚本:

当您的脚本修改时,请修改如下。

从:
for (var prop in obj) {
  if(obj.hasOwnProperty(prop)) {
    var val = obj[prop];
    var key = prop.indexOf('intake') === 0 ? prop.toUpperCase() : '';
    //Logger.log(key + ' = ' + val);
    //Logger.log(typeof val);
    body.replaceText('##' + key + '##', val);
    _doc.saveAndClose();
    var _doc2 = DocumentApp.openById(id);
    body = _doc2.getBody();
    body.replaceText('##.*##', '');
  }
}
到:
for (var prop in obj) {
  if(obj.hasOwnProperty(prop)) {
    var val = obj[prop];
    var key = prop.indexOf('intake') === 0 ? prop.toUpperCase() : '';
    body.replaceText('##' + key + '##', val);
  }
}
body.replaceText('##.*##', '');
  • 在这个修改中,首先,body.replaceText('##' + key + '##', val);在for循环中是运行。然后,body.replaceText('##.*##', ''); 是 for 循环外的 运行。

注:

  • 如果需要saveAndClose(),在body.replaceText('##.*##', '');之后加上doc.saveAndClose()怎么样?