google-apps-script - 如何提高创建 60 张纸的应用脚本的性能?
问题描述
我在 Google 表格中有一个使用该insertSheet
方法的简单应用脚本。它循环一个数组,从而创建 60 个工作表。然而,该脚本非常缓慢- 需要几分钟才能完成。
如何提高此方法的性能?或者是否有另一种方法以更高效的方式创建 60 张工作表 - 也许使用工作表 REST api?
语境
我有一个主表,它就像一个模板。当对这张表进行更改时,需要复制 60 次,因此用户不必一遍又一遍地进行更改。
当前代码
var listOfSheetsToCreate = ['1', '2', '3', ... '60'];
var ss = SpreadsheetApp.getActive();
var templateSheet = ss.getSheetByName('templateSheet');
listOfSheetsToCreate.forEach(function(sheetName) {
ss.insertSheet(sheetName, ss.getNumSheets(), {template: templateSheet});
});
解决方案
在得到评论和反馈后,我做了一些实验:
- 使用 app-scripts 复制 60 张纸大约需要80 秒。
- 使用 Sheets REST API 端点batchUpdate复制 60 张工作表大约需要10 秒- (删除 60 张工作表大约需要 1 秒)。使用请求体方法DuplicateSheetRequest
- 通过高级 Google 服务运行 batchUpdate。执行时间稍长 -大约 15 秒,但脚本要简单得多 - 感谢@Tanaike。这是我最终使用的解决方案 - 来解决我的问题。我可能还应该提到,运行脚本实际上会导致表格在浏览器中重新加载——我不知道为什么。但是当它重新加载时,所有的工作表都会被创建。
我仍然认为 10 秒很慢,所以如果您有任何改进此性能的想法,请告诉我。我提供了我的代码,以获取以下灵感。真的很期待一些现代的javascript...
表格 REST API Node.js 代码
export async function batchUpdate() {
// moved authentication to another method.
const authObect = await getAuthenticated();
// The batchupdate endpoint needs the sheet id of the template sheet, so that's why we need the following code
const ssInQuestion = await sheets.spreadsheets.get({
auth: authObect,
spreadsheetId: <spreadsheetId>
});
const masterSheet = ssInQuestion.data.sheets.find(v => v.properties.title.toLowerCase() === 'master');
if (!masterSheet) {
throw new Error(`Could not find master sheet in spreadsheet, will now exit!`);
}
// If we want to delete, the requests to the batch update should look like this:
// const requests: sheets_v4.Schema$Request[] = ssInQuestion.data.sheets
// .filter(v => v.properties.title.includes(' - test'))
// .map(v => v.properties.sheetId)
// .map(v => ({
// deleteSheet: {
// sheetId: v
// }
// } as sheets_v4.Schema$Request));
const requests: sheets_v4.Schema$Request[] = [];
for (let i = 0; i <= 60; i++) {
requests.push({
duplicateSheet: {
sourceSheetId: masterSheet.properties.sheetId,
newSheetName: `${i} - test`
}
})
}
const batchUpdateOptions: sheets_v4.Params$Resource$Spreadsheets$Batchupdate = {
spreadsheetId: <SpreadSheetIdInQuestion>,
auth: authObect,
requestBody: {
includeSpreadsheetInResponse: false,
requests
}
}
let start = new Date()
await sheets.spreadsheets.batchUpdate(batchUpdateOptions);
let end = +new Date() - +start;
console.info('Execution time: %dms', end)
}
高级 Google 服务应用脚本
// I ended up with something that looks like this:
function deleteListOfSheets(listOfSheets) {
if (listOfSheets.length == 0) {
return;
}
var ss = SpreadsheetApp.getActive();
var deleteRequests = listOfSheets.map(function(v) {
return {
deleteSheet: {
sheetId: v.getSheetId()
}
}
});
Sheets.Spreadsheets.batchUpdate({
includeSpreadsheetInResponse: false,
requests: deleteRequests
}, ss.getId())
}
function createListOfSheets(listOfSheetNames, templateSheetId) {
if (listOfSheetNames.length == 0) {
Logger.log("List of sheets to create had 0 length, will now exit")
return;
}
var ss = SpreadsheetApp.getActive();
// Create the array of 'create requests'
var createRequests = listOfSheetNames.map(function(v) {
return {
duplicateSheet: {
sourceSheetId: templateSheetId,
newSheetName: v
}
}
});
// Finally dispatch!
Sheets.Spreadsheets.batchUpdate({
includeSpreadsheetInResponse: false,
requests: createRequests
}, ss.getId())
}
推荐阅读
- sql - 如何在多表继承(table-per-type继承)上使用标识PK列
- .net - 将动态 DbContext 依赖注入到服务中
- ssl - SSL 慢。建立安全连接耗时过长
- jquery - 无法使用 Ajax 将数据插入数据库 - ASP.NET MVC
- java - 如何在 Java 中延迟一张图像在屏幕上显示?
- jquery - 如何确定 jQuery 中的活动选项卡
- javascript - Webpack 在我的包中包含所有 JSON 文件
- numpy - xt::where 用于 xtensor C++ 的示例用法
- javascript - 插入数据引导程序 3.3 后重定向到另一个选项卡
- proguard - 构建 App Bundle Proguard 错误