【问题标题】:Why my dropdown is so slow to update second dependent dropdown in webapp from google sheet为什么我的下拉列表从谷歌表更新 webapp 中的第二个依赖下拉列表这么慢
【发布时间】:2021-04-07 22:17:05
【问题描述】:

我在第 1 次选择中有大约 50 个数据,在第 2 次选择中有一些数据。这是我的完整代码。 我的问题尤其是第一个选择选项中的第一个项目选择。选择第一个项目时,更新第二个选择选项的速度非常慢。

gs 代码:

function get1st() {

var ss = getSS();
var sheet = ss.getSheetByName('data'); 
var range  = sheet.getRange("A2:A");//or "A2:A" for all data
var vA  = range.getValues();
var dataSize = vA.length;
var options = [];
Logger.log("array size="+ dataSize);
for(let i=2;i<range.getLastRow();i++){
  if(options.indexOf(val = sheet.getRange(i,1).getValue())===-1){
    options.push(val);
  }
  
}
// var dataArray = values.toString().split(",");
// var stringVal = JSON.stringify(dataArray);
// Logger.log(stringVal);
// return JSON.stringify(stringVal); //Modified
Logger.log(options);
return options;

}

function get2nd(first='X60') {

var ss = getSS();
var sheet = ss.getSheetByName('data'); 
var range  = sheet.getRange("A2:A");//or "A2:A" for all data
var vA  = range.getValues();
var dataSize = vA.length;
var options = [];
Logger.log("array size="+ dataSize);
for(let i=2;i<range.getLastRow();i++){
  if(sheet.getRange(i,1).getValue() === first){
    if(options.indexOf(val = sheet.getRange(i,2).getValue())===-1){
    options.push(val);
  }
  }
  
}
// var dataArray = values.toString().split(",");
// var stringVal = JSON.stringify(dataArray);
// Logger.log(stringVal);
// return JSON.stringify(stringVal); //Modified
Logger.log(options);
return options;

}

HTML 代码:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
<script>
    async function  AddList() {
      google.script.run.withSuccessHandler(function(ar) 
    {

    console.log(ar);
    
    List.length = 0;
    
    let option = document.createElement("option");
    option.value = "";
    option.text = "Select State";
    option.selected =true;
    List.appendChild(option);
    
    ar.forEach(function(item, index) 
    {    
      let option = document.createElement("option");
      option.value = item;
      option.text = item;
      List.appendChild(option);    
    });
    
    }).get1st();

    // google.script.run.withFailureHandler(function(error) {
    //   alert("This action failed to complete. Error: "+ error);
    //  }.getCountry();

    };


  window.onload = function() {

  AddList();
}
</script>
  </head>
  <body>
<form id="form">
  <div>
    <label for="List">Country<label>
    <select id="List" name="List"  onclick="SecondSelect(this.value)" required ></select>
  </div>     
  <div>
    <label for="list2">State<label>
    <select id="list2" name="list2" required></select>
  </div>     
</form>

      <a href="#" id="tButton1">click me</a>
      <a href="#" id="tButton2">click me I have a parameter</a>
    <script>
    

        // document.addEventListener("DOMContentLoaded", theDomHasLoaded, false);
        // window.addEventListener("load", pageFullyLoaded, false);
        // function theDomHasLoaded(e) {
        //     alert("haha DOM content is loaded");
        // }

        // function pageFullyLoaded(e){
        //    alert("haha page fully loaded");
        //   document.getElementbyId("tButton1").onclick = function(){myFunction()};
        //   document.getElementbyId("tButton2").onclick = function(){sayHi("Hi")};

        //   function myFunction(){
        //     alert("my Function is called");
        //   }

        //   function sayHi(msg){
        //     alert(msg);
        //   }

        // }

    
    function  SecondSelect(country) {
      var country = document.getElementById("List");
      google.script.run.withSuccessHandler(function(ar) 
    {

    console.log(ar);
    
    list2.length = 0;
    
    let option = document.createElement("option");
    option.value = "";
    option.text = "Select State";
    option.selected =true;
    list2.appendChild(option);
    
    ar.forEach(function(item, index) 
    {    
      let option = document.createElement("option");
      option.value = item;
      option.text = item;
      list2.appendChild(option);    
    });
    
    }).get2nd(country.value);

    // google.script.run.withFailureHandler(function(error) {
    //   alert("This action failed to complete. Error: "+ error);
    //  }.getCountry();

    };

    </script>     
    <!-- <script type="text/javascript" src="cart_Test.js"> </script> -->
   
  

   <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"> 
    </script>
  </body>
</html>

主要问题是它很慢。虽然点击几下后选项显示正确。

【问题讨论】:

  • 您应该避免使用像"A2:A" 这样的范围,因为在 getLastRow() 和 getMaxRows() 之间经常会返回很多尾随空值。 getRange(2,1,sheet.getLastRow()-1,1) 是更好的方法。

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


【解决方案1】:

这个函数做同样的事情,只是它一次获取所有需要的数据并从 vA 中使用它,而不是从循环内部运行 getValue()

function get2nd(first = 'X60') {
  var ss = SpreadsheetApp.getActive();
  var sheet = ss.getSheetByName('data');
  var range = sheet.getRange(2,1,sheet.getLastRow()-1,2);//returning first two columns rather than using getValue() to get them from inside the loop
  var vA = range.getValues();
  var options = [];
  vA.forEach(r=>{
    if(r[0]==first && !~options.indexOf(r[1])) {
      options.push(r[1]);
    }
  }) 
  Logger.log(options);
  return options;
}

您可能会发现阅读best practices 很有价值

bit wise not ~

【讨论】:

  • 我已经使用了您的解决方案。我更容易理解。但是我现在面临的一个问题是在 android chrome 浏览器上,我必须从第一个选择的项目中选择两次,然后只更新第二个选择选项。令人惊讶的是,这在我的笔记本电脑或 PC 中从未出现过。为什么我有线索?
  • Youtube录屏link
  • 对不起,我没有安卓设备,所以在这方面我帮不上忙。
  • 感谢您的帮助。我仍在试图弄清楚为什么下拉项目必须点击两次,有时点击另一个项目,然后再次从选择列表中点击我想要的项目。然后更新第二个项目列表。此问题存在于移动设备中。
【解决方案2】:

修改点:

  • 在您的脚本中,getValue() 用于函数 get1stget2nd 的 for 循环中。在这种情况下,处理成本会变高。现有答案已经提到了这一点。 Ref
  • 在您的情况下,当单元格值在选择第一个下拉列表和第二个下拉列表之间的值时未更改时,如何从 get1st() 的电子表格中检索“A”和“B”列中的所有值? By this, when the 2nd dropdown list is selected, the values for 2nd dropdown list can be put without using google.script.run.我认为当google.script.run的使用次数减少时,流程成本就能降低。

当以上几点反映到你的脚本中时,它变成如下。

Google Apps 脚本方面:

在这种情况下,使用getValues() 的一个函数来代替get1st()get2nd()

function getValues() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('Sheet1');
  return sheet.getRange("A2:B" + sheet.getLastRow()).getValues();
}

Javascript 端:

请修改AddListSecondSelect的功能如下。

AddList()

let values = [];  // Added

function AddList() {
  google.script.run.withSuccessHandler(function(ar) {
    values = ar;  // Added
    List.length = 0;
    let option = document.createElement("option");
    option.value = "";
    option.text = "Select State";
    option.selected = true;
    List.appendChild(option);
    [...new Set(values.map(([a]) => a))]  // Modified
    .forEach(a => {
      let option = document.createElement("option");
      option.value = a;
      option.text = a;
      List.appendChild(option);
    });
  }).getValues();
}

window.onload = function() {
  AddList();
}

SecondSelect()

function SecondSelect(country) {
  var country = document.getElementById("List");
  list2.length = 0;
  let option = document.createElement("option");
  option.value = "";
  option.text = "Select State";
  option.selected = true;
  list2.appendChild(option);
  var v = country.value || 'X60';
  [...new Set(values.filter(([a]) => a == v).map(([,b]) => b))]  // Modified
  .forEach(function(item, index) {
    let option = document.createElement("option");
    option.value = item;
    option.text = item;
    list2.appendChild(option);
  });
}

【讨论】:

  • 谁能指导我SecondSelect函数的参数。 country 在哪里以及如何使用?
  • 我对使用@Tanaike 建议的代码犹豫不决,但是当真正完成后,我可以在我的 PC 中看到 google chrome 浏览器的速度差异。可悲的是,android chrome 浏览器中有些东西不对劲。从第一个列表中选择第一个元素后,第二个列表没有更新。这只是导致大多数问题的第一个元素。
  • 最后通过连接值将两个列表合并为一个 'var dataRow = values.map(row => { return row[0] + " : "+ row[1]}); console.log("数据行"+数据行); dataRow.forEach(function(item, index) { let option = document.createElement("option"); option.value = item; option.text = item; List.appendChild(option); });'
  • @k.b 感谢您的回复。首先,我为I was hesitant to use the code 深表歉意。而且,我必须为我糟糕的英语水平道歉。很遗憾,我无法从您的回复中了解您目前的情况。可以问一下它的详细情况吗?通过这个,我想试着理解它。
  • 感谢@Tanaike 的回复。我完全删除了第二个下拉选择元素,因为在移动设备(android 和 ios)中,第二个选择的行为很奇怪(我必须单击/点击 2-3 次,在第一个选择中切换选项以更新第二个选择选项)。我找不到任何解决方案。因为我的客户等不及了,我们决定将第一个和第二个选项连接在一起,只提供一个下拉菜单。这就是我在上一条消息中回复的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-06
  • 1970-01-01
  • 2021-09-07
  • 2014-11-16
相关资源
最近更新 更多