我是电子表格脚本的新手。我正在根据另一张表格生成一份报告(新表格),我每天都会输入值。在Apps脚本中,我首先生成工作表然后遍历从该输入表检索到的数据范围。 之后,我必须根据日期和类别合并值 现在我的报告格式是行是类别而日期是列。 因此,如果输入中有另一个具有相同日期和相同类别的值,则必须添加该值。
我的问题是如何检查报告中是否存在具有相同日期和类别的值,并且我不想使用循环,因为我已经在循环中,这样会使进程运行得非常慢。
答案 0 :(得分:0)
我认为没有一些循环就可以做到这一点。由于此操作在服务器端执行而无需调用电子表格,因此即使使用非常大的数据集也只需要很短的时间。
如果您的脚本已经很慢,那很可能是因为脚本的其他部分效率低下/延迟。我有一个脚本,它复制了一个电子表格并重命名它,只有那些操作需要5到5之间。 8秒
举个例子:
function test(){
var ss = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
var value = "agdsdfgsdfg" // This value is in cell BD1000
for(var i = 0; i < ss.length; i ++){
if(ss[i].indexOf(value)>=0){
var x = ss[i].indexOf(value) + 1;
break;
}
}
var y = i + 1
// var x & y are the row, cell coordinates of value in the data range
}
对数据集56列x 1000行执行的此操作在0.88秒内完成,搜索值位于范围的最后一个单元格中。
答案 1 :(得分:0)
您的报告听起来有点像数据透视表,其中行中的类别,列中的日期以及作为数据字段的SUM(值)。要使用脚本报告重现此问题,您可以使用Object
变量来映射密钥和&#34;值&#34; Object
:
这可能不是您的确切用例(它假设您需要从可能大量的馈送器数据生成新报告,但它应该演示如何使用嵌套Object
来简化/内化查找过程,包括测试未定义的值和强制执行矩形输出。
// Make an array of the data, to limit use of the slow spreadsheet interface.
var inputs = SpreadsheetApp.openById(<id>).getSheetByName(<dataSheetName>)
.getDataRange().getValues();
// The first row is probably column headers from the input sheet, and
// doesn't likely contain useful data that you want in your report.
var headers = inputs.splice(0, 1);
var report = {};
for(var row = 0; row < inputs.length; ++row) {
// Change these indexes (0, 1, 2) to the proper values.
// Also do any necessary formatting / validation, etc. for "category" and "date".
var category = inputs[row][0];
var date = inputs[row][1];
var value = inputs[row][2];
// If this category doesn't exist, default construct its report object.
// For each category, a nested object is used to store the date-value pair.
if(!report[category]) {
report[category] = {};
}
// Otherwise, if the date is not yet seen for the category, set
// the value. If it is seen, increment the stored value by the new value.
if(!report[category][date]) {
report[category][date] = value;
} else {
// Treat this as numeric addition, not string concatenation.
report[category][date] += value - 0;
}
}
// To print your report, you need a header you can index against.
var outputHeader = [];
for(var category in report) {
for(var date in category) {
outputHeader.push(date);
}
}
// Sort this header row. If the dates are strings that don't simply
// coerce to proper Date objects, you'll need to write your own sort() method.
// (You don't technically need to sort, but if you don't then the dates
// won't be "in order" when the report prints.)
outputHeader.sort();
// After sorting, add a row label for the header of sorted dates.
outputHeader.splice(0, 0, "Category / Date");
// Serialize the report object into an array[][];
var output = [outputHeader];
var totalColumns = outputHeader.length;
for(var category in report) {
// Initialize each row with the row label in the 0 index position.
var row = [category];
for(var date in category) {
var index = outputHeader.indexOf(date);
row[index] = category[date];
}
// Unless you are guaranteed that every category has a value for every date
// in the report, you need to ensure that the row has a value at each index.
// (This is a good idea anyway, to ensure that you have a rectangular array.)
var filled = Object.keys(row);
// We can start at 1 since we know that every row starts with its category.
for(var col = 1; col < totalColumns; ++col) {
if(filled.indexOf(String(col)) < 0) {
row[col] = "";
}
}
output.push(row);
}
SpreadsheetApp.openById(<id>).getSheetByName(<reportSheetName>)
.getRange(1, 1, output.length, output[0].length).setValues(output);