问题
根据我收到的错误电子邮件,我的Google脚本触发器未运行,因为它“占用大量CPU时间”。如何优化脚本以减少CPU时间?
我已经将sortGsheetFiles
分成了不同的触发器,但是仍然要花费很多时间。它曾经与importXLSXtoGsheet
函数结合使用。
脚本说明
我有52个文件夹,每个文件夹包含一个电子表格文件。
每个文件夹与不同的同事共享。
白天,人们会对文件进行更改。
gsheetFolder
)中,并使用功能collectAndExportXLS
转换为XLSX文件。这些文件在晚上(使用批处理脚本和驱动器同步)复制到本地服务器,这将更新文件中的其他信息,然后复制回到importXLSXfolder
。
importXLSXtoGsheet
函数运行并将importXLSXfolder
文件夹中的所有XLSX文件转换为gsheetFolder
中的Gsheet文件。sortGsheetFiles
之后,将所有Gsheet文件排序并移动到52个文件夹之一中(使用当前电子表格中的数组列表)。其他操作包括使用deleteFolder
功能清理文件夹。
触发器
importXLSXtoGsheet
-每天-早上6点至早上7点之间
sortGsheetFiles
-每天-上午7点至8点之间
collectAndExportXLS
-每天-晚上10点至晚上11点之间
脚本
var gsheetFolder = 'xxx';
var XLSXfolder = 'xxxxx';
var importXLSXfolder = 'xxxxx';
function checkEmptyFolder() {
var folders = DocsList.getAllFolders()
for(n=0;n<folders.length;++n){
if(folders[n].getFiles().length==0 && folders[n].getFolders().length==0){
folders[n].setTrashed(true)
Logger.log(folders[n].getName())
}
}
}
function importXLSXtoGsheet(){
// ========= convert all XLS files in XLS folder to GSheet and put in the general gsheet folder - after that sort in gsheet filiaal folders =========
// cleanup exportXLS folder first
deleteFolder(XLSXfolder);
var files = DriveApp.getFolderById(importXLSXfolder).searchFiles('title contains ".xlsx"');
while(files.hasNext()) {
var xFile = files.next();
var name = xFile.getName();
if (name.indexOf('.xlsx')) {
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = {
title : name + ('.xlsx'),
key : ID,
parents: [{"id": gsheetFolder}]
}
file = Drive.Files.insert(newFile, xBlob, {convert: true});
}
}
deleteFolder(importXLSXfolder);
}
function sortGsheetFiles() {
// ========= sort Gsheet folder and move to corresponding filiaal folders =========
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var myArrayFileName = sheet.getRange("A2:A53").getValues();
var myArrayFolderId = sheet.getRange("B2:B53").getValues();
var a = myArrayFileName.join().split(',').filter(Boolean);
var b = myArrayFolderId.join().split(',').filter(Boolean);
var folderId = gsheetFolder;
// Log the name of every file in the folder.
var files = DriveApp.getFolderById(folderId).getFiles();
while (files.hasNext()) {
var file = files.next();
for (var i in a) {
var id = file.getId();
if (file.getName() == a[i]) {
moveFiles(id, b[i]); // Match found and move to corresponding folder
}
}
}
deleteFolder(importXLSXfolder);
}
function collectAndExportXLS() {
// ========= collect all Gsheet files, copy to gsheet folder and convert to xlsx and move to xlsx folder =========
// cleanup gsheet folder
deleteFolder(gsheetFolder);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var myArrayFileName = sheet.getRange("A2:A53").getValues();
var myArrayFolderId = sheet.getRange("B2:B53").getValues();
var a = myArrayFileName.join().split(',').filter(Boolean);
var b = myArrayFolderId.join().split(',').filter(Boolean);
var folderId = gsheetFolder;
for (var i in b) {
var files = DriveApp.getFolderById(b[i]).getFiles();
while (files.hasNext()) {
var file = files.next();
var id = file.getId();
moveFiles(id , folderId);
}
}
ConvertBackToXLS()
deleteFolder(gsheetFolder);
}
function moveFiles(sourceFileId, targetFolderId) {
var file = DriveApp.getFileById(sourceFileId);
file.getParents().next().removeFile(file);
DriveApp.getFolderById(targetFolderId).addFile(file);
}
function deleteFolder(folder) {
//delete files in a folder without sending to trash!
var eachFile, idToDLET, myFolder, rtrnFromDLET, thisFile, files;
files = DriveApp.getFolderById(folder).getFiles();
while (files.hasNext()) {//If there is another element in the iterator
eachFile = files.next();
idToDLET = eachFile.getId();
//Logger.log('idToDLET: ' + idToDLET);
rtrnFromDLET = Drive.Files.remove(idToDLET);
};
Logger.log('folder deleted');
}
function ConvertBackToXLS() {
// Log the name of every file in the folder.
var files = DriveApp.getFolderById(gsheetFolder).getFiles();
var dir = DriveApp.getFolderById(XLSXfolder);
while (files.hasNext()) {
try {
var file = files.next();
var ss = SpreadsheetApp.openById(file.getId());
Logger.log(file.getId());
var url = "https://docs.google.com/feeds/download/spreadsheets/Export?key=" + file.getId() + "&exportFormat=xlsx";
var params = {
method : "get",
headers : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
};
var blob = UrlFetchApp.fetch(url, params).getBlob();
blob.setName(ss.getName());
var newfile = dir.createFile(blob);
} catch (f) {
Logger.log(f.toString());
}
}
}
答案 0 :(得分:1)
此修改如何?请认为这只是几个答案之一。
重要的一点是,请先根据实际情况测试脚本,然后再运行实际情况。
collectAndExportXLS()
:在此函数名称之前,我没有修改collectAndExportXLS()
。因为我认为您可能在其他脚本或触发器上使用了此函数名称。
gsheetFolder
中的所有文件。sample.xlsx
。XLSXfolder
中。XLSXfolder
中的XLSX文件由其他脚本放入importXLSXfolder
中。 importXLSXtoGsheet()
:在此函数名称之前,我没有修改collectAndExportXLS()
。因为我认为您可能在其他脚本或触发器上使用了此函数名称。
XLSXfolder
中的所有文件。importXLSXfolder
中的所有XLSX文件转换为Google Spreadsheet。
sample.xlsx
。gsheetFolder
中。importXLSXfolder
中的所有文件。 sortGsheetFiles()
gsheetFolder
中的Google Spreadsheets移动到从工作表“ B2:B53”中检索到的每个文件夹ID,该ID在活动Spreadsheet中为第一个索引。
importXLSXfolder
中的所有文件。我了解到,从您的问题来看,活动电子表格的“ A2:A53”列的文件名与Google电子表格的文件名相同,后者已放入“ B2”列的文件夹ID的文件夹中: B53”。
我理解如上。如果我的理解是正确的,那么该修改如何?在我的修改中,我使用了Drive API的Batch请求和类型为multipart/form-data
的UrlFetchApp的fetchAll方法。批处理请求和fetchAll方法可以与异步过程一起使用。因此,我认为您的流程成本可能会降低。
为了使用这些方法,我使用了2个GAS库。在运行脚本之前,请为您的脚本安装这两个库。您可以按照以下步骤查看如何安装该库。
multipart/form-data
. collectAndExportXLS()
importXLSXtoGsheet()
sortGsheetFiles()
deleteFolder()
当以上几点反映到您的脚本中时,它如下所示。
安装2个库后,请运行以下脚本。
var gsheetFolder = '###';
var XLSXfolder = '###';
var importXLSXfolder = '###';
// Modified
function deleteFolder(folderId) {
var url = "https://www.googleapis.com/drive/v3/files?q='" + folderId + "'+in+parents+and+trashed%3Dfalse&fields=files%2Fid&access_token=" + ScriptApp.getOAuthToken();
var res = UrlFetchApp.fetch(url);
var obj = JSON.parse(res.getContentText());
var reqs = obj.files.map(function(e) {return {method: "DELETE", endpoint: "https://www.googleapis.com/drive/v3/files/" + e.id}});
var requests = {batchPath: "batch/drive/v3", requests: reqs};
if (requests.requests.length > 0) BatchRequest.Do(requests);
}
// Added
function deleteFiles(files) {
var reqs = files.map(function(e) {return {method: "DELETE", endpoint: "https://www.googleapis.com/drive/v3/files/" + e.id}});
var requests = {batchPath: "batch/drive/v3", requests: reqs};
if (requests.requests.length > 0) BatchRequest.Do(requests);
}
// Added
function getValuesFromSpreadsheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
return sheet.getRange("A2:B53").getValues();
}
// Modified
function sortGsheetFiles() {
var url = "https://www.googleapis.com/drive/v3/files?q='" + gsheetFolder + "'+in+parents+and+mimeType%3D'" + MimeType.GOOGLE_SHEETS + "'+and+trashed%3Dfalse&fields=files(id%2Cname)&access_token=" + ScriptApp.getOAuthToken();
var res = UrlFetchApp.fetch(url);
var obj = JSON.parse(res.getContentText());
var values = getValuesFromSpreadsheet();
var reqs = values.reduce(function(ar, e) {
for (var i = 0; i < obj.files.length; i++) {
if (obj.files[i].name == e[0]) {
ar.push({
method: "PATCH",
endpoint: "https://www.googleapis.com/drive/v3/files/" + obj.files[i].id + "?addParents=" + e[1] + "&removeParents=" + gsheetFolder,
});
break;
}
}
return ar;
}, []);
var requests = {batchPath: "batch/drive/v3", requests: reqs};
if (requests.requests.length > 0) BatchRequest.Do(requests);
deleteFolder(importXLSXfolder);
}
// Modified
function importXLSXtoGsheet(){
deleteFolder(XLSXfolder);
var url = "https://www.googleapis.com/drive/v3/files?q='" + importXLSXfolder + "'+in+parents+and+mimeType%3D'" + MimeType.MICROSOFT_EXCEL + "'+and+trashed%3Dfalse&fields=files(id%2Cname)&access_token=" + ScriptApp.getOAuthToken();
var res = UrlFetchApp.fetch(url);
var obj = JSON.parse(res.getContentText());
var reqs = obj.files.map(function(e) {return {
method: "POST",
endpoint: "https://www.googleapis.com/drive/v3/files/" + e.id + "/copy",
requestBody: {mimeType: MimeType.GOOGLE_SHEETS, name: e.name + ".xlsx", parents: [gsheetFolder]},
}
});
var requests = {batchPath: "batch/drive/v3", requests: reqs};
if (requests.requests.length > 0) BatchRequest.Do(requests);
deleteFolder(importXLSXfolder);
}
// Modified
function ConvertBackToXLS(fileList) {
var token = ScriptApp.getOAuthToken();
var reqs1 = fileList.map(function(e) {return {
method: "GET",
url: "https://docs.google.com/spreadsheets/export?id=" + e.id + "&exportFormat=xlsx&access_token=" + token,
}
});
var res = UrlFetchApp.fetchAll(reqs1);
var reqs2 = res.map(function(e, i) {
var metadata = {name: fileList[i].name, parents: [XLSXfolder]};
var form = FetchApp.createFormData(); // Create form data
form.append("metadata", Utilities.newBlob(JSON.stringify(metadata), "application/json"));
form.append("file", e.getBlob());
var url = "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart";
return {url: url, method: "POST", headers: {Authorization: "Bearer " + token}, body: form};
});
FetchApp.fetchAll(reqs2);
}
// Modified
function collectAndExportXLS() {
deleteFolder(gsheetFolder);
var values = getValuesFromSpreadsheet();
var reqs1 = values.reduce(function(ar, e) {
if (e[0] && e[1]) {
ar.push({
method: "GET",
endpoint: "https://www.googleapis.com/drive/v3/files?q='" + e[1] + "'+in+parents+and+trashed%3Dfalse&fields=files(id%2Cname)",
});
}
return ar;
}, []);
var resForReq1 = BatchRequest.Do({batchPath: "batch/drive/v3", requests: reqs1});
var temp = resForReq1.getContentText().split("--batch");
var files = temp.slice(1, temp.length - 1).map(function(e) {return JSON.parse(e.match(/{[\S\s]+}/g)[0])});
var fileList = files.reduce(function(ar, e) {return ar.concat(e.files.map(function(f) {return f}))}, []);
ConvertBackToXLS(fileList);
deleteFiles(fileList);
}