如何在Google Apps脚本中将数组显示到HTML侧边栏

时间:2016-08-18 15:53:08

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

这是google-apps-script初学者的一个大项目,我在数组中有一个清单列表(columnValues),这需要搜索用户关注的内容(成分)。现在它只是寻找完全匹配,但我会回去让它变得更聪明(有一些帮助),现在虽然我很难得到我的数组匹配(匹配)我的侧边栏。我想最终给用户一份更聪明的潜在匹配清单(比如搜寻水煮鸡会产生鸡胸肉,鸡翅和水煮鲑鱼)。单击时,我希望将相对于用户焦点(两个单元格)的值写入某些单元格。

那么我应该根据我想做的事情将它作为列表或表格显示在侧边栏中吗?我怎样才能修复列表的功能?任何关于使搜索变得更聪明的建议都会受到欢迎。此外,欢迎任何有关初学者的提示。

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

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

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

Code.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
  }
}


page.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>

1 个答案:

答案 0 :(得分:2)

  

“我如何修复列表的功能?”

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

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

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

那么你应该做什么?

您应该将matches的列表从谷歌应用脚​​本返回给客户端,并在makeUL中写下page.html功能,这是您的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,这是因为 Logger 可在 google应用程序脚本中找到窗口对象中提供了>和 console

<强> Code.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;
}

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

  

“那么我应该根据我想要做的事情将它作为列表或表格显示在侧边栏中吗?”

完全取决于您的用户体验您想要达到的目标;如何设计UI。

  

“任何有关使搜索变得更聪明的建议都会受到欢迎。”

从您的用例中,您可以用单独的单词分解您的成分然后匹配。如果任何关键字匹配,则将其添加到匹配数组。即在你的食材清单中:鸡胸肉,鸡翅。当用户搜索鸡时,您可以使用空格字符分割成分:

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

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

如果您想要更高级的匹配方案,可以使用Levenshtein distance algorithmbitap algorithm。您可以使用fuzzy matching algorithms。你会发现许多字符串匹配,字符串相似性算法。使用高级算法取决于您的使用案例以及您希望实现的目标。

  

“也欢迎初学者的任何提示。”

浏览google应用程序脚本教程,请参阅documentation以了解哪些API可用以及它们的用途。此外,谷歌应用程序脚本在谷歌服务器上运行,所以你在浏览器中获得的所有那些API和javascript对象,即窗口,文档,控制台,警报等。在谷歌上不可用应用脚本。操作HTML dom的代码应该在客户端,即浏览器上。

如何将谷歌应用脚​​本中的字符串和对象发送到 document bound script 中的客户端代码,请参阅此answer