首页 > 解决方案 > 传递给客户端代码时服务器端对象丢失

问题描述

这与通过 google.script.run 传递对象时在服务器端丢失的 Object 属性值不同

我正在尝试设置我的 Google Apps 脚本插件测试框架。由于 Test as add-on 不能用于测试可安装的触发器,我想知道是否可以从有界项目中提取服务器端代码以用作库来测试调用服务器端函数的边栏。

如果我使用 Run > Test 作为附加组件运行以下代码...它会显示我的菜单两次

  1. 作为名为“侧边栏”的自定义菜单,位于帮助菜单旁边
  2. 作为附加菜单,在附加组件 > 我的项目

同样的情况,服务器端对象丢失,当我用getMail()另一个使用电子表格服务返回单元格值的函数,甚至是返回原始字符串的函数替换该函数时。

我错过了什么?

底线是我想在我的侧边栏添加一个按钮,该按钮创建一个可安装的触发器并从电子表格中获取一些值。

用作库的电子表格

代码.gs

function onOpen(e) {
  var ui = SpreadsheetApp.getUi();
  var menu = ui.createMenu('Sidebar');
  menu
    .addItem('Open', 'showSidebar')
    .addToUi();
}

function showSidebar() {
  var ui = HtmlService.createHtmlOutputFromFile('Sidebar')
    .setSandboxMode(HtmlService.SandboxMode.IFRAME)
    .setTitle('A Sidebar');
  SpreadsheetApp.getUi().showSidebar(ui);

}

function getEmail() {
  return Session.getActiveUser().getEmail();
}

边栏.html

<!DOCTYPE html>
<html>

<head>
  <base target="_top">
  <script>
    function updateButton(email, button) {
      console.log(email);
      button.value = 'Clicked by ' + email;
    }
  </script>
</head>

<body>
  <input type="button" value="Not Clicked" onclick="google.script.run
          .withSuccessHandler(updateButton)
          .withUserObject(this)
          .getEmail()" />
  <input type="button" value="Not Clicked" onclick="google.script.run
          .withSuccessHandler(updateButton)
          .withUserObject(this)
          .getEmail()" />
</body>

</html>

用于替换 getMail() 的其他函数示例

function getCellValue(){
  return SpreadsheetApp.getActiveCell().getValue();
}

function getGreeting(){
  return 'Hello world';
}

用作图书馆客户端的电子表格

  1. 将库添加到项目中
  2. 添加以下代码

    函数 onOpen(e) { aLib.onOpen(e); }

    函数 showSidebar(){ aLib.showSidebar(); }

    函数 getEmail(){ aLib.getEmail(); }

作为插件测试...

  1. 单击运行 > 测试作为附加组件
  2. 将“电子表格用作库客户端”添加为用于测试附加组件的文档
  3. 启动文档

标签: google-apps-scriptgoogle-sheetsgoogle-apps-script-addon

解决方案


根据https://developers.google.com/apps-script/guides/html/communication#private_functions google.script 无法访问库函数,但看起来它也无法访问库对象。

解决方案是使用全局变量

用作库的电子表格

代码.gs

/* For tests only, assign the server side function
 * to be called from the sidebar to a global variable 
 */
var email = getEmail(); 

/**
 * Reference: https://stackoverflow.com/q/50595103/1595451
 *
 */
function onOpen(e) {
  var ui = SpreadsheetApp.getUi();
  var menu = ui.createMenu('Sidebar');
  menu
    .addItem('Open', 'showSidebar')
    .addToUi();
}

function showSidebar() {
  var ui = HtmlService.createHtmlOutputFromFile('Sidebar')
    .setSandboxMode(HtmlService.SandboxMode.IFRAME)
    .setTitle('A Sidebar');
  SpreadsheetApp.getUi().showSidebar(ui);

}

function getEmail() {
  return Session.getActiveUser().getEmail();
}

用作图书馆客户端的电子表格

代码.gs

var email = aLib.email;

function onOpen(e) {
  aLib.onOpen(e);
}

function showSidebar(){
  aLib.showSidebar();
}

function getEmail(){
  /* Instead of calling the library function we call the library global variable */
  return email; 
}

推荐阅读