如何在Javascript的For循环中调用Google Script函数

3
我有一个Google脚本函数,基于JavaScript的值填充单元格。 GS函数在JavaScript的“for”循环内部被调用。 当我运行代码时,直到所有“for”循环增量都完成运行,单元格才会被填充。
神奇的是,在for循环结束后,GS函数开始填充相关单元格(以某种方式记住了所有动态值)。然而,并非所有预期的单元格都被填充,也不是按正确顺序填充。
尝试使用.flush() - 没有帮助
GS函数:
function rolesInputer(role, i){
    var rolesInputer = role;
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
    var column = 3+i;
    var cell = sheet.getRange(17,column);
    cell.setValue(role);
}

JS函数:

function saveInput() {
    var i;
    for (i = 1; i <= dataEncoded; i++) {
        sleep(1000);
        var temprole = "role" + (i);
        var roleSelect = document.getElementById(temprole);
        var roleSelected = roleSelect.options[roleSelect.selectedIndex].value;
        google.script.run.withSuccessHandler(roleSelected, i).rolesInputer(roleSelected, i);
        alert("executed");
    }
    google.script.host.close();
}

手动刷新写缓冲区。此外,考虑实现批处理方法以一次性处理所有输入。 - tehhowch
可能是为什么要使用SpreadsheetApp.flush();?的重复问题。 - tehhowch
谢谢您的回复。我已经尝试在我的GS函数底部添加SpreadsheetApp.flush(),但它没有解决问题。我做错了什么吗?我会稍后研究优化,感谢您的建议。 - Ilya Perelman
我也很好奇为什么你会将非函数值传递给 withSuccessHandler。建议查看 google.script.run 客户端 API 的文档。 - tehhowch
1个回答

3
您想使用 google.script.run() 将HTML端的值发送到Google Apps Script端。
如果我理解得不错的话,您需要进行以下修改:由于google.script.run()是异步处理的原因,导致您遇到了问题。
为了避免这种情况,我认为有两种方法适用于您的情况。
Pattern 1:
在此模式中,获取所有值后将其发送到Google Apps Script。 在测试此模式时,请进行以下修改:
Google Apps Script:
function rolesInputer(values){
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  sheet.getRange(17, 3, 1, values.length).setValues([values]);
}

HTML和Javascript:

我使用了<select>...</select>作为示例值。 在本示例中,当HTML被打开时,脚本会被运行。

<select id="role1"><option value="role1" selected>role1</option></select>
<select id="role2"><option value="role2" selected>role2</option></select>
<select id="role3"><option value="role3" selected>role3</option></select>
<select id="role4"><option value="role4" selected>role4</option></select>
<select id="role5"><option value="role5" selected>role5</option></select>

<script>
  function saveInput() {
    var dataEncoded = 5;
    var values = [];
    for (var i = 1; i <= dataEncoded; i++) {
      var temprole = "role" + (i);
      var roleSelect = document.getElementById(temprole);
      var roleSelected = roleSelect.options[roleSelect.selectedIndex].value;
      values.push(roleSelected);
    }
    google.script.run.withSuccessHandler(() => {google.script.host.close()}).rolesInputer(values);
  }
  saveInput();
</script>

模式2:

在此模式中,使用for循环将每个值发送到Google Apps Script。测试此模式时,请按以下方式进行修改。

Google Apps Script:

在此模式中,不需要修改Google Apps Script。

HTML和Javascript:

在此示例中,当打开HTML时,脚本会自动运行。

<select id="role1"><option value="role1" selected>role1</option></select>
<select id="role2"><option value="role2" selected>role2</option></select>
<select id="role3"><option value="role3" selected>role3</option></select>
<select id="role4"><option value="role4" selected>role4</option></select>
<select id="role5"><option value="role5" selected>role5</option></select>

<script>
  function work(roleSelected, i) {
    return new Promise((resolve, reject) => {
      google.script.run.withSuccessHandler(() => resolve()).rolesInputer(roleSelected, i);
    });
  }

  async function saveInput() {
    var dataEncoded = 5;
    for (var i = 1; i <= dataEncoded; i++) {
      var temprole = "role" + (i);
      var roleSelect = document.getElementById(temprole);
      var roleSelected = roleSelect.options[roleSelect.selectedIndex].value;
      await work(roleSelected, i);
    }
  }

  saveInput().then(() => google.script.host.close());
</script>

注意:

  • 考虑到进程成本,我认为模式1更好。

参考资料:

  • google.script.run

    google.script.run是一种异步客户端JavaScript API,可在HTML服务页面中调用服务器端Apps Script函数。

如果这对您的情况没有帮助,我感到很抱歉。


@Ilya Perelman 谢谢您的回复。我很高兴您的问题已经解决。 - Tanaike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接