为范围内的每个名称创建一个单独的 sheet,并将每个名称下的值移动到每个 sheet
Create a separate sheet for every name in a range and move values under each name to each sheet
我有一个主列表,其中第 2 行有几十个名字,分布在一堆列 (A2:Z2) 中。每个名称下都有一个值和数据列表。
row 2
John
Sally
James
row 3
Value
Value
Value
row 4
Value
Value
Value
row 5
Value
Value
row 6
Value
Value
每个名字都应该创建成sheet.
这是用于为第 2 行中的每个名称创建 sheet 的脚本:
function generateSheetByName() {
const ss = SpreadsheetApp.getActive();
var mainSheet = ss.getSheetByName('Master List');
const sheetNames = mainSheet.getRange(2, 1, mainSheet.getLastRow(), 1).getValues().flat();
sheetNames.forEach(n => ss.insertSheet(n));
}
我希望此脚本不仅为每个名称创建一个 sheet,而且还将每个名称下的所有值一直保留到相应列的最后一行。
例如John 在 A2 中,A3:A 是应该传递给创建的 sheet 的值。 Sally 是 B2,B3:B 是应该继承的值。
在 John 的 sheet 中 - “John”是 A1 中的 header,列值位于 A2:A
对于每个 sheet 我还想手动添加其他值。例如,如果创建了“John”sheet,并在 A2:A22 中添加了 20 个值,我希望脚本在 B2:B22 中添加复选框。或者总是在 B1 中添加公式,例如“=counta(a2:a)”或其他内容。
我怎样才能用高效的循环来做到这一点?请注意,这可能会创建 50 sheets 并在每个 sheet
中携带 10-50 个值
示例图片:
主列表:
每个名称都会创建一个 sheet,看起来像这样
约翰的 sheet
我相信你的目标如下。
- 您想使用 Google Apps 脚本实现从第一张图片到第二张图片。
- 将值放入创建的 sheet 后,您想要将复选框插入列“B”,并将公式放入单元格“B1”。
- 您想降低脚本的处理成本。
在这种情况下,下面的示例脚本怎么样?
示例脚本:
在这个示例脚本中,为了减少脚本的处理成本,我使用了Sheets API。使用Sheets API 时,工艺成本可以降低一些。所以,在你使用这个脚本之前,please enable Sheets API at Advanced Google services.
function generateSheetByName() {
// 1. Retrieve values from "Master List" sheet.
const ss = SpreadsheetApp.getActive();
const mainSheet = ss.getSheetByName('Master List');
const values = mainSheet.getRange(2, 1, mainSheet.getLastRow(), mainSheet.getLastColumn()).getValues();
// 2. Transpose the values without the empty cells.
const t = values[0].map((_, c) => values.reduce((a, r) => {
if (r[c]) a.push(r[c]);
return a;
}, []));
// 3. Create a request body for using Sheets API.
const requests = t.flatMap((v, i) => {
const sheetId = 123456 + i;
const ar = [{ addSheet: { properties: { sheetId, title: v[0] } } }];
const temp = {
updateCells: {
range: { sheetId, startRowIndex: 0, startColumnIndex: 0 },
fields: "userEnteredValue,dataValidation"
},
};
temp.updateCells.rows = v.map((e, j) => {
if (j == 0) {
return { values: [{ userEnteredValue: { stringValue: e } }, { userEnteredValue: { formulaValue: "=counta(a2:a)" } }] }
}
const obj = typeof (e) == "string" || e instanceof String ? { stringValue: e } : { numberValue: e }
return { values: [{ userEnteredValue: obj }, { dataValidation: { condition: { type: "BOOLEAN" } } }] }
});
return ar.concat(temp);
});
// 4. Request to the Sheets API using the created request body.
Sheets.Spreadsheets.batchUpdate({requests}, ss.getId());
}
注:
- 在这个示例脚本中,我使用了您的示例输入和输出情况。所以当这些结构与您的实际情况不同时,脚本可能无法使用。请注意这一点。
参考:
我有一个主列表,其中第 2 行有几十个名字,分布在一堆列 (A2:Z2) 中。每个名称下都有一个值和数据列表。
row 2 | John | Sally | James |
---|---|---|---|
row 3 | Value | Value | Value |
row 4 | Value | Value | Value |
row 5 | Value | Value | |
row 6 | Value | Value |
每个名字都应该创建成sheet.
这是用于为第 2 行中的每个名称创建 sheet 的脚本:
function generateSheetByName() {
const ss = SpreadsheetApp.getActive();
var mainSheet = ss.getSheetByName('Master List');
const sheetNames = mainSheet.getRange(2, 1, mainSheet.getLastRow(), 1).getValues().flat();
sheetNames.forEach(n => ss.insertSheet(n));
}
我希望此脚本不仅为每个名称创建一个 sheet,而且还将每个名称下的所有值一直保留到相应列的最后一行。
例如John 在 A2 中,A3:A 是应该传递给创建的 sheet 的值。 Sally 是 B2,B3:B 是应该继承的值。
在 John 的 sheet 中 - “John”是 A1 中的 header,列值位于 A2:A
对于每个 sheet 我还想手动添加其他值。例如,如果创建了“John”sheet,并在 A2:A22 中添加了 20 个值,我希望脚本在 B2:B22 中添加复选框。或者总是在 B1 中添加公式,例如“=counta(a2:a)”或其他内容。
我怎样才能用高效的循环来做到这一点?请注意,这可能会创建 50 sheets 并在每个 sheet
中携带 10-50 个值示例图片:
主列表:
每个名称都会创建一个 sheet,看起来像这样
约翰的 sheet
我相信你的目标如下。
- 您想使用 Google Apps 脚本实现从第一张图片到第二张图片。
- 将值放入创建的 sheet 后,您想要将复选框插入列“B”,并将公式放入单元格“B1”。
- 您想降低脚本的处理成本。
在这种情况下,下面的示例脚本怎么样?
示例脚本:
在这个示例脚本中,为了减少脚本的处理成本,我使用了Sheets API。使用Sheets API 时,工艺成本可以降低一些。所以,在你使用这个脚本之前,please enable Sheets API at Advanced Google services.
function generateSheetByName() {
// 1. Retrieve values from "Master List" sheet.
const ss = SpreadsheetApp.getActive();
const mainSheet = ss.getSheetByName('Master List');
const values = mainSheet.getRange(2, 1, mainSheet.getLastRow(), mainSheet.getLastColumn()).getValues();
// 2. Transpose the values without the empty cells.
const t = values[0].map((_, c) => values.reduce((a, r) => {
if (r[c]) a.push(r[c]);
return a;
}, []));
// 3. Create a request body for using Sheets API.
const requests = t.flatMap((v, i) => {
const sheetId = 123456 + i;
const ar = [{ addSheet: { properties: { sheetId, title: v[0] } } }];
const temp = {
updateCells: {
range: { sheetId, startRowIndex: 0, startColumnIndex: 0 },
fields: "userEnteredValue,dataValidation"
},
};
temp.updateCells.rows = v.map((e, j) => {
if (j == 0) {
return { values: [{ userEnteredValue: { stringValue: e } }, { userEnteredValue: { formulaValue: "=counta(a2:a)" } }] }
}
const obj = typeof (e) == "string" || e instanceof String ? { stringValue: e } : { numberValue: e }
return { values: [{ userEnteredValue: obj }, { dataValidation: { condition: { type: "BOOLEAN" } } }] }
});
return ar.concat(temp);
});
// 4. Request to the Sheets API using the created request body.
Sheets.Spreadsheets.batchUpdate({requests}, ss.getId());
}
注:
- 在这个示例脚本中,我使用了您的示例输入和输出情况。所以当这些结构与您的实际情况不同时,脚本可能无法使用。请注意这一点。