如何在Google Apps Script中打开带表格数据的侧边栏并实现服务端到客户端传参?
服务端变量无法传递到客户端的问题排查与修复
当前代码目标是打开侧边栏后读取表格数据并构建表格,但存在服务端变量无法传递到客户端的问题,且无报错信息。以下是问题分析及修复方案:
原代码梳理
1. Sidebar.html(侧边栏主页面)
<!DOCTYPE html> <html> <head> <base target="_top"> <?!= HtmlService.createHtmlOutputFromFile('Client_side_Functions').getContent(); ?> <!-- <?!= 'Client_side_Functions' ?> --> <!-- <?!= Client_side_Functions ?> --> </head> <body> <h1>Importer Data</h1> <div id="importerData"></div> </body> </html>
2. Client_side_Functions.html(客户端脚本)
<script> var importer = <?= JSON.stringify(importer) ?>; function displayImporterData(importer) { google.script.run.withSuccessHandler(function(data){ var importerDataDiv = document.getElementById("importerData"); if (importerData && importerData.length > 0) { var table = document.createElement("table"); var thead = document.createElement("thead"); var tbody = document.createElement("tbody"); // Table headers var headerRow = document.createElement("tr"); var headers = ["Exportador", "Items", "Peso Bruto (Kg)", "Data"]; headers.forEach(function(header) { var th = document.createElement("th"); th.textContent = header; headerRow.appendChild(th); }); thead.appendChild(headerRow); table.appendChild(thead); //Table body - importer data importerData.forEach(function(rowData) { var row = document.createElement("tr"); rowData.forEach(function(cellData) { var td = document.createElement("td"); td.textContent = cellData; row.appendChild(td); }); tbody.appendChild(row); }); table.appendChild(tbody); importerDataDiv.appendChild(table); } else { importerDataDiv.textContent = "No importer data found."; } }).getImports(importer); } </script>
3. 服务端脚本(Code.gs)
function openSideBar() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const painelSht = ss.getSheetByName('Painel'); const importer = painelSht.getRange(row, 1).getValue(); const js = 'Client_side_Functions'; const html2 = HtmlService.createTemplateFromFile(js); html2.importer = JSON.stringify(importer); const html2Content = html2.evaluate().getContent(); const htmlWindow = HtmlService.createTemplateFromFile("Sidebar"); htmlWindow[js] = html2Content; const sidebarHtml = htmlWindow.evaluate().getContent(); SpreadsheetApp.getUi().showSidebar(HtmlService.createHtmlOutput(sidebarHtml)); } function getImports(importer) { const exportsFileId = 'fileID'; const exportsFile = SpreadsheetApp.openById(exportsFileId); const exportsSht = exportsFile.getSheetByName('Sheet1'); const exportsData = exportsSht.getDataRange().getValues().filter(e => e[1].indexOf(importer) !== -1); return exportsData; }
问题根源
- 变量传递逻辑错误:
openSideBar中先对Client_side_Functions模板赋值并evaluate,再将内容传给Sidebar模板,但Sidebar又直接重新加载Client_side_Functions,导致之前赋值的importer变量完全丢失。 - 客户端函数未触发:页面加载后
displayImporterData函数未被调用,不会自动获取数据。 - 回调参数名不匹配:
withSuccessHandler的参数是data,但代码中使用importerData,导致变量未定义。 row变量未定义:painelSht.getRange(row, 1)中的row无赋值,属于潜在报错点。
修复方案
1. 调整服务端变量传递逻辑(Code.gs)
直接在主模板中传递变量,避免重复加载模板导致变量丢失:
function openSideBar() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const painelSht = ss.getSheetByName('Painel'); // 定义row变量,这里取当前活动行,可根据需求调整 const row = ss.getActiveCell().getRow(); const importer = painelSht.getRange(row, 1).getValue(); // 直接加载主模板并传递变量 const htmlWindow = HtmlService.createTemplateFromFile("Sidebar"); htmlWindow.importer = importer; SpreadsheetApp.getUi().showSidebar(htmlWindow.evaluate()); }
2. 修改Sidebar.html
传递变量并在页面加载时触发函数:
<!DOCTYPE html> <html> <head> <base target="_top"> <!-- 传递服务端变量到客户端 --> <script> const importer = <?= JSON.stringify(importer) ?>; </script> <!-- 加载客户端函数脚本 --> <?!= HtmlService.createHtmlOutputFromFile('Client_side_Functions').getContent(); ?> </head> <body onload="displayImporterData(importer)"> <h1>Importer Data</h1> <div id="importerData"></div> </body> </html>
3. 修复客户端脚本(Client_side_Functions.html)
修正参数名并添加错误处理:
<script> function displayImporterData(importer) { google.script.run .withSuccessHandler(function(importerData){ const importerDataDiv = document.getElementById("importerData"); if (importerData && importerData.length > 0) { const table = document.createElement("table"); const thead = document.createElement("thead"); const tbody = document.createElement("tbody"); // 构建表头 const headerRow = document.createElement("tr"); const headers = ["Exportador", "Items", "Peso Bruto (Kg)", "Data"]; headers.forEach(header => { const th = document.createElement("th"); th.textContent = header; headerRow.appendChild(th); }); thead.appendChild(headerRow); table.appendChild(thead); // 构建表体 importerData.forEach(rowData => { const row = document.createElement("tr"); rowData.forEach(cellData => { const td = document.createElement("td"); td.textContent = cellData; row.appendChild(td); }); tbody.appendChild(row); }); table.appendChild(tbody); // 添加基础样式(可选) table.style.borderCollapse = "collapse"; table.style.width = "100%"; th.style.border = "1px solid #ddd"; th.style.padding = "8px"; th.style.backgroundColor = "#f2f2f2"; td.style.border = "1px solid #ddd"; td.style.padding = "8px"; importerDataDiv.appendChild(table); } else { importerDataDiv.textContent = "未找到Importer数据。"; } }) .withFailureHandler(error => { document.getElementById("importerData").textContent = `加载失败: ${error.message}`; }) .getImports(importer); } </script>
4. 优化服务端查询函数(Code.gs)
添加空值判断避免报错:
function getImports(importer) { if (!importer) return []; const exportsFileId = 'fileID'; const exportsFile = SpreadsheetApp.openById(exportsFileId); const exportsSht = exportsFile.getSheetByName('Sheet1'); const exportsData = exportsSht.getDataRange().getValues() .filter(row => row.length > 1 && row[1].toString().indexOf(importer.toString()) !== -1); return exportsData; }
内容的提问来源于stack exchange,提问作者onit
相关产品推荐
相关产品推荐

