经过一番搜索,我发现这段代码可以将 Google 表格中所有选项卡(工作簿)的侧边栏作为超链接获取。如果可能的话,我希望为此添加两个功能
这是到目前为止的代码:
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>
您应该能够用下面的代码替换您发布的代码并使其正常工作。首先将其复制并粘贴到两个文件中,然后从工作表运行,而不是从脚本编辑器运行。
<!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>
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 中完成功能。解决方案位于文档中的“客户端到服务器通信”文章中。
按下搜索按钮,然后客户端脚本获取搜索输入框中的文本,将其传递给
buildList
函数(也是客户端),该函数依次调用:
google.script.run.withSuccessHandler(onSuccess).returnListItems([SEARCH_TERM])
这是一个位于服务器端的异步函数。 “成功处理程序”是返回列表项时运行的回调函数。
onSuccess
只是更新侧边栏中的 HTML。我修改了 returnListItems
函数以能够接受搜索词,因此当它第一次运行时,它运行时不带任何参数,因此所有工作表都会返回。当由客户端函数调用时,它会以文本运行。如果工作表名称包含搜索词,则会列出它。
感谢 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)
}