Google Apps Script报错:range.getDisplayValues is not a function 求助
问题分析与解决方案
问题还原
我需要在网站中展示Google表格指定范围的内容,默认展示rangeB为"P6:R34";当日14:13过后,rangeB切换为"P5:R34"。但代码运行时报错:
TypeError: range.getDisplayValues is not a function (line 31, file "Code")
原代码
Code.gs
function doGet() { template = HtmlService.createTemplateFromFile('Index.html'); return template.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME) .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL); } var now = new Date().getTime() ; var d = new Date(); var year = d.getFullYear(); var month = d.getMonth(); var date = d.getDate(); var ctdr = new Date(year, month, date, 14, 13, 00).getTime(); distance = ctdr - now; var spreadsheetId = '1jH0y-PknkZXH7KqjPBWDv98kkBnndGt_GIbdUh_1nRM'; var sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName("LNW") ; rangeA = sheet.getRange("P4:R4") ; rangeB = sheet.getRange("P6:R34") ; range = [rangeA, rangeB] ; if (distance < 0) { rangeB = sheet.getRange("P5:R34") ; } var dataValues = range.getDisplayValues() .map(row => row.map(value => value.replace(/\n/g, `<br/>`) ) );
Index.html
<!DOCTYPE html> <html> <head> <base target="_top"> </head> <style> table, tbody, tr, th, td { text-align:center; font-family: Arial, sans-serif; font-size: 14.5px ; border-collapse: collapse; margin : auto ; } th { background-color: #f5f5f5 ; padding : 6px ; } </style> <body> <table cellpadding="12px" > <? var tableData = dataValues ?> <? for(var i = 0; i < tableData.length; i++) { ?> <? if(i == 0) { ?> <tr> <? for(var j = 0; j < tableData[i].length; j++) { ?> <th> <?= tableData[i][j] ?></th> <? } ?> </tr> <? } else { ?> <tr> <? for(var j = 0; j < tableData[i].length; j++) { ?> <td> <?= tableData[i][j] ?></td> <? } ?> </tr> <? } ?> <? } ?> </table> </body> </html>
报错原因
- 数组调用Range专属方法:你把
rangeA和rangeB存入数组range = [rangeA, rangeB],但getDisplayValues()是Range对象的专属方法,数组没有这个方法,直接调用就会触发报错。 - 逻辑更新无效:即使没有报错,你在时间判断后重新赋值的
rangeB并没有更新到range数组中,导致14:13过后展示的还是旧范围数据。 - 数据未传递到模板:原代码中没有把
dataValues赋值给模板变量,HTML无法获取数据进行渲染。
解决方案
提供两种合并范围数据的方式,同时修复所有问题:
方式一:分别获取数据后数组合并
这种方式简单直接,适合少量范围的合并:
function doGet() { // 时间判断逻辑 var now = new Date().getTime(); var d = new Date(); var ctdr = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 14, 13, 0).getTime(); var distance = ctdr - now; // 表格操作 var spreadsheetId = '1jH0y-PknkZXH7KqjPBWDv98kkBnndGt_GIbdUh_1nRM'; var sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName("LNW"); var rangeA = sheet.getRange("P4:R4"); // 根据时间选择对应的rangeB var rangeB = distance < 0 ? sheet.getRange("P5:R34") : sheet.getRange("P6:R34"); // 分别获取两个范围的显示值,再合并数组 var dataA = rangeA.getDisplayValues(); var dataB = rangeB.getDisplayValues(); var dataValues = dataA.concat(dataB) .map(row => row.map(value => value.replace(/\n/g, `<br/>`))); // 将数据传递给HTML模板 var template = HtmlService.createTemplateFromFile('Index.html'); template.dataValues = dataValues; return template.evaluate() .setSandboxMode(HtmlService.SandboxMode.IFRAME) .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL); }
方式二:使用RangeList批量处理范围
如果需要合并多个不连续范围,推荐使用RangeList,更高效:
function doGet() { // 时间判断逻辑 var now = new Date().getTime(); var d = new Date(); var ctdr = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 14, 13, 0).getTime(); var distance = ctdr - now; // 表格操作 var spreadsheetId = '1jH0y-PknkZXH7KqjPBWDv98kkBnndGt_GIbdUh_1nRM'; var sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName("LNW"); // 根据时间选择对应的rangeB字符串 var rangeBStr = distance < 0 ? "P5:R34" : "P6:R34"; // 创建RangeList对象,包含需要合并的范围 var rangeList = sheet.getRangeList(["P4:R4", rangeBStr]); // 获取所有范围的显示值,展平为二维数组后处理换行符 var dataValues = rangeList.getDisplayValues() .flat() // 把二维数组的数组展平为一个二维数组 .map(row => row.map(value => value.replace(/\n/g, `<br/>`))); // 将数据传递给HTML模板 var template = HtmlService.createTemplateFromFile('Index.html'); template.dataValues = dataValues; return template.evaluate() .setSandboxMode(HtmlService.SandboxMode.IFRAME) .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL); }
注意事项
- 两种方式都修复了数据传递问题:通过
template.dataValues = dataValues将处理好的数据传给HTML模板,确保表格能正常渲染。 - 时间判断逻辑进行了简化,无需单独提取年、月、日,直接用
d对象的方法即可。
内容的提问来源于stack exchange,提问作者Prabhu Paul
相关产品推荐
相关产品推荐

