如何将值从google脚本传递到html页面

我有一个谷歌表,维护一个项目列表,后面有一些脚本运行 . 我已经能够添加功能以单击“添加项目”按钮,该按钮将打开一个用于输入信息的HTML窗口,并且在提交时,会向工作表添加新记录 .

现在,如果状态更改为“已取消”,我正在处理删除记录的过程 . 我想要做的是显示一个html窗口,列出项目的某些细节,并让用户有机会在不取消项目的情况下返回,或者输入一些关于它被取消的原因的注释,然后继续 .

我陷入困境的是用html窗口填充项目的详细信息 . 我找到了一种方法,但我知道这不是最好的方法 .

Google脚本:

function onEdit(e) {
  if(e.range.getColumn() == 9 && e.value == "Cancelled" && e.source.getActiveSheet().getName() == "Summary") {
    var cancelSheet = ss.getSheetByName(e.source.getActiveSheet().getName());
    var cancelRange = cancelSheet.getRange(e.range.getRow(), 1, 1, cancelSheet.getLastColumn());
    var cancelRow = cancelRange.getValues();

    openCancelDialog(cancelRow);
  }
}

function openCancelDialog(x) {
  var html = HtmlService
  //.createHtmlOutputFromFile('Cancel')
  .createHtmlOutput(
    '<table><tr><td colspan = \"2\"><b>You are cancelling the following project:</b></td></tr>' +
    '<tr><td>Project Name: </td><td>' + x[0][4] + '</td></tr>' + 
    '<tr><td>Project Number: </td><td>' + x[0][0] + '</td></tr>' + 
    '<tr><td>Project Category: </td><td>' + x[0][1] + '</td></tr>' + 
    '<tr><td>Business Owner: </td><td>' + x[0][17] + '</td></tr>' + 
    '<tr><td>Project Manager: </td><td>' + x[0][18] + '</td></tr>' + 
    '</table>'
  )
  .setSandboxMode(HtmlService.SandboxMode.IFRAME);
  SpreadsheetApp.getUi()
       .showModalDialog(html, 'Cancel a Project');
}

这种方式是直接在gs中编写html . 我想做的是创建一个单独的html页面 . 这可以用这个方法完成(我是如何在gs中的其他地方创建Add Project对话框):

function openCancelDialog(x) {
  var html = HtmlService.createHtmlOutputFromFile('Cancel').setSandboxMode(HtmlService.SandboxMode.IFRAME);
  SpreadsheetApp.getUi()
       .showModalDialog(html, 'Cancel a Project');
}

这将是Cancel.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
    </script>

    <script>
      <!-- Scripting to get my values? -->
    </script>

  </head>
  <body>
    <!-- Layout the window
         Add a Comments section
         Add a button to go back without cancel
         Add a button to submit the cancel and update -->
  </body>
</html>

但我还没想到的是如何将数组从openCancelDialog函数传递给html,所以它可以在页面上显示 .

我怀疑我需要在Cancel.html文件中添加脚本以获取这些值 . 但有没有办法在创建时将该数组发送到html?

回答(3)

2 years ago

这是另一种方法 . 我喜欢这样做,因为我有比模板更多的控制权 .

这是我在处理电子表格中包含的电子邮件示例脚本时所执行的脚本 . 此脚本稍微复杂一点,因为它只是为用户提供了从电子邮件设置页面删除已发送电子邮件并将其存档到另一页面的选项 . 它通过动态创建html并将其作为字符串收集然后将其添加到另一个html页面来实现 . 我在脚本末尾启动html作为一个对话框,允许用户通过选中复选框并单击名为Archive Selected的按钮来选择要存档的电子邮件 . 我发现将javascript函数放在一个标准的html文件中然后先通过HtmlService运行并稍后追加该字符串会更容易 .

这是脚本:

function archiveSelectedEmails()
{
  var ss=SpreadsheetApp.getActiveSpreadsheet();
  var sht=ss.getSheetByName('EmailSetup');
  var rng=sht.getDataRange();
  var rngA=rng.getValues();
  var s='<html><head><script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script></head><body>';
  var s='';
  for(var i=2;i<rngA.length;i++)
  {
    var dataA={};
    for(var j=0;j<rngA[1].length;j++)
    {
      dataA[rngA[1][j]]=rngA[i][j];
    }
    var row=Number(i+1);
    s+='<div id="row' + row + '"><input type="checkbox" name="email" value="' + Number(i+1) + '" />' + ' <strong>Row:</strong> ' + Number(i+1) + ' <strong>Name:</strong> ' + dataA.Name + ' <strong>Email:</strong> ' + dataA.Email + ' <strong>Subject:</strong> ' + dataA.Subject + ' <strong>DateSent:</strong> ' + Utilities.formatDate(new Date(dataA.DateSent), 'GMT-6', "M/dd/yyyy HH:mm:ss") + '</div>';
  }
  s+='
<input type="button" value="Exit" onClick="google.script.host.close();" /><input type="button" value="Archive Checked" onClick="getCheckedBoxes(\'email\');" />'; var html=HtmlService.createHtmlOutputFromFile('htmlToBody').setWidth(800).setHeight(250); html.append(s); SpreadsheetApp.getUi().showModelessDialog(html, 'Select Emails to Archive'); }

这是html文件'htmlToBody':

<!DOCTYPE html>
<html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script>
function getCheckedBoxes(chkboxName) {
  var checkboxes = document.getElementsByName(chkboxName);
  var rowsToArchive = [];
  for (var i=0; i<checkboxes.length; i++) 
  {
     if (checkboxes[i].checked) 
     {
        rowsToArchive.push(Number(checkboxes[i].value));
     }
  }
  google.script.run
    .withSuccessHandler(setResponse)
    .archiveSelectedRows(rowsToArchive);
}

function setResponse(a)
{
  var s='
Rows: '; for(var i=0;i<a.length;i++) { if(i>0) { s+=', '; } s+=a[i]; var id='#row' + a[i] $(id).css('display','none'); } s+='
Total: ' + a.length; google.script.run.displayMessage(s,'Archived Rows') } console.log('script here'); </script> </head> <body>

我接受了你的项目想法并且稍微运行了一下 .

这些是谷歌脚本 . 你会注意到我从你的功能名称开始 .

function openCancelDialog1()
{
  var ss=SpreadsheetApp.getActiveSpreadsheet();
  var sht=ss.getSheetByName('Projects');
  var rng=sht.getDataRange();
  var rngA=rng.getValues();
  var s='';
  for(var i=1;i<rngA.length;i++)
  {
    var dataA={};
    for(var j=0;j<rngA[0].length;j++)
    {
      dataA[rngA[0][j]]=rngA[i][j];
    }
    var row=Number(i+1);
    s+='<div id="row' + row + '"><input type="checkbox" name="project" value="' + row + '" />' + ' <strong>Row:</strong> ' + Number(i+1) + ' <strong>Name:</strong> ' + dataA.Name + ' <strong>Project:</strong> ' + dataA.Description + '</div>';
  }
  s+='
<input type="button" value="Exit" onClick="google.script.host.close();" /><input type="button" value="Cancel and Archive Checked" onClick="getCheckedBoxes(\'project\');" />'; var html=HtmlService.createHtmlOutputFromFile('htmlToBody').setWidth(800).setHeight(250); html.append(s); SpreadsheetApp.getUi().showModelessDialog(html, 'Select Project to Cancel'); } function archiveSelectedRows(rows) { var ss=SpreadsheetApp.getActiveSpreadsheet(); var sht=ss.getSheetByName('Projects'); var dest=ss.getSheetByName('ArchivedProjects'); var rng=sht.getDataRange(); var rngA=rng.getValues(); var deleted=[]; for(var i=rngA.length-1;i>1;i--) { if(rows.indexOf(i+1)>-1) { deleted.push(Number(i+1)); rngA[i][4]=Utilities.formatDate(new Date(), 'GMT-7', 'M/d/yyyy') dest.appendRow(rngA[i]); sht.deleteRow(i+1); } } var msg='Row Numbers Deleted = ' + deleted; var title='Rows Deleted'; var timeout=10; return deleted; } function displayMessage(msg,title) { msg+='
<input type="button" value="Exit" onClick="google.script.host.close()"; />'; var html=HtmlService.createHtmlOutput(msg).setWidth(400).setHeight(300); SpreadsheetApp.getUi().showModelessDialog(html, title); }

这是htmlTobody文件 . 对于这种情况,它已被修改了一下 .

<!DOCTYPE html>
<html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script>
function getCheckedBoxes(chkboxName) {
  var checkboxes = document.getElementsByName(chkboxName);
  var rowsToArchive = [];
  for (var i=0; i<checkboxes.length; i++) 
  {
     if (checkboxes[i].checked) 
     {
        rowsToArchive.push(Number(checkboxes[i].value));
     }
  }
  google.script.run
    .withSuccessHandler(setResponse)
    .archiveSelectedRows(rowsToArchive);
}

function setResponse(a)
{
  var s='
Row Numberss: '; for(var i=0;i<a.length;i++) { if(i>0) { s+=', '; } s+=a[i]; var id='#row' + a[i] $(id).css('display','none'); } s+='
Total: ' + a.length; google.script.run.displayMessage(s,'Canceled Rows') } console.log('script here'); </script> </head> <body>

这就是我的“项目”标签的样子 . 我有一个Projects选项卡和一个ArchivedProjects选项卡 . 当我归档项目时,它们会被复制到ArchivedProjects表中 .

enter image description here

2 years ago

使用HtmlService.createTemplateFromFile

function openCancelDialog(row)
{
  var ui = SpreadsheetApp.getUi();

  // get template
  var template = HtmlService.createTemplateFromFile('Cancel');

  // pass data to template
  template.data = {
    row: JSON.stringify(row)
  };

  // get output html
  var html = template.evaluate();

  // show modal window
  ui.showModalDialog(html, 'Cancel a Project');
}

Cancel.html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <script>
    var row = <?!=data.row?>;
    //document.write(row);
    </script>
  </body>
</html>

详细的模板文档:https://developers.google.com/apps-script/guides/html/templates

2 years ago

科斯的回答给了我一些关于如何解决问题的想法 . 这一点,以及一些额外的阅读,特别是https://www.w3schools.com/js/js_json_intro.asp和后续章节,帮助我解决了这个问题 .

新的js代码:

function onEdit(e) {
  if(e.range.getColumn() == 9 && e.value == "Cancelled" && e.source.getActiveSheet().getName() == "Summary") {
    var cancelSheet = ss.getSheetByName(e.source.getActiveSheet().getName());
    var cancelRange = cancelSheet.getRange(e.range.getRow(), 1, 1, cancelSheet.getLastColumn());
    var cancelRow = cancelRange.getValues();

    //openCancelDialog(cancelRow);

    var aSheet = e.source.getActiveSheet().getName();
    var column = e.range.getColumn();
    var row = e.range.getRow();
    Logger.log("Col: " + column + "  Row: " + row + "  Sheet: " + aSheet);
    Logger.log(cancelRow);
  }
  Logger.log(e);
}

function openCancelDialog(row) {
  var ui = SpreadsheetApp.getUi();

  // get template
  var template = HtmlService.createTemplateFromFile('Cancel');

  var myJSON = JSON.stringify(row);

  // pass data to template
  template.data = myJSON;

  // get output html
  var html = template.evaluate();

  // show modal window
  ui.showModalDialog(html, 'Cancel a Project');
}

新HTML:

<!DOCTYPE html>
<html>
  <body>  
    <table>
      <tr><td>Number: </td><td id="number"></td></tr>
      <tr><td>Name: </td><td id="name"></td></tr>
      <tr><td>Category: </td><td id="category"></td></tr>
      <tr><td>Business Owner: </td><td id="owner"></td></tr>
      <tr><td>Project : </td><td id="manager"></td></tr>
    </table>

    <script>
      var objII = JSON.parse(<?=data?>);

      document.getElementById("number").innerHTML = objII[0][0];
      document.getElementById("name").innerHTML = objII[0][4];
      document.getElementById("category").innerHTML = objII[0][1];
      document.getElementById("owner").innerHTML = objII[0][17];
      document.getElementById("manager").innerHTML = objII[0][18];
    </script>

  </body>
</html>

我怀疑可能有更优雅的方法来做到这一点,甚至可能更“正确”的方式 . 但这似乎适用于我需要它做的事情,所以我想我会发布它,万一其他人正在寻找 .

谢谢