I create a PDF and then send its information to my website so that this PDF is converted to an image file and published:
SpreadsheetApp.flush();
var theurl = 'https://docs.google.com/a/mydomain.org/spreadsheets/d/' +
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +
'/export?format=pdf' +
'&size=0' +
'&portrait=true' +
'&fitw=true' +
'&top_margin=0' +
'&bottom_margin=0' +
'&left_margin=0' +
'&right_margin=0' +
'&sheetnames=false&printtitle=false' +
'&pagenum=false' +
'&gridlines=false' +
'&fzr=FALSE' +
'&gid=' +
'aaaaaaaaaaa';
var token = ScriptApp.getOAuthToken();
var docurl = UrlFetchApp.fetch(theurl, { headers: { 'Authorization': 'Bearer ' + token } });
var pdfBlob = docurl.getBlob();
//...get token and Blob (do not create the file);
var fileName = ss.getSheetByName("General").getRange("H2").getValue();
//Access or create the 'Archives' folder;
var folder;
var folders = DriveApp.getFoldersByName("Archives");
if(folders.hasNext()) {
folder = folders.next();
}else {
folder = DriveApp.createFolder("Archives");
}
//Remove duplicate file with the same name;
var existing = folder.getFilesByName(fileName);
if(existing.hasNext()) {
var duplicate = existing.next();
if (duplicate.getOwner().getEmail() == Session.getActiveUser().getEmail()) {
var durl = 'https://www.googleapis.com/drive/v3/files/'+duplicate.getId();
var dres = UrlFetchApp.fetch(durl,{
method: 'delete',
muteHttpExceptions: true,
headers: {'Authorization': 'Bearer '+token}
});
var status = dres.getResponseCode();
if (status >=400) {
} else if (status == 204) {
folder.createFile(pdfBlob.setName(fileName));
}
}
} else {
folder.createFile(pdfBlob.setName(fileName));
}
Utilities.sleep(5000);
createPostByFileName(folder, fileName);
function createPostByFileName(folder, fileName) {
var fileIterator = folder.getFilesByName(fileName);
if(fileIterator.hasNext()) {
var file = fileIterator.next()
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW)
name = file.getName();
league = name.split(' ')[0];
title = name.split(league)[1].split('.pdf')[0];
link = file.getUrl();
shareable = link.split('/view')[0];
id = file.getId();
var data = {
'api_league_name': league,
'title': title,
'google_drive_id': id,
'google_drive_url': shareable,
'pass': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
};
var options = {
'method' : 'post',
'contentType': 'application/json',
'payload' : JSON.stringify(data)
};
UrlFetchApp.fetch('https://www.xxx.com.br/api/posts', options);
}
}
For some reason I am forced to put Utilities.sleep(5000); before calling the function that sends the PDF data to my website, because if I don't, when the website tries to convert the PDF to an image, an problem happens as if the PDF is not yet available in the folder or it generates a big slowdown until can access the file.
Obviously putting this sleep is not a professional way to solve the case, because then I can't even know why this happens.
Anyone who has had this experience, can tell me how I should proceed in a professional way?
From the discussions in the comment, when Drive API is used for your script, it becomes as follows. Before you use this, please enable Drive API at Advanced Google services.
Modified script:
function sample() {
const createFile = (filename, blob, folderId) => Drive.Files.insert({ title: filename, parents: [{ id: folderId }] }, blob);
SpreadsheetApp.flush();
var theurl = 'https://docs.google.com/a/mydomain.org/spreadsheets/d/' +
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +
'/export?format=pdf' +
'&size=0' +
'&portrait=true' +
'&fitw=true' +
'&top_margin=0' +
'&bottom_margin=0' +
'&left_margin=0' +
'&right_margin=0' +
'&sheetnames=false&printtitle=false' +
'&pagenum=false' +
'&gridlines=false' +
'&fzr=FALSE' +
'&gid=' +
'aaaaaaaaaaa';
var token = ScriptApp.getOAuthToken();
var docurl = UrlFetchApp.fetch(theurl, { headers: { 'Authorization': 'Bearer ' + token } });
var pdfBlob = docurl.getBlob();
var fileName = ss.getSheetByName("General").getRange("H2").getValue();
var folder;
var folders = DriveApp.getFoldersByName("Archives");
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder("Archives");
}
var existing = folder.getFilesByName(fileName);
var pdfFileId = "";
if (existing.hasNext()) {
var duplicate = existing.next();
if (duplicate.getOwner().getEmail() == Session.getActiveUser().getEmail()) {
var durl = 'https://www.googleapis.com/drive/v3/files/' + duplicate.getId();
var dres = UrlFetchApp.fetch(durl, {
method: 'delete',
muteHttpExceptions: true,
headers: { 'Authorization': 'Bearer ' + token }
});
var status = dres.getResponseCode();
if (status >= 400) {
} else if (status == 204) {
var obj = createFile(fileName, pdfBlob, folder.getId());
pdfFileId = obj.id;
}
}
} else {
var obj = createFile(fileName, pdfBlob, folder.getId());
pdfFileId = obj.id;
}
// Utilities.sleep(5000);
Drive.Permissions.insert({ role: "reader", type: "anyone" }, pdfFileId);
league = fileName.split(' ')[0];
title = fileName.split(league)[1].split('.pdf')[0];
shareable = "https://drive.google.com/file/d/" + pdfFileId;
id = pdfFileId;
var data = {
'api_league_name': league,
'title': title,
'google_drive_id': id,
'google_drive_url': shareable,
'pass': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
};
var options = {
'method': 'post',
'contentType': 'application/json',
'payload': JSON.stringify(data)
};
UrlFetchApp.fetch('https://www.xxx.com.br/api/posts', options);
}
Note:
This is a sample script for testing whether Utilities.sleep(5000) can be removed.
Related
I used a script to backup all my google docs, when running the function it works correctly and makes a copy. But when setting up a time-driven trigger it doesn't run but says that it does.
Project Trigger
I checked to make sure the project's time zone was correct and tried to run it at different times, but it still doesn't run.
The script below:
var BACKUP_FOLDER_ID = '16SGkgNCPeNn9DgB9RmhLAv-z5C_kCbCM';
var NATIVE_MIME_TYPES = {};
NATIVE_MIME_TYPES[MimeType.GOOGLE_DOCS] = MimeType.MICROSOFT_WORD;
NATIVE_MIME_TYPES[MimeType.GOOGLE_SHEETS] = MimeType.MICROSOFT_EXCEL;
NATIVE_MIME_TYPES[MimeType.GOOGLE_SLIDES] = MimeType.MICROSOFT_POWERPOINT;
var NATIVE_EXTENSIONS = {};
NATIVE_EXTENSIONS[MimeType.GOOGLE_DOCS] = '.docx';
NATIVE_EXTENSIONS[MimeType.GOOGLE_SHEETS] = '.xlsx';
NATIVE_EXTENSIONS[MimeType.GOOGLE_SLIDES] = '.pptx';
var BACKUP_MIME_TYPES = Object.keys(NATIVE_MIME_TYPES);
function backupAll() {
const backupFolder = DriveApp.getFolderById(BACKUP_FOLDER_ID);
BACKUP_MIME_TYPES.forEach(function(mimeType) {
var files = DriveApp.getFilesByType(mimeType);
while (files.hasNext()) {
var file = files.next();
if (file.getOwner() && file.getOwner().getEmail() == Session.getActiveUser().getEmail()) {
backup(file, backupFolder);
}
}
});
}
function backup(file, folder) {
var targetName = file.getName() + ' ' + file.getId();
var lastUpdated = file.getLastUpdated();
var pdf = getPdfBlob(file);
var native = getNativeBlob(file);
var zip = Utilities.zip([pdf, native], targetName + '.zip');
createOrUpdateFileForBlob(zip, folder, lastUpdated);
}
function createOrUpdateFileForBlob(blob, folder, ifOlderThan) {
var existingFiles = folder.getFilesByName(blob.getName());
if (existingFiles.hasNext()) {
var file = existingFiles.next();
if (file.getLastUpdated() < ifOlderThan) {
updateFile(file, blob);
}
} else {
folder.createFile(blob);
}
}
function updateFile(file, blob) {
const url = 'https://www.googleapis.com/upload/drive/v2/files/' + file.getId() + '?uploadType=media';
const params = {
method: 'put',
headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() },
payload: blob
};
var response = UrlFetchApp.fetch(url, params);
if (response.getResponseCode() < 200 || response.getResponseCode() > 299) {
throw 'Failed to update file named ' + file.getName();
}
}
function getPdfBlob(file) {
var blob = file.getAs('application/pdf');
return blob;
}
function getNativeBlob(file) {
const nativeMimeType = NATIVE_MIME_TYPES[file.getMimeType()];
const extension = NATIVE_EXTENSIONS[file.getMimeType()];
const url = 'https://www.googleapis.com/drive/v2/files/' + file.getId() + '/export?mimeType=' + nativeMimeType;
const params = {
method: 'get',
headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() }
};
const blob = UrlFetchApp.fetch(url, params).getBlob();
blob.setName(file.getName() + extension);
return blob;
}
It was actually a Google Sheets project, so I'm learning on the fly as best as I can, but I can't even format this code below correctly - ugh!)
The error I am receiving is this:
TypeError: Cannot read property 'getResponseCode' of undefined
doGet_Appraisal # Appraisal_Email.gs:64
And the code is below:
//1. Performing to generate the Payslip getting sheet contents
function doGet_Appraisal(range,shTabName) {
var blob,exportUrl,name,options,response,sheetTabId,ss,ssID,url_base,email,subject;
var folderId ="1o9WImzeKdzsek7DfZWD_qzFsI9yLoplz";
var milliseconds = 2000;
range = range ? range : "B1:R44";
ss = SpreadsheetApp.openById("sheet_ID");
shTabName = "Appraisal Payslip Template";
ssID = ss.getId();
sh = ss.getSheetByName(shTabName);
const body = "Dear Employee" + "\n\n" + "<p>" + "<b> Payslip for the month of January is Available </b>" + "</p>";
var htmlText = body.replace(/\n/g,'\n<br>');
var bioCode = sh.getRange('F12');
const values = [...new Set(bioCode.getDataValidation().getCriteriaValues()[0].getValues().flat())];
var first = values[0];
var number = values.length - 1;
bioCode.setValue(first);
//2. Looping the Emp_ID till null
for(i = 0;i < number;i++)
{
if (sh.getRange('F12').getValue().length > 0) {
var person = sh.getRange('F12').getValue();
sheetTabId = sh.getSheetId();
//3. Getting the Corresponfing EMail based on Emp_ID
email = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Appraisal Payslip Template').getRange('N12').getValue().toString();
Utilities.sleep(milliseconds);
url_base = ss.getUrl().replace(/edit$/,'');
name = sh.getRange("S1").getValue();
name = name + ""
subject = `${name}`;
Logger.log('email: ' + email)
Logger.log('body: ' + body)
//4. Exporting the sheet as PDF (contents)
exportUrl = url_base + 'export?exportFormat=pdf&format=pdf' +
'&gid=' + sheetTabId + '&id=' + ssID +
'&range=' + range +
'&size=A4' +
'&portrait=true' +
'&fitw=true' +
'&sheetnames=false&printtitle=false&pagenumbers=true' +
'&gridlines=false' +
'&fzr=false';
//5. Authorizing email setup OAuthToken
options = {
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken(),
}
}
//6. Getting the sheet url and export as PDF
options.muteHttpExceptions = true;
response = UrlFetchApp.fetch(exportUrl, options);
//var response2 = UrlFetchApp.fetch(exportUrl, options).getBlob();
Logger.log(response.getResponseCode())
const nextValue = values[values.indexOf(bioCode.getValue()) + 1] || values[0];
bioCode.setValue(nextValue);
}
else {const nextValue = values[values.indexOf(bioCode.getValue()) + 1] ||
values[0];
bioCode.setValue(nextValue);
}
//7. If response code is not 200 return error exporting PDF
if (response.getResponseCode() !== 200) {
console.log("Error exporting Sheet to PDF! Response Code: " + response.getResponseCode());
return;
}
blob = response.getBlob();
blob.setName(name + '.pdf')
GmailApp.sendEmail(email, subject, htmlText,
{
htmlBody: htmlText,
attachments: [{
fileName: `${name}` + ".pdf",
//content: response2.getBytes(),
mimeType: "application/pdf"
}]
});
//pdfFile = DriveApp.getFolderById(folderId).createFile(blob);
}
}
This was worked recently but now throws error
TypeError: Cannot read property 'getResponseCode' of undefined
doGet_Appraisal # Appraisal_Email.gs:64
I'm trying to sent a print job to one of my printers in Cloud Print.
The information I would like to print is the current range the user is selecting inside a Spreadsheet.
For this I have used this guide:
https://www.labnol.org/code/20061-google-cloud-print-with-apps-script in order to set up the printer with GAS.
Step 1: Get the information you want to print
Source: How to Print sheet/range using .gs script in Google Sheets?
Explanation: carlesgg97's solution opens a modal window that will show our spreadsheet range exported as a PDF. From that point the user would need to manually print the job.
However, the information is sent to the Html via script.
Code adapted:
var PRINT_OPTIONS = {
'size': 7, // paper size. 0=letter, 1=tabloid, 2=Legal, 3=statement, 4=executive, 5=folio, 6=A3, 7=A4, 8=A5, 9=B4, 10=B
'fzr': false, // repeat row headers
'portrait': false, // false=landscape
'fitw': true, // fit window or actual size
'gridlines': false, // show gridlines
'printtitle': false,
'sheetnames': false,
'pagenum': 'UNDEFINED', // CENTER = show page numbers / UNDEFINED = do not show
'attachment': false
}
var PDF_OPTS = objectToQueryString(PRINT_OPTIONS);
function printSelectedRange() {
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet(); //Our Spreadsheet
var sheet = ss.getActiveSheet(); //Our Active Sheet
var range = sheet.getActiveRange(); // Our Active Range
var gid = sheet.getSheetId();
var printRange = objectToQueryString({
'c1': range.getColumn() - 1,
'r1': range.getRow() - 1,
'c2': range.getColumn() + range.getWidth() - 1,
'r2': range.getRow() + range.getHeight() - 1
});
//Here is variable that we will send to the htmlTemplate
//We will build the HtmlTemplate using this url
var url = ss.getUrl().replace(/edit$/, '') + 'export?format=pdf' +
PDF_OPTS + printRange + "&gid=" + gid;
var htmlTemplate = HtmlService.createTemplateFromFile('js');
//Here I'm wrongly trying to get the content from the Html.
//What I'll get is the content of js.html and not the info from the url
var pdf_html = htmlTemplate.evaluate().getContent();
//The blob needs to be build using an object.
//However I don't know how to access the pdf I'm exporting inside the url var
var blob = Utilities.newBlob(pdf_html, MimeType.HTML, 'temp').getAs(MimeType.PDF);
//random printer ID
var printerID = 'b71f9cd2-3e3e-qweq-12asd-aogt5keoqoa2';
printGoogleDocument(blob, printerID, 1);
}
function objectToQueryString(obj) {
return Object.keys(obj).map(function(key) {
return Utilities.formatString('&%s=%s', key, obj[key]);
}).join('');
}
js.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<script>
window.open('<?=url?>', '_blank', 'width=800, height=600');
google.script.host.close();
</script>
</body>
</html>
Step 2: Print the Job
function printGoogleDocument(docBlob, printerID, docName) {
var ticket = {
version: "1.0",
print: {
color: {
type: "STANDARD_COLOR",
vendor_id: "Color"
},
duplex: {
type: "NO_DUPLEX"
}
}
};
var payload = {
"printerid" : printerID,
"title" : docName,
"content" : docBlob,
"contentType": "application/pdf",
"ticket" : JSON.stringify(ticket)
};
var response = UrlFetchApp.fetch('https://www.google.com/cloudprint/submit', {
method: "POST",
payload: payload,
headers: {
Authorization: 'Bearer ' + getCloudPrintService().getAccessToken()
},
"muteHttpExceptions": true
});
response = JSON.parse(response);
if (response.success) {
Logger.log("%s", response.message);
} else {
Logger.log("Error Code: %s %s", response.errorCode, response.message);
}
}
I believe that what I need to modify is how the HtmlTemplate is build so that I can create a correct BLOB and send it to the printer.
EDIT
Applying Tanaike recommendation it works just fine when I call the function directly from the Script Editor.
Although in the scenario where we want to call this function printSelectedRange() using another function I got the following error:
Exception: Request failed for https://docs.google.com returned code 500.
Truncated server response: <!DOCTYPE html><html lang="en"><head>
<metaname="description" content="Web word processing, presentations and
spreadsheets"><meta name="viewport" c... (use muteHttpExceptions option to`
examine full response)`
The error points out to this line of code
var blob = UrlFetchApp.fetch(url, {headers: {authorization: "Bearer " +
ScriptApp.getOAuthToken()}}).getBlob();
In order to avoid this I updated the parameters for the UrlFetchApp:
var htmlTemplate = HtmlService.createTemplateFromFile('js');
htmlTemplate.url = url;
var params = {
headers: {authorization: "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
};
var blob = UrlFetchApp.fetch(url, params).getBlob();
var printerID = 'randomprinterID';
printGoogleDocument(blob, printerID, 1);
How about this modification?
In this modification, blob is directly retrieved from url as the PDF data.
From:
var url = ss.getUrl().replace(/edit$/, '') + 'export?format=pdf' +
PDF_OPTS + printRange + "&gid=" + gid;
var htmlTemplate = HtmlService.createTemplateFromFile('js');
//Here I'm wrongly trying to get the content from the Html.
//What I'll get is the content of js.html and not the info from the url
var pdf_html = htmlTemplate.evaluate().getContent();
//The blob needs to be build using an object.
//However I don't know how to access the pdf I'm exporting inside the url var
var blob = Utilities.newBlob(pdf_html, MimeType.HTML, 'temp').getAs(MimeType.PDF);
//random printer ID
var printerID = 'b71f9cd2-3e3e-qweq-12asd-aogt5keoqoa2';
printGoogleDocument(blob, printerID, 1);
To:
var url = ss.getUrl().replace(/edit$/, '') + 'export?format=pdf' + PDF_OPTS + printRange + "&gid=" + gid;
var blob = UrlFetchApp.fetch(url, {headers: {authorization: "Bearer " + ScriptApp.getOAuthToken()}}).getBlob();
var printerID = 'b71f9cd2-3e3e-qweq-12asd-aogt5keoqoa2';
printGoogleDocument(blob, printerID, 1);
I am trying to put a Google Sheet on a trigger every hour or so to export the contents of a sheet and upload them to Dropbox using Google Apps Script. The below code is successfully getting all of the sheets content and creating a new file in Dropbox, however that file is always empty. I think it has to do with how I'm sending the data, right now I think it is just sending the csv data and not the actual file. I have been searching around trying to figure out how to turn this into a file before sending it to Dropbox but I am stuck :/. Do I need to convert this csv content into a file in Google Drive first or is there a way to do it in real time?
function uploadToDropbox() {
try{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('sheet5');
var csvFile = convertRangeToCsvFile('testfile.csv', sheet)
var url = "https://content.dropboxapi.com";
var options = {
"hostname": url,
"method": "POST",
"encoding": "utf8",
"followRedirect": true,
"headers": {"Authorization": "Bearer XXXXXXXX",
"Content-Type": "application/octet-stream",
"Dropbox-API-Arg": '{"path": "/testfile.csv","mode": "overwrite","autorename": false,"mute": false,"strict_conflict": false}'
},
'muteHttpExceptions': true,
'body': csvFile
};
var response = UrlFetchApp.fetch(url + "/2/files/upload", options);
var responseCode = response.getResponseCode();
if(responseCode != 200) {throw 'Error: ' + responseCode + " - " + response}
var jsonResponse = JSON.parse(response.getContentText());
} catch(e) {
Logger.log(e)
}
}
function convertRangeToCsvFile(csvFileName, sheet) {
var activeRange = sheet.getDataRange();
try {
var data = activeRange.getValues();
var csvFile = undefined;
if (data.length > 1) {
var csv = "";
for (var row = 0; row < data.length; row++) {
for (var col = 0; col < data[row].length; col++) {
if (data[row][col].toString().indexOf(",") != -1) {
data[row][col] = "\"" + data[row][col] + "\"";
}
}
if (row < data.length-1) {
csv += data[row].join(",") + "\r\n";
}
else {
csv += data[row];
}
}
csvFile = csv;
}
return csvFile;
}
catch(err) {
Logger.log(err);
}
}
Try this:
function uploadToDropbox() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sheet=ss.getSheetByName('sheet5');
var csvFile=DriveApp.getFileById(convertRangeToCsvFile('testfile.csv', sheet));//this is the file now do whatever you want with it. It contains the csv
var url="https://content.dropboxapi.com";
var options={
"hostname": url,
"method": "POST",
"encoding": "utf8",
"followRedirect": true,
"headers": {"Authorization": "Bearer XXXXXXXX",
"Content-Type": "application/octet-stream",
"Dropbox-API-Arg": '{"path": "/testfile.csv","mode": "overwrite","autorename": false,"mute": false,"strict_conflict": false}'
},
'muteHttpExceptions': true,
'body': csvFile
};
var response=UrlFetchApp.fetch(url + "/2/files/upload", options);
var responseCode=response.getResponseCode();
if(responseCode != 200) {throw 'Error: ' + responseCode + " - " + response}
var jsonResponse=JSON.parse(response.getContentText());
}
function convertRangeToCsvFile(csvFileName, sheet) {
var activeRange=sheet.getDataRange();
var data=activeRange.getValues();
if (data.length>1) {
var csv="";
for(var row=0;row<data.length;row++) {
for (var col=0;col<data[row].length; col++) {
if (data[row][col].toString().indexOf(",") != -1) {
data[row][col]="\"" + data[row][col] + "\"";
}
}
if (row>data.length-1){csv += data[row].join(",") + "\r\n";
}else {csv += data[row];}
}
var file=DriveApp.getFilesByName('testFiles.csv').next();//assuming its the only one
file.setContent(csv);
}
return file.getId();
}
Problem:
The import function importXLSXtoGsheet() times out before it can process all 52 XLSX files, I received the error:
Exception: Time-out: https://www.googleapis.com/batch/drive/v3 at [unknown function](Code:63) at Do(Code:8) at importXLSXtoGsheet(Code:71)
If I run the function with 1 file in the importXLS folder, it works correctly.
Script explained:
I've got 52 folders, each containing one spreadsheet file.
Each folder is shared with different colleagues.
During the day, people make changes to the files.
At the end of the day, all files are collected in one folder (gsheetFolder) and converted to XLSX files, using the function collectAndExportXLS.
These files are copied to a local server in the evening (using batch script and drive sync) which updates other information in the file and are copied back to the importXLSXfolder.
In the morning the importXLSXtoGsheet function runs and converts all XLSX files in the importXLSXfolder folder to Gsheet files in the gsheetFolder.
After that sortGsheetFiles runs, sorting and moving every Gsheet file in one of the 52 folders (using an array list from the current spreadsheet).
Other actions include cleaning the folders with the deleteFolder function.
Script:
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);
}
About your question, I could understand like below.
When importXLSXtoGsheet() is run with 52 files, the error occurs.
When importXLSXtoGsheet() is run with less than 13 files, no error occurs.
Other functions except for importXLSXtoGsheet() works fine.
If my understanding is correct, as one workaround, it decides the maximum number for processing the files once. When this is reflect to importXLSXtoGsheet() of your script, the modified script is as follows.
Modified script:
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());
// I modified below script.
var n = 10; // Maximum number.
var files = [];
var len = obj.files.length;
for (var i = 0; i < len; i++) {
files.push(obj.files.splice(0, n));
len -= n - 1;
}
files.forEach(function(f) {
var reqs = f.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);
}
Note:
In this sample script, 10 files are processed every batch request. If you want to change this, please modify var n = 10;.