【问题标题】:Can I use HTML sidebar to call a function in Google Appscript?我可以使用 HTML 侧边栏调用 Google Appscript 中的函数吗?
【发布时间】:2022-01-25 05:03:20
【问题描述】:

我需要使用侧边栏获取一些变量,然后使用 AppScript 在工作表的最后一行打印。所以,我试图使用这段代码:

Sidebar.HTML

<!DOCTYPE html>
<html>

<head>
  <base target="_top">
</head>

<body>
  <p>Name: <input type="text" name="txtName" /></p>
  <p>Date: <input type="text" name="txtDate" /></p>
  <p>Value: <input type="text" name="txtValue" /></p>
  <button onclick="doSomething()"> submit </button>
  <script>
    function doSomething() {
      google.script.run.withFailureHandler(myFunction(document.getElementById("txtName", "txtDate", "txtValue").value))
    }
  </script>

</body>

</html>

Code.js

function myFunction(name = "", date = "", value = "") {
  var ss = SpreadsheetApp.getActive()
  var sheet = ss.getSheetByName("1")

  var lr = sheet.getLastRow() + 1

  sheet.getRange(lr, 1).setValue(name)
  sheet.getRange(lr, 2).setValue(date)
  sheet.getRange(lr, 3).setValue(value)
}

function openDialog() {
  var html = HtmlService.createHtmlOutputFromFile("Sidebar");
  html.setTitle("Form");
  SpreadsheetApp.getUi().showSidebar(html);
}

但它不起作用。当我单击按钮时,没有任何反应。我是 HTML 新手,那么,我能做些什么来修复它?

【问题讨论】:

    标签: javascript html google-apps-script google-sheets sidebar


    【解决方案1】:

    看起来你几乎做对了,除了 Sidebar.HTML 文件中的两件事——

    1. 鉴于您使用的是getElementById,您还需要在input 字段中添加id 标签
    2. google.script.run.withFailureHandler 的实现似乎有点偏离。您可以阅读official documentation 了解更多信息
      • 您也可以完全跳过使用withFailureHandler,只需使用google.script.run.myFunction(...)

    这是最终的工作代码供参考——

    <!DOCTYPE html>
    <html>
    
    <head>
      <base target="_top">
    </head>
    
    <body>
      <p>Name: <input type="text" name="txtName" id="txtName" /></p>
      <p>Date: <input type="text" name="txtDate" id="txtDate" /></p>
      <p>Value: <input type="text" name="txtValue" id="txtValue" /></p>
      <button onclick="doSomething()"> submit </button>
      <script>
        function doSomething() {
          google.script.run.withFailureHandler()
          .myFunction(document.getElementById("txtName").value,document.getElementById("txtDate").value,document.getElementById("txtValue").value)
        }
      </script>
    
    </body>
    
    </html>
    

    【讨论】:

      【解决方案2】:

      通过侧边栏中的名称动态调用服务器端函数

      您可以从侧边栏调用许多服务器端函数。我有一个电子表格,用于回答关于 SO 的问题,其中大部分脚本位于五个文件中,它们位于我的全局哈希表中,位于密钥 sbfiles 下。目前他们是 ag1,ag2,ag3,ag4,zkeepers。

      选择下拉列表中的名称是动态的,每次重新加载侧边栏时都会读取。

      当我使用以下功能加载侧边栏时:

      使用此功能:

      function showToolsSideBar() {
        var userInterface = HtmlService.createTemplateFromFile('toolsSideBar').evaluate().setTitle('SO Tools');
        SpreadsheetApp.getUi().showSidebar(userInterface);
      }
      

      这会加载包含这四个按钮的 toolsSideBar.html:

       <br /><strong>Test Buttons</strong>
         <br /><input type="button" value="run1()" onClick="execFunc1();" /><select id="func1"></select>
         <br /><input type="button" value="run2()" onClick="execFunc2();" /><select id="func2"></select>
         <br /><input type="button" value="run3()" onClick="execFunc3();" /><select id="func3"></select>
         <br /><input type="button" value="run4()" onClick="execFunc4();" /><select id="func4"></select>
         <hr />
      

      这是一个包含这一行的模板化 html 文件:

      <?!= include('sbscript') ?>
      

      而 sbscript.html 包含:

      $(function(){
          google.script.run
          .withSuccessHandler(function(vA){
            let idA=["func1","func2","func3","func4"];
            idA.forEach(function(id){
              updateSelect(vA,id);
            });
          })
          .getProjectFunctionNames();
          var elem = document.getElementById("permnotes1");
          var v = localStorage.getItem(elem.name);
          if(v) {elem.value = v;}
          elem.addEventListener("change",saveText);
          //console.log('elem.name: %s',elem.name);
        })
      

      调用这个服务器端函数getProjectFunctionNames():

      function getProjectFunctionNames() {
        const vfilesA=getGlobal('sbfiles').split(',');
        const scriptId="script id";
        const url = "https://script.googleapis.com/v1/projects/" + scriptId + "/content?fields=files(functionSet%2Cname)";
        const options = {"method":"get","headers": {"Authorization": "Bearer " +  ScriptApp.getOAuthToken()}};
        const res = UrlFetchApp.fetch(url, options);
        let html=res.getContentText();
        //SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html), "Project Functions");
        let data=JSON.parse(res.getContentText());
        let funcList=[];
        let files=data.files;
        files.forEach(function(Obj){
          if(vfilesA.indexOf(Obj.name)!=-1) {
            if(Obj.functionSet.values) {
              Obj.functionSet.values.forEach(function(fObj){
                funcList.push(fObj.name);
              });
            }
          }
        });      //SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(funcList.join(', ')), "Project Functions");
        return funcList;
      }
      

      此函数使用应用程序脚本 api 来读取我的全局哈希表键 sbfiles 中的所有文件。该列表返回到 javascript 函数的成功处理程序,并使用此函数加载使用此脚本的 html 文件中的四个按钮中的每一个的选择框:

      function updateSelect(vA,id){
          var id=id || 'sel1';
          var select = document.getElementById(id);
          select.options.length = 0; 
          vA.unshift("");
          for(var i=1;i<vA.length;i++){
            select.options[i] = new Option(vA[i],vA[i]);
          }
        }
      

      这让我们回到了这个:

       <br /><strong>Test Buttons</strong>
         <br /><input type="button" value="run1()" onClick="execFunc1();" /><select id="func1"></select>
         <br /><input type="button" value="run2()" onClick="execFunc2();" /><select id="func2"></select>
         <br /><input type="button" value="run3()" onClick="execFunc3();" /><select id="func3"></select>
         <br /><input type="button" value="run4()" onClick="execFunc4();" /><select id="func4"></select>
         <hr />
      

      您可以通过四个选择下拉列表中的任何一个选择任何函数名称,然后按左侧的按钮,您将在按钮右侧的选择下拉列表中调用该函数:

      function execFunc1() {
          var funcname=$('#func1').val();
          google.script.run.executeFunctionByName(funcname);
        }
        function execFunc2() {
          var funcname=$('#func2').val();
          google.script.run.executeFunctionByName(funcname);
        }
        function execFunc3() {
          var funcname=$('#func3').val();
          google.script.run.executeFunctionByName(funcname);
        }
        function execFunc4() {
          var funcname=$('#func4').val();
          google.script.run.executeFunctionByName(funcname);
        }
      

      然后调用这个函数:

      function executeFunctionByName(func) {
        this[func]();
      }
      

      依次调用在 sbfiles 的哈希表键中找到的文件中的函数。

      这使我可以在开发这些文件时从侧栏中调用我正在开发的任何功能,只需为四个可能的按钮中的每一个选择它们中的每一个即可调用名称出现在与该函数关联的选择框中的函数。这让我可以方便地测试我目前正在处理的代码。

      在开发新代码时,这是一个非常方便的功能,以便能够直接访问最新的代码。这在开发新的对话框代码时非常方便,因为您可以从侧边栏重新调用您正在处理的函数:

      演示:

      【讨论】:

        猜你喜欢
        • 2022-01-21
        • 1970-01-01
        • 1970-01-01
        • 2017-03-30
        • 2016-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多