将URL参数传递到Web应用程序脚本

4
这个问题让我想拔光头发。我想把一个 URL 参数传递给 Google Apps Script,其中包含我想要呈现的数据的行 ID(来自电子表格)。我的参数是story。然而,无论我尝试什么,都会出现各种错误。最新的错误是:

TypeError:无法从未定义的变量中读取“parameter”属性。(第2行,文件“Code”,项目“singleStory”)

以下是我的 Code.gs 和 Index.html 文件(该项目尚未完成。这只是我到目前为止的进展情况)。

Code.gs

function doGet(e) {
    var i = e.parameter.story;
    return HtmlService
      .createTemplateFromFile('Index')
      .evaluate()
      .setSandboxMode(HtmlService.SandboxMode.IFRAME);

 function getData() {
 return SpreadsheetApp
      .openById("1Z582cnr03fkLC7xCca4pcj7QwDtSCS4KGneyFKMgdyo")
      .getSheetByName("StoryTopics")
      .getDataRange()
      .getValues();
 }
}

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
  <? var data = doGet(); ?>

<div id="container">
<div id="header">
<div id="topicname">
    <?= data[i][0] ?>
</div>
<div id="todaysdate">
<p>As of: <?= new Date() ?></p>
</div>
<div id="topictype">
<?= data[i][1] ?>
</div>
<div id="locale">
<?= data[i][2] ?>
</div>
</div>
<div id="contact_container">
<div id="subheader">
</div>
<div id="contact_name">
<?= data[i][3] ?>
</div>
<div id="contact_title">
<?= data[i][4] ?>, <?= data[i][5] ?>
</div>
<div id="contact_email">
<?= data[i][6] ?>
</div>
<div id="contact_phone">
<?= data[i][7] ?>
</div>
</div>
<div id="action_container">
<div id="subheader">
</div>
<table id="action_table">
<tr>
<td>
Date:
</td>
<td>
Type:
</td>
<td>
Description:
</td>
</tr>
</table>
</div>
<div id="story_container">
<div id="story_title">
</div>
<div id="story_content">
</div>
</div>
</div>
</body>
</html>

我正在测试的URL + 参数是:
https://script.google.com/a/macros/--DOMAIN--/s/--SCRIPTID--/exec?story=3

有人能给我一些关于为什么它不工作的想法吗?


1
请明确说明您想要实现的目标。从您的问题中并不清楚。 - Br. Sayan
e参数在doGet()中是什么意思?我不熟悉这种调用AppScript函数的方式,但看起来你的index.html中缺少了这个参数。 - nickpharris
1
@nickpharris - 应该是事件参数,如此处所述。然而,在我的代码副本中没有提供事件参数 - 出现了非常严重的问题。 - Mogsdad
1
没关系 - 问题在于你的模板HTML编写有误,因此Web应用程序无法正常启动。(它不应该调用doGet() - HTML是由该函数生成的,因此您正在设置执行循环。第二次调用没有事件参数,所以BOOM。) - Mogsdad
1个回答

5
这告诉你,你期望包含指定属性“parameter”的对象是未定义的。
查看你的代码(e.parameter.story),它引用了事件参数e。对于那些不熟悉此内容的人,当在部署的Web应用程序中调用它时,特别命名的doGet()函数会接收一个event parameter,在本例中命名为e。
为什么这里的e未定义?
可能出现这种情况的原因之一是,你正在从调试器运行该函数,而不是将其作为Web应用程序进行测试。但这不是你的情况,Kevin,因为你正在浏览器中输入URL来尝试启动Web应用程序。
问题出在模板HTML中。你的HTML中的第一条语句是:

<? var data = doGet(); ?>

这会在我们尝试 .evaluate() 模板时出现问题,因为它重新调用了 doGet() 函数,这次没有任何事件对象。而正是那个时间点导致了错误消息的出现。
您可能想要使用以下方法从电子表格中获取数据:
<? var data = getData(); ?>

完成这个更改后,您现在会收到事件参数e(一直都有...),代码继续执行。直到下一个错误:

ReferenceError: "i"未定义(第3行,文件“Code”)

现在事情变得棘手了,因为错误报告针对Code.gs中的此语句:

return HtmlService
    .createTemplateFromFile('Index')
    .evaluate()
    .setSandboxMode(HtmlService.SandboxMode.IFRAME);

等等!i不是刚在第2行定义吗?是的,确实是这样... 但是这个错误是关于evaluate()试图填充模板,而你的代码还没有为此设置i。你需要将这个语句分解成三部分:首先获取模板,然后为其设置参数,最后对其进行评估。像这样:

function doGet(e) {
  var i = e.parameter.story;

  // First, get the template
  var template = HtmlService.createTemplateFromFile('Index');

  // Second, set template parameters
  template.i = i;

  // Finally, evaluate() the template
  return template.evaluate()
                 .setSandboxMode(HtmlService.SandboxMode.IFRAME);

}  // <-- You had this on the other side of 'getData()'

这应该能让您开始了。您还有其他错误:

  • 您的函数阻塞方法不正确,您需要将 getData() 放在全局范围内,而不是在 doGet() 中。
  • 您可能需要调试模板,请参考 调试模板 中的指导。
  • 模板代码应该用 <? thusly ?> 包含,而不是 <?= like this ?>

1
确实修好了!非常感谢!我当然很欣赏您逐步解决问题并详细解释错误所在以及如何修复的方法。我是 Google Apps Script 的新手,所以我正在学习中。再次感谢您! - KevinH

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