从库中获取HTML模态框以在活动工作表上运行.gs函数

huangapple go评论68阅读模式
英文:

Getting an html modal from a library to run .gs functions on active sheet

问题

我有几个电子表格,我想要能够运行相同的代码。所以我创建了一个.gs库。库的其中一项功能是使用htmlService在活动工作表中创建一个模态对话框。HTML代码也包含在库中。在每个绑定的脚本中,我添加了一个菜单项到工作表,允许用户调用库函数。然而,当我尝试使用google.script.run从HTML访问活动工作表的数据时,我遇到了一些问题。我尝试了几种方法:

测试 1

首先,我尝试让HTML调用库.gs中的一个函数,假设它在范围内。代码看起来像这样:

bounded.gs

function onOpen(e) {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('myMenu')
  .addItem('Run Custom Function', 'myLibrary.createMyModal')
}

myLibrary.gs

function createMyModal() {
  var widget = HtmlService.createHtmlOutputFromFile('modalHTMLfile');
  SpreadsheetApp.getUi().showModalDialog(widget, "title");
}


function helloWorld() {
  var ui = SpreadsheetApp.getUi(); 
  ui.alert('hello, world!');
}

modalHTMLfile.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onClickFn() {
        google.script.run.helloWorld();

      }
    </script>
  </head>
  <body>
    <button onclick='onClickFn();'>click me!</button>
  </body>
</html>

模态对话框生成得很好,但是当我点击按钮时,在控制台中生成错误消息:“Uncaught TypeError: google.script.run.helloWorld is not a function”。

所以我认为这是范围的问题,我应该将helloWorld函数放在绑定的.gs中:

测试 2

我将helloWorld函数移动到了绑定的.gs中,如下所示:

bounded.gs

function onOpen(e) {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('myMenu')
  .addItem('Run Custom Function', 'myLibrary.createMyModal')
}

function helloWorld() {
  var ui = SpreadsheetApp.getUi(); 
  ui.alert('hello, world!');
}

myLibrary.gs

function createMyModal() {
  var widget = HtmlService.createHtmlOutputFromFile('modalHTMLfile');
  SpreadsheetApp.getUi().showModalDialog(widget, "title");
}

modalHTMLfile.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onClickFn() {
        google.script.run.helloWorld();

      }
    </script>
  </head>
  <body>
    <button onclick='onClickFn();'>click me!</button>
  </body>
</html>

这次,当我点击按钮时,服务器端发生了一些事情,但又出现了另一条错误消息。这次是“Uncaught ScriptError: We're sorry, a server error occurred” 查看此图片。这导致我进行了测试#3:

测试 3

所以我在互联网上找到了一些建议,包括在堆栈交换上有两个同名的函数,一个是绑定脚本中的空函数,另一个是库.gs中的真实函数。所以我尝试了这个...下面是代码:

bounded.gs

function onOpen(e) {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('myMenu')
  .addItem('Run Custom Function', 'myLibrary.createMyModal')
}

function helloWorld() {
  //占位符函数以“使事情工作”
}

myLibrary.gs

function createMyModal() {
  var widget = HtmlService.createHtmlOutputFromFile('modalHTMLfile');
  SpreadsheetApp.getUi().showModalDialog(widget, "title");
}


function helloWorld() {
  var ui = SpreadsheetApp.getUi(); 
  ui.alert('hello, world!');
}

modalHTMLfile.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onClickFn() {
        google.script.run.helloWorld();

      }
    </script>
  </head>
  <body>
    <button onclick='onClickFn();'>click me!</button>
  </body>
</html>

这第三个测试产生与测试2相同的错误。

测试 4

在前三个测试中,我使用开发模式将myLibrary包含在bounded.gs中,我在网上读到有人说在开发模式下运行会引发此问题。所以我尝试使用库的最新部署。

这是我的库部署看起来是这样的(v5)

库部署

当我点击按钮时,我收到一个错误消息,显示该库未被识别:

错误消息

--

我在这里象征性地拔了一些头发,有人有什么建议吗?这是否可能?我可以将所有代码放在bounded.gs文件中,但我有8个电子表格,我真的不想要有8个相同但分开的代码库需要更新(这是库的初衷XD)。

谢谢!!!

英文:

I have several spreadsheets from which i would like to be able to run the same code. So i created a .gs library. One of the things that the library does is create a modal in the active sheet using htmlService. The HTML code is also part of the library. On each bounded script, i add a menu item to the sheet that allows the user to call the library function. However, i am running into issues when trying to access the active sheet's data from the HTML using google.script.run. I have tried several things:

Test 1

First i tried having the HTML call a fn in the library gs, assuming it would be within scope. The code looked like this:

bounded.gs

function onOpen(e) {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu(&#39;myMenu&#39;)
  .addItem(&#39;Run Custom Function&#39;, &#39;myLibrary.createMyModal&#39;)
}

myLibrary.gs

function createMyModal() {
  var widget = HtmlService.createHtmlOutputFromFile(&#39;modalHTMLfile&#39;);
  SpreadsheetApp.getUi().showModalDialog(widget, &quot;title&quot;);
}


function helloWorld() {
  var ui = SpreadsheetApp.getUi(); 
  ui.alert(&#39;hello, world!&#39;);
}

modalHTMLfile.html

&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;base target=&quot;_top&quot;&gt;
    &lt;script&gt;
      function onClickFn() {
        google.script.run.helloWorld();

      }
    &lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;button onclick=&#39;onClickFn();&#39;&gt;click me!&lt;/button&gt;
  &lt;/body&gt;
&lt;/html&gt;

The modal generates just fine but when i click the button, it generates an error in the console: "Uncaught TypeError: google.script.run.helloWorld is not a function"

So i figured that there was an issue of scope, and i should put helloWorld in the bounded .gs:

Test 2

I moved the fn helloWorld into the bounded .gs as follows:

bounded.gs

function onOpen(e) {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu(&#39;myMenu&#39;)
  .addItem(&#39;Run Custom Function&#39;, &#39;myLibrary.createMyModal&#39;)
}

function helloWorld() {
  var ui = SpreadsheetApp.getUi(); 
  ui.alert(&#39;hello, world!&#39;);
}

myLibrary.gs

function createMyModal() {
  var widget = HtmlService.createHtmlOutputFromFile(&#39;modalHTMLfile&#39;);
  SpreadsheetApp.getUi().showModalDialog(widget, &quot;title&quot;);
}

modalHTMLfile.html

&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;base target=&quot;_top&quot;&gt;
    &lt;script&gt;
      function onClickFn() {
        google.script.run.helloWorld();

      }
    &lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;button onclick=&#39;onClickFn();&#39;&gt;click me!&lt;/button&gt;
  &lt;/body&gt;
&lt;/html&gt;

This time, when i clicked the button, something happened on the server side (see image below), but another error message appeared. This time, "Uncaught ScriptError: We're sorry, a server error occurred"
See this image. Which led me to test #3:

Test 3

Soooo i did some questing around the interwebs and found some suggestions on stack exchange including to have two fns with the same name, an empty one in the bounded script and the real function in the library gs. So i tried that...here's the code:

bounded.gs

function onOpen(e) {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu(&#39;myMenu&#39;)
  .addItem(&#39;Run Custom Function&#39;, &#39;myLibrary.createMyModal&#39;)
}

function helloWorld() {
  //placeholder function to &quot;make things work&quot;
}

myLibrary.gs

function createMyModal() {
  var widget = HtmlService.createHtmlOutputFromFile(&#39;modalHTMLfile&#39;);
  SpreadsheetApp.getUi().showModalDialog(widget, &quot;title&quot;);
}


function helloWorld() {
  var ui = SpreadsheetApp.getUi(); 
  ui.alert(&#39;hello, world!&#39;);
}

modalHTMLfile.html

&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;base target=&quot;_top&quot;&gt;
    &lt;script&gt;
      function onClickFn() {
        google.script.run.helloWorld();

      }
    &lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;button onclick=&#39;onClickFn();&#39;&gt;click me!&lt;/button&gt;
  &lt;/body&gt;
&lt;/html&gt;

This third test yielded the same error as Test 2.

Test 4

For all three of the previous tests I included myLibrary in bounded.gs using Development Mode and i read something online suggesting that running in Development Mode can cause this issue. So i tried using the most up to date deployment of the library.

This is what my library deployment looks like (v5)

Library deployment

And when i click the button, i get an error message showing that the library is not recognized:

error message

--

I'm metaphorically pulling my hair out over here, does anyone have any suggestions? Is this even possible? I couuuuuuld put all the code in the bounded.gs file but i have 8 spreadsheets and i'd really love to avoid having 8 identical yet separate code bases to keep updated (that's the point of the library in the first place XD).

Thank you!!!

答案1

得分: 0

确保您已登录到您在浏览器中用于运行代码的 Google 帐户作为默认帐户


好的,看起来问题出在我登录到 Google 的方式上。(感谢这个帖子上评论的提示:https://stackoverflow.com/questions/67076991/google-script-run-functions-failing-in-firefox-safari)

通常,我会从我的工作帐户开发,这在我的 Firefox 会话中是用户 #1(u=1)(我的个人帐户是默认帐户,u=0)。这个配置导致了原帖中描述的问题。然而,当我在 Firefox 的隐身窗口中使用时,只有登录到我的工作帐户时它才能正常工作。当我的工作帐户(相关工作表和脚本的所有者)成为默认帐户并且浏览器也登录到我的个人帐户时,它也可以正常工作。在隐身模式下,当我切换帐户以匹配我的非隐身配置(个人=0,工作=1)时,我再次遇到错误。

看起来这可能与默认帐户没有权限访问脚本有关,很可能是 Google 方面的错误。

感谢所有评论的人们,感谢你们的支持!

英文:

tl;dr: Make sure that you are signed into the Google Account you are using to run the code as the default account in the browser.


Ok, it seems like the issue is how i am logged into Google. (Thanks to prompting from comments on this thread: https://stackoverflow.com/questions/67076991/google-script-run-functions-failing-in-firefox-safari)

I typically develop from my work account which is user #1 (u=1) in my Firefox session (my personal account is the default account, u=0). This configuration leads to the bugs described in the original post. However, when i am using an Incognito Window in Firefox, it works when i'm only signed into my work account. It also works fine when my work account (the owner of the relevant sheets and scripts) is the default account and the browser is also signed into my personal account. In Incognito mode, when i swap the accounts so that they match my non-Incognito configuration (personal=0, working=1) i run into the errors again.

Seems likely that this has something to do with the default account not having permission to access the scripts and is likely a Google-side bug.

Thanks to everyone who commented for your support on this!!!

huangapple
  • 本文由 发表于 2023年7月14日 02:01:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76682116.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定