[返回故事] 我有一张Google工作表,用于通过电子邮件将时间表发送给分包商。每个分包商都有自己的表格,我还有一张名为MasterSchedule的最后一张表。
主计划使用对所有单个工作表的引用,以便所有转包计划都可见。尽管如此,这仍然很重要。因此,我在所有工作表中都包含了一个帮助列,只返回 true 或 false ,指示是否应在主数据库中显示行。
然而,行仍然显示在主服务器上,但是帮助程序列恰好是假的。所以我用AutoFilter来隐藏它。
问题:Google Apps脚本没有自动过滤器的API。像VBA使用标准等。所以我看到的唯一选择是隐藏行。但这很慢。我知道这个想法是为了减少对Google服务的调用次数,谷歌建议制作一个阵列然后在阵列上拨打电话。我不知道该怎么做。
我需要一个高效的脚本/函数来查看列和每个读取 false 的单元格,该函数将隐藏整行,并显示所有其他行。
最快的非脚本方法是使用Google表格版自动过滤器,只需取消选中 false 。
我尝试创建一个for循环来读取列中的每个单元格,如果单元格值为false,则每次迭代都会隐藏该行。 速度非常慢。
请参阅:
function MasterFilter() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var maxRows = sheet.getMaxRows();
//show all the rows
sheet.showRows(1, maxRows);
//get data from column B
var data = sheet.getRange('B:B').getValues();
//iterate over all rows
for(var i=5; i< data.length; i++){
if(sheet.getRange(i,2).getValue() == false){
sheet.hideRow(i);
}
}
}
答案 0 :(得分:1)
我必须更改原始代码的一行,才能使其正常工作:
sheet.hideRow(sheet.getRange(i,2)); // Operates on a range
有了这个,我把它计时在一个测试电子表格上,大约200行,true
/ false
个单元格均匀分布。执行记录报告[4.656 seconds total runtime]
。
如您所料,您可以通过使用包含一组数据的数组(在本例中为B列的所有内容)来减少服务调用。这是“隐藏”方法,使用数组来测试可见性:
function MasterFilter() {
var headers = 4; // # rows to skip
var sheet = SpreadsheetApp.getActiveSheet();
var maxRows = sheet.getMaxRows();
//show all the rows
sheet.showRows(1, maxRows);
//get data from column B
var data = sheet.getRange('B:B').getValues();
//iterate over all rows
for(var i=headers; i< data.length; i++){
if(data[i][0] == false){
sheet.hideRow(sheet.getRange(i+1,1));
}
}
}
根据执行记录,这需要[0.106 seconds total runtime]
作为测试表。观看屏幕时,刷新时看起来像是3或4秒。
这是另一种方法。在这一篇中,我们读取了主表上的所有数据,然后使用Array.filter()
将二维数组简化为只有列B中true
的行。然后将这个较小的集合写入在我们清除所有以前的内容后,主表。根据执行记录,这会将执行时间缩短一半[0.059 seconds total runtime]
。再一次,刷新查看副本的延迟使它看起来像几秒钟。
// Evaluation function for Array.filter()
function isVisible(row) {
return (row[1] === true); // Check column B
}
function MasterFilter2() {
var headers = 4; // # rows to skip
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var headerData = data.splice(0,headers); // Skip header rows
var filteredData = data.filter( isVisible );
var outputData = headerData.concat(filteredData); // Put headers back
sheet.clearContents(); // Clear content, keep format
// Save filtered values
sheet.getRange(1, 1, outputData.length, outputData[0].length).setValues(outputData);
}