我在Google表格(有效范围)中选择了一系列单元格。我想迭代该范围内的每个单元格,并在末尾添加一个字符串。字符串始终相同,可以硬编码到函数中。
这似乎是一件非常简单的事情,但我现在已经把代码弄乱了一个小时,并且不能发生任何有用的事情,而且文档实际上没有帮助。
这就是我现在所拥有的。我不编码JS(我知道VBA,对所有有帮助的人......)。
function appendString() {
var range = SpreadsheetApp.getActiveSheet().getActiveRange();
for (var i = 0; i < range.length; i++) {
var currentValue = range[i].getValue();
var withString = currentValue + " string";
range[i].setValue(withString);
}
}
答案 0 :(得分:76)
您可以尝试这样的事情:
function appendString() {
var range = SpreadsheetApp.getActiveSheet().getActiveRange();
var numRows = range.getNumRows();
var numCols = range.getNumColumns();
for (var i = 1; i <= numRows; i++) {
for (var j = 1; j <= numCols; j++) {
var currentValue = range.getCell(i,j).getValue();
var withString = currentValue + " string";
range.getCell(i,j).setValue(withString);
}
}
}
答案 1 :(得分:19)
或者使用setValues()同时写入所有值。似乎也能更快地执行。
var range = SpreadsheetApp.getActiveSheet().getActiveRange();
var numRows = range.getNumRows();
var numCols = range.getNumColumns();
var writeValues = []
for (var i = 1; i <= numRows; i++) {
var row = []
for (var j = 1; j <= numCols; j++) {
var currentValue = range.getCell(i,j).getValue();
var withString = currentValue + " string";
row.push(withString)
}
writeValues.push(row)
}
range.setValues(writeValues)
答案 2 :(得分:3)
这里是Voy's post的更新,使用range.getValues()获取所有值并省略了临时数组。应该更快,因为在二维循环中省略了range.getCell().getValue()
。请注意,此代码段中的索引从0
开始。我也觉得这更具可读性。
var cells = range.getValues();
var numRows = range.getNumRows();
var numCols = range.getNumColumns();
for (var i = 0; i < numRows; i++) {
for (var j = 0; j < numCols; j++) {
cells[i][j] += " string";
}
}
range.setValues(cells);
答案 3 :(得分:2)
这是一个非常通用的函数,它迭代一个范围的值。它也可用于在其上执行cPanel
函数(这在您的情况下很有用)。如果您只想找到第一个元素,它也可以突破循环。
可以很容易地将其更改为接受实际的Range实例而不是值数组。
reduce
在你的情况下:
function range_reduce(rangeValues,fn,collection) {
collection = collection || [];
var debug_rr = "<<";
for(var rowIndex = 0, row=undefined; rowIndex<rangeValues.length && (row = rangeValues[rowIndex]); rowIndex++) {
for(var colIndex = 0, value=undefined; colIndex<row.length && (value = row[colIndex]); colIndex++) {
try {
collection = fn(collection, value, rowIndex, colIndex);
} catch (e) {
if(! e instanceof BreakException) {
throw e;
} else {
return collection;
}
}
}
}
return collection;
}
// this is a created, arbitrary function to serve as a way
// to break out of the reduce function. Your callback would
// `throw new BreakException()` and `rang_reduce` would stop
// there and not continue iterating over "rangeValues".
function BreakException();
答案 4 :(得分:2)
与旧式forEach
循环相比,我更喜欢Javascript 1.6 for
方法。您可以:
function appendString() {
var range = SpreadsheetApp.getActiveSheet().getActiveRange();
var values = range.getValues();
values.forEach(function(row, rowId) {
row.forEach(function(col, colId) {
values[rowId][colId] += " string";
});
});
range.setValues(values);
}
请注意,rowId和colId从零开始。而不是像老派解决方案那样基于基础的。 Javascript 1.6还提供了map
,值得考虑:
function appendString() {
var range = SpreadsheetApp.getActiveSheet().getActiveRange();
var values = range.getValues();
var modified = values.map(function (row) {
return row.map(function (col) {
return col + " string";
});
})
range.setValues(modified);
}
使用箭头功能可以改善代码,但google-apps-script尚不支持它们。
答案 5 :(得分:1)
google-sheets
您可以使用“查找并替换”轻松完成此操作。
选择范围
查找:
^(.*)$
替换:
$1AppendString
标记为使用正则表达式
单击全部替换
我在这里看不到使用脚本的任何优势,但是,如果必须的话,还可以通过工作表API发出Find Replace请求。
答案 6 :(得分:0)
Google 表格使用多维数组,因此为了让您的生活更轻松,您可以像这样将数组展平:
range.getValues().flat().forEach(function(item, i){
var currentValue = item[i].getValue();
var withString = currentValue + " string";
item[i].setValue(withString);
});
答案 7 :(得分:0)
这就是我要做的。它有点长,但我认为它非常实用且可重用。绝对实用。
这使用了 V8 引擎和 TypeScript
/*
Transforms the original "Array of Arrays"—
[
[a, b, c, d, e],
[a, b, c, d, e],
[...],
...,
]
into an "Array of Objects".
[
{timestamp: a, email: b, response_1: c, response_2: d, response_3: e},
{timestamp: a, email: b, response_1: c, response_2: d, response_3: e},
{...},
...,
]
*/
var original_values = SpreadsheetApp.getActiveSheet()
.getRange("A:E")
.getValues()
.map(
([
a, b, c, d, e,
// f, g, h, i, j,
// k, l, m, n, o,
// p, q, r, s, t,
// u, v, w, x, y,
// z, aa, ab, ac, ad,
// etc...
]) => {
return Object.create({
timestamp: a,
email: b,
response_1: c,
response_2: d,
response_3: e,
});
}
);
/*
Appends the string to some part of the Objects in our Array.
Since the Objects match the table structure (hopefully) we can be
pretty specific.
I tried to mock how a Google Form might collect responses.
*/
var appended_string = original_values.map(
(arg: { timestamp; email; response_1; response_2; response_3 }) => {
switch (typeof arg.response_1) {
case "string":
return Object.assign(arg, {
response_1: (arg.response_1 += " string"),
});
default:
return arg;
}
}
);
/*
Need to reshape the "Array of Objects" back into an "Array of Arrays".
Pretty simple compared to the original.
*/
var values_to_set = appended_string.map(
(arg: { timestamp; email; response_1; response_2; response_3 }) => {
return [
arg.timestamp,
arg.email,
arg.response_1,
arg.response_2,
arg.response_3,
];
}
);
/*
Here we'll take our finalized "values_to_set Array of Arrays" and
use it as the input for ".setValues()".
All Google Sheets data starts and ends as an "Array of Arrays" but...
It is significantly easier to work with as an "Array of Objects".
Rhetorical Question: Who wants to keep track of indexes?
*/
SpreadsheetApp.getActiveSheet().getRange("A:E").setValues(values_to_set);