【问题标题】:Google Sheets Index Sidebar of all tabs - add search functionality所有选项卡的 Google 表格索引侧边栏 - 添加搜索功能
【发布时间】:2022-04-24 01:57:25
【问题描述】:

经过一番搜索,我发现此代码可以将 Google 表格中所有选项卡(工作簿)的侧边栏作为超链接。如果可能的话,我希望为此添加两个功能

  1. 搜索功能 - 侧边栏上的搜索框可以更轻松地查找标签
  2. 同一标签 - 在同一浏览器标签中打开单击的超链接标签,而不是在新窗口中打开。

这是目前为止的代码:

    function onOpen() {
      SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
          .createMenu('Sidebar Menu')
          .addItem('Show sidebar', 'showSidebar')
          .addToUi();
    }
    
    function showSidebar() {
      var ui = HtmlService.createTemplateFromFile('sidebar.html')
          .evaluate()
          .setSandboxMode(HtmlService.SandboxMode.IFRAME)
          .setTitle('Index Sidebar');
      
      SpreadsheetApp.getUi().showSidebar(ui);
    }
        
    function getSheetNames() {
      
      // Get all the different sheet IDs
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheets = ss.getSheets();
      
      return sheetNamesIds(sheets);
    }
        
    // function to create array of sheet names and sheet ids
    function sheetNamesIds(sheets) {
      
      var indexOfSheets = [];
      
      // create array of sheet names and sheet gids
      sheets.forEach(function(sheet){
        indexOfSheets.push([sheet.getSheetName(),sheet.getSheetId()]);
       
      });
      
      //Logger.log(indexOfSheets);
      return indexOfSheets; 
    }

HTML

<!DOCTYPE html>
<h1>Index of all sheets in this workbook:</h1>
<input type="button" value="Close" onclick="google.script.host.close()" />

<ol>
<?!= getSheetNames().map(function(d) {
    return "<li><a href='https://docs.google.com/spreadsheets/d/1234/edit#gid=" + d[1] + "' target='_blank'>" + d[0] + "</a></li>";
    }).join(''); ?>
</ol>

【问题讨论】:

  • 我必须为我糟糕的英语水平道歉。不幸的是,我无法理解1. Search function - a search box on sidebar to look up tabs more easily. 2. Same tab - open the clicked hyperlinked tab in the same browser tab instead of opening in a new window.。可以问一下具体情况吗?

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


【解决方案1】:

建议的解决方案

您应该能够用下面的代码替换您发布的代码并使其正常工作。首先将其复制并粘贴到这两个文件中,然后从工作表中运行它,而不是从脚本编辑器中运行。

HTML

<!DOCTYPE html>
<h1>Index of all sheets in this workbook:</h1>
<script>

function removeElement(elementId) {
    var element = document.getElementById(elementId);
    element.parentNode.removeChild(element);
}

function buildList(text) {
    google.script.run.withSuccessHandler(onSuccess).returnListItems(text)
}

function onSuccess(result) {
    var element = document.createElement("ol")
    element.innerHTML = result
    var sidebar = document.getElementById("sidebar")
    sidebar.appendChild(element)
}

function getTextAndSearch() {
    var text = document.getElementById("text-search").value
    removeElement("ol")
    buildList(text)
}


</script>
<sidebar id="sidebar">
    <input type="button" value="Close" onclick="google.script.host.close()" />
    <br>
    <input type="text" id="text-search" />
    <input type="button" value="Search" onclick="getTextAndSearch()" />

    <ol id="ol">
       <?!=
        returnListItems()
       ?>
    </ol>
</sidebar>

JS

function onOpen() {
  SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
  .createMenu('Sidebar Menu')
  .addItem('Show sidebar', 'showSidebar')
  .addToUi();
}

function showSidebar() {
  var ui = HtmlService.createTemplateFromFile('sidebar.html')
  .evaluate()
  .setSandboxMode(HtmlService.SandboxMode.IFRAME)
  .setTitle('Index Sidebar');
  
  SpreadsheetApp.getUi().showSidebar(ui);
}

function getSheetNames() {
  
  // Get all the different sheet IDs
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheets = ss.getSheets();
  
  return sheetNamesIds(sheets);
}

// function to create array of sheet names and sheet ids
function sheetNamesIds(sheets) {
  
  var indexOfSheets = [];
  
  // create array of sheet names and sheet gids
  sheets.forEach(function(sheet){
    indexOfSheets.push([sheet.getSheetName(),sheet.getSheetId()]);
    
  });
  
  //Logger.log(indexOfSheets);
  return indexOfSheets; 
}

// function to return a button with onclick attribute for each sheet that matches

function returnListItems(text) {
  
    var sheetNames = getSheetNames()
    
    // Checking if there is a search term
    if (text) {
      sheetNames = sheetNames.filter(n => n[0].includes(text))
    }
    
    var htmlString = sheetNames.map(function(d) {
        var string = `
        <li> 
          <input
           type="button"
           value="${d[0]}"
           onclick=\"google.script.run.setActiveByName('${d[0]}')\"/>
        </li>
        `
        return string }).join(' ')
    
    return htmlString
}

// Utility function to set Active sheet by name.
function setActiveByName(name) {
  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(name)
  SpreadsheetApp.setActiveSheet(ss)
}

您可能需要在脚本编辑器中创建一个虚拟函数:function init(){} 并运行它只是为了授予脚本所需的权限,尽管这应该在您从菜单运行脚本时发生。

说明

使工作表成为焦点 - setActiveSheet

这相对简单,所以我将其包含在答案中,虽然技术上是第二个问题。以后确保每个帖子只问一个问题,这样可以使网站上的内容更加整洁,让未来的用户更容易搜索答案。谢谢

这涉及使用setActiveSheet,我为此创建了实用函数setActiveByName

为了将这个函数插入到每个链接中,我编写了函数returnListItems,它为每个按钮生成并返回HTML,以便在单击时调用setActiveByName。把它写成第二个函数并不是绝对必要的,但它让事情变得更清楚了,特别是因为它会使主要问题变得容易得多。

搜索功能

当我快速开始时看起来相对简单的事情变得相当复杂。它涉及将一些代码分解为其组件功能,以使其更易于使用。然而,最大的挑战是正确设置服务器端代码(Apps 脚本编辑器)和客户端代码(包含在 HTML 中)。

加载侧边栏后,我发现对侧边栏 HTML 的任何进一步操作都需要在客户端完成,因此 HTML 中的功能。解决方案位于文档中的"Client-to-Server Communication" 文章中。

按下搜索按钮,然后客户端脚本获取搜索输入框中的文本,将其传递给 buildList 函数,也是客户端,然后调用:

google.script.run.withSuccessHandler(onSuccess).returnListItems([SEARCH_TERM])

这是服务器端的异步函数。 “成功处理程序”是在返回列表项时运行的回调函数。 onSuccess 只是更新侧边栏中的 HTML。我修改了returnListItems 函数以便能够接受搜索词,因此当它第一次运行时,它不带任何参数运行,因此所有工作表都会返回。当被客户端函数调用时,它会以文本形式运行。如果工作表名称包含搜索词,则会列出。

参考文献

【讨论】:

  • 非常感谢您的回复和解释。但是,我得到 Cannot call SpreadsheetApp.getUi() 从这个上下文。 (第 14 行,文件“代码”) 错误。我是不是做错了什么?
  • 您收到此错误是因为您从脚本编辑器而不是菜单项调用该函数。由于脚本是从脚本编辑器运行的,因此没有合适的“UI”对象可供获取。您必须在脚本编辑器中运行任何函数才能授予所有权限,因此您可以考虑创建一个空白函数 function init(){} 并运行它以获取权限,然后从自定义菜单中打开侧边栏床单。在这方面,我会更新我的答案,使其更加清晰。
  • 我添加了一个简短的视频来演示该功能的运行情况,并添加了更多关于设置的说明。
  • 对不起,如果我很痛苦,但现在出现错误:TypeError: Cannot read property 'getSheets' of null (line 21, file "code" 感谢您的 gifs,好嫉妒?为什么它对我不起作用..?
  • 制作电子表格时,是否从电子表格的菜单中打开了脚本编辑器?或者它是一个“单独的”脚本?查看更多关于 here 的信息 - 如果你有一个独立的脚本,那么我认为你需要使用 var ss = SpreadsheetApp.openById("[SS_ID]"); - reference 而不是第 21 行的 var ss = SpreadsheetApp.getActiveSpreadsheet();
【解决方案2】:

感谢 Ian 为您提供上述解决方案。效果很好!经过反复试验,我能够对其进行调整以确保不包含隐藏的工作表。以下是其他感兴趣的人的更新代码:

function onOpen() {
  SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
  .createMenu('Sidebar Menu')
  .addItem('Show sidebar', 'showSidebar')
  .addToUi();
}

function showSidebar() {
  var ui = HtmlService.createTemplateFromFile('Sidebar.html')
  .evaluate()
  .setSandboxMode(HtmlService.SandboxMode.IFRAME)
  .setTitle('Index Sidebar');
  
  SpreadsheetApp.getUi().showSidebar(ui);
}


function getSheetNames() {
  
  // Get all the different sheet IDs
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheets = ss.getSheets().filter(s => !s.isSheetHidden());
  
  return sheetNamesIds(sheets);
}


// function to create array of sheet names and sheet ids
function sheetNamesIds(sheets) {
  
  var indexOfSheets = [];

  // create array of sheet names and sheet gids
  sheets.forEach(function(sheet){
  
    indexOfSheets.push([sheet.getSheetName(),sheet.getSheetId()]);
        
  });

  
  //Logger.log(indexOfSheets);
  return indexOfSheets; 
}


// function to return a button with onclick attribute for each sheet that matches
function returnListItems(text) {
  
    var sheetNames = getSheetNames()
    
    // Checking if there is a search term
    if (text) {
      sheetNames = sheetNames.filter(n => n[0].includes(text))
    }
    
    var htmlString = sheetNames.map(function(d) {
        var string = `
        <li> 
          <input
           type="button"
           value="${d[0]}"
           onclick=\"google.script.run.setActiveByName('${d[0]}')\"/>
        </li>
        `
        return string }).join(' ')
    
    return htmlString
}



// Utility function to set Active sheet by name.
function setActiveByName(name) {
  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(name)
  SpreadsheetApp.setActiveSheet(ss)
}

【讨论】:

    猜你喜欢
    • 2013-09-25
    • 2015-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多