如何从 HTML 服务中的列表框获取值

How to get a value from a Listbox in HTML Service

我在 Google Apps 脚本中遇到 HTML 服务问题。我正在尝试从列表框中获取一个值以拉取并填充表单的其余部分。这在使用 uiApp 时效果很好,但由于 Google 已决定下个月关闭 uiApp,我别无选择,只能将我所有的应用程序迁移到 HTML 服务。

我在 Whosebug 上发现了一些关于使用 scriptlet 的技巧,但我一直收到错误。

HTML

<form>

<table>
<tbody>
<tr>
  <td><label>Select Clinic:</label></td>
  <td><select name="selectClinic"id="selectClinic"onchange="doThisOnChange(this.value)"> 
  </select>

  <script>
    doThisOnChange = function(value)
    {
    alert( "Do something with the value: " + value );
    <?!=
    var ClinicID =  value;
    var SS = SpreadsheetApp.openById("MyID");
    var sheet= SS.getSheetByName('Data');
    var getClinicName = sheet.getRange("D"+ClinicID+":D"+ClinicID);
    window.document.getElementById("clinicName").value = getClinicName ; 
    ?>          
    }
    </script>

    <tr>
    <td><label>Clinic Name:</label></td>
    <td><input type="text" name="clinicName" id="clinicName" value=""> 
  </td>
</tr>

使用 scriptlet 时,脚本似乎无法获取传递的值。收到错误

"ReferenceError: "value" is not defined. (line 5, file "Code")"

我终于能够使用 window.document.getElementById 方法获取表单来填充字段,但似乎在不使用 scriptlet 时脚本停止了。

如有任何帮助,我们将不胜感激。

问题

您混淆了 server-side 组件 运行s only once on template evaluation (scriplets)和 client-side 脚本。因此,无法在脚本中访问用作 doThisOnChange 参数的 value

解决方案

如果您需要多次调用 server-side 组件,您应该使用 google.script.run API 代替,因为这是与 server-side 函数通信的唯一方式.

示例

所以,如果我正确理解了你的目标,你应该像这样解耦你的代码(请注意,server-side 函数显式 return 所需的输出很重要 + 你设置withSuccessHandler() 对 server-side 函数执行 client-side 操作成功 运行 结果):

Server-side

function getClinicName(ClinicID) {
  var OPCDSS = SpreadsheetApp.openById("MyID"); //I assume SS === OPCDSS?;
  var sheet = OPCDSS.getSheetByName('Data');
  var range = sheet.getRange("D"+ClinicID+":D"+ClinicID);
  var name  = range.getValue(); //this part was originally missing;
  return name;    
}

Client-side

  <script>
    /**
     * Asynchronously calls server-side function;
     * @param {String} value clinic select value; 
     */
    function doThisOnChange (value) {
      alert( "Do something with the value: " + value );
      google.script.run.withSuccessHandler(fillName).getClinicName(value);
    }

    /**
     * Performs client-side actions on server-side function return;
     * @param {*} serverOutput value returned from server-side;
     */
    function fillName (serverOutput) {
      var clinicNameInput = document.getElementById('clinicName');
          clinicNameInput.value = serverOutput;
    }
</script>

多个 server-side 字段

如评论中所述,添加了一个使用 multi-column 和/或行 Range 实例的示例。如果您在 Range 上调用 getValues() 方法,要迭代的结果 Array 值将被构造为:

[ //pseudo-code;
  row1 [ col1 , ..., colN ] ,
  ...,
  rowN [ col1, ..., colN ] 
]

请注意,处理 2D Array 实例只是最佳实践,因为 getValue() / getValues() 方法的计算量很大。总而言之,不是直接 returning 诊所的 name,而是创建一个包含所有诊所属性的 Object 实例(稍后可以在 client-side 回调中引用通过 key) 运行,或者您可以简单地传递 return 和 Array 并对其进行处理 client-side:

function getData(ClinicID) {
  var ss     = SpreadsheetApp.openById("MyID");
  var sheet  = ss.getSheetByName('Data');
  var range  = sheet.getRange(yourRangeboundaries); 
  var values = range.getValues(); //gets 2D Array of values;

  var output = {}; //initiate output Object;

  output.name = values[0][0]; //assuming name is in 1st row 1st column;
  output.phone = values[0][4]; //assuming phone is in 1st row 5th column;
  //etc;

  return output;
}

有用的笔记

Client-to-server与google.script.run的通信本质上是异步,这意味着您不必等待 直到您的 server-side 函数完成执行其他任务,但同时您只能访问 server-side 结果 在回调 函数的范围内。

有用的链接

  1. 模板化HTMLguide;
  2. Client-to-server通讯guide;
  3. google.script.run API reference;
  4. getValue()方法reference;