【问题标题】:Google Apps Script Add On google.run.script runs as developer?Google Apps Script Add On google.run.script 作为开发者运行?
【发布时间】:2018-09-15 15:47:24
【问题描述】:

我只在 GAS 工作了不到 6 个月。到目前为止,所有内容都绑定了电子表格项目,但已经创建了很多。我有一个新的需求,即创建一个人们可以在他们想要的任何电子表格中使用的附加侧边栏(在域中)。我创建了代码,发布了它,所以只有域可以看到它,并且可以作为同一域中的另一个用户安装它,所有这些似乎都工作正常。

问题与sidebar.html 有关,并在我的脚本中使用google.script.run 调用函数来调用获取一些外部数据并将其写入当前工作表的函数。获取外部数据的所有代码都可以正常工作,它们都进入了一个二维数组。它中断的部分位于SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(1,1,x,y).setValues(array)。我收到 “您无权访问请求的文档”

我在测试期间做了以下一些事情:

1) 插件脚本最初是作为现有工作表的绑定脚本进行开发的。考虑到这可能是问题所在,我将该项目重新创建为独立的 GAS,并将其作为工作表的 Web 插件发布。这并没有什么不同。

2) 开发者可以正常运行插件,没有侧边栏错误。

3) 我为插件创建了另一个菜单项,而不是打开侧边栏并让侧边栏通过 google.script.run 调用该函数,而是直接从菜单中运行该函数。这样做,它对其他域用户“有效”(从侧边栏运行它失败)。

4) 我与开发人员“共享”了用于与域测试用户测试插件的底层 Google 表格,然后侧边栏脚本将起作用。如果我在另一个非共享工作表中使用加载项,则会收到权限错误。

5) 如果我在我们都使用并有权访问(域范围)的大型共享云端硬盘文件夹中的工作表上使用它,它工作正常,正如我对上面“3”中的测试所期望的那样。

大问题:

因此,“google.script.run”似乎以开发人员身份运行,并且 不是当前用户(在键盘上)?是对的吗?往里看 像this 这样的文件,我找不到任何可以表明的东西 那。我应该添加一些东西以确保它有效吗? 这是我发布它的方式的副作用,仅供域使用吗?

更新:在没有特别确定的情况下,我测试了某人的“查找和替换”插件,果然,它能够从侧边栏直接写到工作表上,没有任何问题。我唯一做的就是在安装应用程序时对其进行授权。所以这显然是可能的。我只是想弄清楚我的附加组件中可能缺少什么,这将使我能够做同样的事情。

这是我放在一起的一个小示例,只是为了测试将 2 列和 2 行的数组“写入”到当前活动工作表中的 A1:B2。作为开发人员,它可以在菜单和侧边栏中工作。它始终作为域用户从菜单中工作,但如果开发人员对文件具有直接权限(通过一次性共享或通过在开发人员拥有的先前共享文件夹中创建),它将“仅”从侧边栏中工作适当的权限)。

// scopes
https://www.googleapis.com/auth/script.container.ui
https://www.googleapis.com/auth/spreadsheets

// code.gs
function onOpen(e) {
  SpreadsheetApp.getUi().createAddonMenu()
 .addItem('Sidebar Test', 'showSidebar')
 .addItem('setValues Test', 'setValuesTest')
 .addToUi();
}

function showSidebar() {
  var htmlTemplate = HtmlService.createTemplateFromFile('sidebar');
  var ui = htmlTemplate.evaluate()
    .setTitle('Sidebar Test')
  SpreadsheetApp.getUi().showSidebar(ui);
}

function onInstall(e) {
  onOpen(e);
}

function setValuesTest() {
  try {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = ss.getActiveSheet();
    var valArr = [];
    valArr.push([1,2]);
    valArr.push([3,4]);
    sheet.getRange(1, 1, 2, 2).setValues(valArr);
  } catch (e) {
    throw new Error(errorMessage({e: e}));
  }
}

function errorMessage(params) {
  return params.e.message + '<br/><div class="main">file: '+ 
    params.e.fileName+'<br/>line: '+ params.e.lineNumber + '</div>';
}

function getVersion() {
  var scriptProps = PropertiesService.getScriptProperties();
  return scriptProps.getProperty('Version');
}

// utility.gs
function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename)
      .getContent();
}

// sidebar.js.html
<script>
$(function() {
  $('#run-query').click(runQueryButton);
});

function runQueryButton() {
  runQuery(this);
}

function runQuery(element) {
  element = (element === 'undefined') ? this : element;
  element.disabled = true;
  $('#error').remove();
  google.script.run
    .withSuccessHandler(
      function(msg, element) {
        element.disabled = false;
      })
    .withFailureHandler(
      function(msg, element) {
        showError(msg, $('#main'));
        element.disabled = false;
      })
    .withUserObject(element)
    .setValuesTest();
  google.script.host.editor.focus();
}

function showError(msg, element) {
  var div = $('<div id="error" class="error">' + msg + '</div>');
  $(element).after(div);
}
</script>

// sidebar.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
    <?!= include('sidebar.css'); ?>
  </head>
  <body>
    <div class="sidebar branding-below">
      <div id="main" >
        <button class="blue cursor-pointer" id="run-query" data-toggle="modal">Execute</button>
      </div>
    </div>
    <div class="sidebar bottom">
      Version: <?!= getVersion(); ?>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <?!= include('sidebar.js'); ?>
  </body>
</html>

// sidebar.css.html
<style>
.error {
  padding: .25em .25em;
  font-family: Arial,sans-serif;
}
</style>

更新 2 我将部署类型更改为“仅受信任的测试人员”,并将我的非域自我添加为该测试人员。我向我(其他)自己发送了该应用程序的链接并从那里安装了它。回答了授权弹出窗口(不过,由于我不在域中,我不得不走“不安全”的路线,这很好)。运行测试插件......它就像一个冠军!现在,我自己(非域)和其他开发者自己(域)都支付了 5 美元。是这个问题吗?问题是我在域中创建的测试用户没有支付任何费用,所以它不起作用?

这对我来说没有多大意义,因为安装了测试插件,并且测试用户(在域中)可以从“菜单”调用底层脚本,并且它可以很好地填充电子表格。只有当域用户尝试从侧边栏运行应用程序时,它才会崩溃,边栏使用 google.script.run 调用来调用代码。这真的非常非常奇怪,令人沮丧。

另一方面,我添加了一个功能以在侧栏上显示“有效用户”,以防万一这方面发生了一些奇怪的事情,而且看起来一切都很好,报告了测试的名称域中的用户,而不是域中开发者的名称。

我想我的下一个测试将是:

  1. 将其转回域,为域测试用户重新安装,看看是否没有发生其他问题来修复它。

  2. 如果仍然损坏,请将其转回受信任的测试人员,将域测试用户添加到该组,支付 另一个 5 美元,看看他们是否可以以这种方式安装和运行它。如果可以,则说明插件的域发布存在缺陷,或者我缺少一些文档(或未记录的内容)。

【问题讨论】:

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


    【解决方案1】:

    google.script.run 将始终作为插件的有效用户(可能是也可能不是开发人员)运行。

    但是,如果未授予用户编辑电子表格的权限,您将遇到错误。

    您可以尝试为您的域设置团队云端硬盘,以便与团队中的用户轻松共享文档。或者,您可以为您域中的所有用户创建一个共享文件夹(具有编辑权限),以存储该域中的所有用户都应该可以访问的文档。

    【讨论】:

    • 谢谢。这不是附加组件的使用方式吗?我认为,当您在安装期间授权插件时,它会列出您正在授权的内容(基于范围,那时您让应用程序作者与您的文档进行交互,不是吗?是的,我可以在这种情况下按照你的建议做,尽管它似乎对用户有限制。我很惊讶这不是授予应用程序运行权限的一部分。有没有办法根据你的编码告诉谁“有效用户”会是?
    • 这很有趣:developers.google.com/apps-script/reference/base/… 它说您可以设置谁是“网络应用程序”的有效用户。我如何为“添加”做到这一点?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    相关资源
    最近更新 更多