javascript - 如何在 Google 应用程序脚本中将数组显示到 HTML 侧边栏

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

对于 google-apps-script 初学者来说,这是一个大项目,我有一个数组(columnValues)中的 list 列表,需要搜索用户关注的内容(成分)。现在它只是在寻找精确的匹配项,但我要回去让它更智能(在一些帮助下),尽管我现在无法让我的匹配项(匹配项)数组显示在我的侧边栏中。我想最终为用户提供一个更智能的潜在匹配列表(比如搜索水煮鸡会得到鸡胸肉、鸡翅和水煮三文鱼)。单击时,我希望将值写入与用户焦点相关的某些单元格(两个单元格上方)。

那么我应该根据我想做的事情把它做成列表还是表格来显示在侧边栏中呢?我该如何修复构成列表的函数?欢迎任何有关使搜索更智能的建议。也欢迎任何给初学者的提示。

JSFiddle 链接:https://jsfiddle.net/amreinj/fk1a5to7/

Google 文档链接:https://docs.google.com/spreadsheets/d/1Xnbvy4tg2jNhYqL8QKIPJ28AcJ0whygygKzrQ51cGvQ/edit?usp=sharing

我没有使用 jQuery 而这个答案使用了它,可以使用翻译:How to return an array (Google apps script) to a HTML sidebar?

代码.gs

function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('Costing Tools')
    .addItem('Search menu', 'showSidebar')
    .addToUi();
}

function showSidebar() { // Brings up side bar to do inventory search
  var html = HtmlService.createHtmlOutputFromFile('page')
    .setTitle('Inventory search')
    .setWidth(300);
  SpreadsheetApp.getUi()
    .showSidebar(html);
}

function onSearch() { //When the search button is pressed it loops through the inventory list and finds exact matches eventually I'd like it to be smart
  var ui = SpreadsheetApp.getUi();
  var ingredient = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getActiveCell().getValue(); //user focus, they click on the item they want to search
  Logger.log('i ' + ingredient); //debug
  var isheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("INVENTORY");
  var columnValues = isheet.getRange("G:G").getValues(); //inventory list
  var i = columnValues.length,
    array, flag = false,
    matches = [];
  while (i--) { //walk through columnValues
    array = columnValues[i]; //get the ingredient in the li
    if (-1 !== array.indexOf(ingredient)) { //-1, string not found
      flag = true;
      matches.push(array);
    }
  }
  if (!flag) {
    ui.alert('No match found.');
  } else {
    Logger.log('m ' + matches); //debug
    function makeUL(arr) { //This function not working 
      var list = document.createElement('ul'); // Create the list element
      Logger.log(list); //debug
      for (var i = 0; i < arr.length; i++) { //loop through the array to make the list
        var item = document.createElement('li'); // Create the list item
        item.appendChild(document.createTextNode(arr[i])); // Set its contents
        Logger.log(item); //debug
        list.appendChild(item); // Add it to the list
      }
      Logger.log(list); //debug
      return list;
    }
    document.getElementById('foo').appendChild(makeUL(matches)); //this doesn't work
  }
}


页面.html

<!DOCTYPE html>
<html>
  <head>
    <script >
    </script>
    <base target="_top">
  </head>
  <body>
    <p>Click on the ingredient you want to find in inventory and then click search.</p>
    <button onclick="google.script.run.onSearch()">Search</button>
    <br>
    <br>
    <div id="foo">Results</div>
  </body>
</html>

最佳答案

"How could I fix the function that makes the list?"

你编写函数 makeUL(arr) 的地方,它负责 DOM 操作和这行代码:

document.getElementById('foo').appendChild(makeUL(matches));

完全是在错误的地方。您正在尝试在 google app script code.gs 文件中操作 HTML DOM 元素,而 google app script 无法直接操作 dom 元素。 HTML 的 document 和它的 API 在谷歌应用程序脚本中不可用。它在浏览器中可用。

那么你应该怎么做?

您应该将 matches 列表从 google app script 返回给客户端,并在 page.html 中编写您的 makeUL 函数您的 javascript 将运行。

page.html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <p>Click on the ingredient you want to find in inventory and then click search.</p>
    <button onclick="onSearchClickHandler()">Search</button>
    <br>
    <br>
    <div id="foo">Results</div>
    <script>

    // search button click handler
    function onSearchClickHandler(e){
        google.script.run
           .withFailureHandler(function(err){
               // failure handler callback
               console.log(err)
           })
           .withSuccessHandler(function(arr){
                // arr is your match array returned by onSearch
                if(arr.length > 0){
                    var domList = makeUL(arr);
                    // document object will be available here
                    document.getElementById('foo').appendChild(domList);
                }
            })
           .onSearch()
    }

    function makeUL(arr) {  
        var list = document.createElement('ul'); // Create the list element
        console.log(list); //debug
        for (var i = 0; i < arr.length; i++) { //loop through the array to make the list
            var item = document.createElement('li'); // Create the list item
            item.appendChild(document.createTextNode(arr[i])); // Set its contents
            console.log(item); //debug
            list.appendChild(item); // Add it to the list
        }
        console.log(list); //debug
        return list;
    }
    </script>
  </body>
</html>

另请注意,在 makeUL 函数中,我已将 Logger.log 替换为 console.log,这是因为 Loggergoogle app script 中可用,console 在浏览器 window 对象中可用。

代码.gs:

function onSearch() { //When the search button is pressed it loops through the inventory list and finds exact matches eventually I'd like it to be smart
  var ui = SpreadsheetApp.getUi();
  var ingredient = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getActiveCell().getValue(); //user focus, they click on the item they want to search
  Logger.log('i ' + ingredient); //debug
  var isheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("INVENTORY");
  var columnValues = isheet.getRange("G:G").getValues(); //inventory list
  var i = columnValues.length,
    array, flag = false,
    matches = [];
  while (i--) { //walk through columnValues
    array = columnValues[i]; //get the ingredient in the li
    if (-1 !== array.indexOf(ingredient)) { //-1, string not found
      flag = true;
      matches.push(array);
    }
  }
  if (!flag) {
    ui.alert('No match found.');
  } 
  return matches;
}

我自己没有运行代码,但它应该是这样工作的。

"So should I make it a list or a table to display it in the sidebar based on what I want to do?"

完全取决于您想要实现的用户体验;你如何设计你的用户界面。

"Any advice on making the search smarter would be welcome."

根据您的用例,您可以将成分分解为单独的词,然后进行匹配。如果任何关键字匹配,则将其添加到匹配数组。即在您的配料表中:鸡胸肉、鸡翅。用户搜索鸡肉时,可以用空格符拆分配料:

ingredientList = ["chicken breast", "chicken wings"];
ingredientWords = ingredientList[0].split(" ");

ingredientWords 将有 ["chicken", "breast"] 并检查此数组是否包含您的搜索词“chicken”,然后您可以在匹配项中添加该项目.

如果你想要更高级的匹配方案,你可以使用Levenshtein distance algorithm , bitap algorithm .您可以使用 fuzzy matching algorithms .你会发现很多字符串匹配、字符串相似度算法。使用高级算法取决于您的用例和您想要实现的目标。

" Also any tips for a beginner would be welcome."

通过谷歌应用程序脚本教程,查看 documentation了解哪些 API 可用以及它们的作用。此外,google app script 在 google 服务器上运行,因此您在浏览器中获得的所有那些 API 和 javascript 对象,即 window、document、console、alert 等在 google 上不可用应用程序脚本。操作 HTML dom 的代码应该在客户端,即浏览器上。

如何将字符串和对象从 google app script 发送到您在 中的客户端代码 document bound script 看到这个answer .

关于javascript - 如何在 Google 应用程序脚本中将数组显示到 HTML 侧边栏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39022630/

相关文章:

javascript - 动态数据到数组时出错

java - 按字母顺序对数组进行排序

javascript - 错误 : '[object Object]' of type 'object' . NgFor 仅支持绑定(bind)到 Iterables,例如 Arrays。 - ionic 项目

javascript - Nodejs : Run a js file on node server startup

html - 在列表导航菜单中缩放背景图像的大小

html - 为什么小空间不断出现在我的网页中?

javascript - 附加另一个时删除子表

javascript - JQuery .find() 多个数组的函数

javascript - onclick 的旋转代码不起作用?

c - 读入短语并过滤掉字符以查找数字 C