【问题标题】:Need help updating dropdowns in HTML Web Apps using Google Apps Script需要帮助使用 Google Apps 脚本更新 HTML Web Apps 中的下拉菜单
【发布时间】:2021-01-17 03:23:31
【问题描述】:

这是我第一次在这里发帖,如果我需要编辑任何内容,请告诉我。

我正在开发一个程序,该程序运行在谷歌表格中导入的数据,在 HTML Web 应用程序中显示一个“行”数据,然后用户可以在其中将帐号(在下拉列表中找到)分配给显示的项目,然后移动到数据中的下一行。数据中的每个项目都有一个 ID 号,用户根据该 ID 号和数据描述,在列表中选择适当的帐号分配给数据。

问题是这样的帐号有数百个,让用户滚动/搜索这些帐号以找到正确的帐号将非常乏味。

好消息是,只有某些帐户可以分配一个 ID 号。我可以有效地对下拉列表进行排序以仅显示可以分配给当前 ID 的帐户,从而使用户的工作更加轻松和快捷。

但是,我不知道如何在项目加载到 html 页面后更新下拉列表。我能够获取当前的 ID 号并对帐户进行排序,但我无法更新下拉列表。

我已经粘贴了 code.gs 和 html/javascript 代码。 我没有在 code.gs 文件中包含所有代码,因为其中一些与我的问题无关。

我正在使用 Materialise CSS。

代码.gs:

var url = "hidden";

var ss = SpreadsheetApp.openByUrl(url);
var masterWS = ss.getSheetByName("Master List");

var items = [];

var Route = {};

Route.path = function (route, callback){
  Route[route] = callback;
}

function doGet(e) {

  Route.path("summary", summaryPage);
  Route.path("edit", editPage);

  if(Route[e.parameters.v]){
    return Route[e.parameters.v]();
  } else {
    return editPage();
  }

  

}

function summaryPage(){
  var tmp =  HtmlService.createTemplateFromFile("summary");

  var sumList = showSummary();

  tmp.summaryList = sumList;

  return tmp.evaluate();
}

function include(fileName){
  return HtmlService.createHtmlOutputFromFile(fileName).getContent();
}

function editPage(){

  var ss = SpreadsheetApp.openByUrl(url);
  var ws = ss.getSheetByName("GLAccounts");
 
  // Create drop down and populate with all account options
  var SSassetList = ws.getRange(2,1, getLastRowSpecial("A", "GLAccounts"),1).getValues();
  var htmlAssetList = SSassetList.map(function (r){return '<option>' + r[0] + '</option>';}).join('');

  var tmp = HtmlService.createTemplateFromFile("page");

  tmp.assetList = htmlAssetList;
  
  return tmp.evaluate();

}


function calculateTotalEntries(){

  //Logger.log("Done: " + done);
  var lastRow = masterWS.getLastRow();
  var totalEntries = 0;
  
  var i = lastRow;
  while (masterWS.getRange(i, 1).getValue() != "Transaction Date"){
    i--;
    totalEntries++;
  }



  masterWS.getRange("R1").setValue(totalEntries);
  masterWS.getRange("R2").setValue(lastRow);


}


function userClicked(userInfo){

  var r = masterWS.getRange("P1").getValue();
  var GLAccount = userInfo.act;

  var lastRow = masterWS.getRange("R2").getValue();
  var totalEntries = masterWS.getRange("R1").getValue();


  if(!(masterWS.getRange("P3").getValue())){
    //Logger.log("Done parsing. Items length: " + items.length);
    if(r <= totalEntries - 1 ){
      masterWS.getRange("P4").setValue(lastRow - totalEntries + 1 + r);
      if(masterWS.getRange("P1").getValue() != 0){
        masterWS.getRange(lastRow - totalEntries + r, 8).setValue(GLAccount);
      }
      r = r + 1;
      masterWS.getRange("P1").setValue(r);
    } else {
      //Logger.log("Last one"); 
      masterWS.getRange("P3").setValue(true);
      masterWS.getRange(lastRow, 8).setValue(GLAccount);
      //return Error;
      resetCounters();
      calculateChange();
    } 
  } 
    
     
    
}

function showItem(){
  var row = masterWS.getRange("P4").getValue();
  return "Item: " + masterWS.getRange(row,5).getValue() + "; Date: " + slice(masterWS.getRange(row,1).getValue(), 13) + "; ID: "+ masterWS.getRange(row,6).getValue();
}

function getData(){
  
  var row = masterWS.getRange("P4").getValue();
  var id = "";
  id = masterWS.getRange(row,6).getValue().toString();
  
  var availAccounts = [];

  var IDSheet = ss.getSheetByName("MerchantCodes");
  var lastIDRow = IDSheet.getLastRow();

  var lastIDCol = 0;

  var currentRow = 0;

  for(var i = 6; i < lastIDRow; i++){
    if(IDSheet.getRange(i, 1).getValue().toString() == id){
      currentRow = i;
      break;
    }
  }

  //Logger.log("ID: " + id + " @ row " + i);
  for( var j = 1; j < 10; j++){
    if(IDSheet.getRange(currentRow,j).getValue() != ""){
      lastIDCol = j;
    }
  }
  //Logger.log("Last Column for row  " + i + ": " + lastIDCol);
  for(var r = lastIDCol - (lastIDCol - 3) + 1; r < lastIDCol+1; r++){
    //Logger.log("Account: " + IDSheet.getRange(currentRow,r).getValue());
    availAccounts.push(IDSheet.getRange(currentRow,r).getValue());
  }

  return availAccounts;

}

function resetCounters(){
  masterWS.getRange("P1").setValue(0);
  masterWS.getRange("P3").setValue(false);
  masterWS.getRange("P4").setValue("");
  masterWS.getRange("P5").setValue("");
  masterWS.getRange("P6").setValue("");
}
 


function getLastRowSpecial(col, sheetName){
  var ss = SpreadsheetApp.openByUrl(url);
  var ws = ss.getSheetByName(sheetName);
  var data = ws.getRange(col + "2:" + col).getValues();
  var lastRowData = data.filter(String).length;

  return lastRowData;
}
}

HTML:

Web 应用程序中显示的项目(根据数据而变化)位于标签中。 使用标签填充下拉列表。这些标签中的数据来自 code.gs 文件中的 doGet() 和 editPage() 函数。

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
    <?!= include("page-css"); ?>
  </head>
  <body>

  <div class = "container">  <!-- Open container -->

    <div> <!-- Open row -->
      <label>Item</label>
      <p><span id="current"></span></p>
    </div> <!-- Close row -->

    <div class ="row"> <!-- Open row -->

      <button id="btn2" class="btn waves-effect waves-light red darken-3" type="submit" name="action">Start</button> 

    </div> <!-- Close row -->

  
    <div class ="row"> <!-- Open row -->

      <div class="input-field col s6">
        <select id="glAcc">
          <option disabled selected>Choose your GL Account</option>

            <?!= assetList; ?>
 
        </select>
        <label>GL Account</label>
      </div>

    </div> <!-- Close row -->
    
    <div class ="row"> <!-- Open row -->

    <button id="updDrop" class="btn waves-effect waves-light red darken-3" type="submit"            name="action">Update Dropdown
        <i class="material-icons right">send</i>
      </button> 

    </div> <!-- Close row -->

    <div class ="row"> <!-- Open row -->

      <button id="btn" class="btn waves-effect waves-light red darken-3" type="submit" name="action">Submit
        <i class="material-icons right">send</i>
      </button> 

    </div> <!-- Close row -->

    <div class ="row"> <!-- Open row -->

      <a href="<?= ScriptApp.getService().getUrl(); ?>?v=summary" id="summary" class="btn waves-effect waves-light red darken-3" type="submit" name="action">Go to Summary Page
        <i class="material-icons right">arrow_forward</i>
      </a> 

    </div> <!-- Close row -->


  </div> <!-- Close container -->

    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
    <?!= include("page-js"); ?>

  </body>
</html>

HTML JS 代码:

<script>

document.addEventListener('DOMContentLoaded', function(){
  var elems = document.querySelectorAll('select');
  var instances = M.FormSelect.init(elems);
});
document.addEventListener('DOMContentLoaded', reset);

document.getElementById("btn").addEventListener("click",doStuff);
document.getElementById("btn2").addEventListener("click",doStuff);
document.getElementById("sumBtn").addEventListener("click", summary);
document.getElementById("updDrop").addEventListener("click", updateDropdown);


function doStuff(){

  var userInfo = {};
  
  userInfo.act = document.getElementById("glAcc").value;
    
  google.script.run.withSuccessHandler(findItem).userClicked(userInfo);
  //findItem();
  //google.script.run.getLength();
  
  // Reset dropdown
  var myApp = document.getElementById("glAcc");
  myApp.selectedIndex = 0;
  M.FormSelect.init(myApp);
} 

function reset(){
  google.script.run.resetCounters();
  google.script.run.calculateTotalEntries();

  document.getElementById("current").textContent = "Click the Start Button";
}

function updateDropdown(){
  google.script.run.withSuccessHandler(updateSelect).getData();
}

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

function findItem(){
  google.script.run.withSuccessHandler(changeItem).showItem();
}

function changeItem(item){
  document.getElementById("current").textContent = item;
  //document.getElementById("options"). = "<option>1</option><option>2</option>";
  
}

function summary(){
  google.script.run.withSuccessHandler(findSummary).calculateChange();
}

function findSummary(){
  google.script.run.withSuccessHandler(changeSummary).showSummary();
}

function changeSummary(summary){
  document.getElementById("sumText").textContent = summary;
}


</script>

总的来说,我希望下拉选项随着显示的项目也更新而更新。如果不能同时更新,我可以添加一个按钮,点击后会更新下拉列表。

我不想将整个代码/电子表格分享给所有人,但如果你想访问,请给我发消息,我可以分享给你。

谢谢。

【问题讨论】:

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


    【解决方案1】:

    欢迎来到 SO 社区。​​p>

    我认为问题不在于 Apps 脚本。

    当你使用 Materialize Select 时,你需要重新初始化它。

    这是我在我的代码库中找到的函数,它应该可以帮助你:

    function fillMaterializeSelect(elSelect, data) {
    
        elSelect.options.length = 0;
    
        for (let i = 0; i < data.length; i++) {
    
          const dataElement = data[i];
    
          const option = document.createElement("option");
          option.value = dataElement.value;
          option.text = dataElement.text;
          elSelect.add(option);
    
        }
    
        M.FormSelect.init(elSelect);
    
    }
    

    【讨论】:

    • 完美!这行得通。我只需要重新初始化表单,它就开始按计划工作。谢谢!
    【解决方案2】:

    这是一个我经常使用的 JavaScript 函数来更新&lt;select&gt;

    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]);//one is the value and the other is the display value
        }
      }
    

    您使用 a 检索数据

    gooogle.script.run
    .withSuccessHandler(updateSelect)
    .getData();
    

    【讨论】:

    • 感谢您的回答。这是有道理的,我假设 getData() 函数是我在 code.gs 文件中创建的一个函数,它返回我想要放入下拉列表中的所有选项/帐户的数组。它还必须返回 elementID,还是我可以删除 element ID 参数?谢谢
    • 它可以返回任何你想要的东西 我是这样写的,因为有时我想使用多个下拉菜单,这样我就可以在一个函数中全部使用,这样你就可以将返回对象更改为一个对象而不是数组,然后只重写更新选择函数
    • 好的。我刚写完代码,在
    • 请不要在评论中发布您的代码,如果您在问题中发布代码会更容易阅读。
    • 对不起,我对堆栈溢出还是新手。我刚刚更新了问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-09
    相关资源
    最近更新 更多