I want to make a script to get Crypto prices updated in a Google Spreadsheets. I don't want to use API connector, rather do it myself end to end. I found a blog post on CMC blog but it doesn't work, I get an error.
Here is the code:
function ohlc_price() {
var sh1=SpreadsheetApp.getActiveSpreadsheet().getSheetByName(“IDs″);
var requestOptions = {method: ‘GET’, uri: ‘https://pro-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical’, qs: {‘id’: ‘1’,’time_period’:’daily’,’interval’:’2d’, ‘start_date’: ‘2019-08-15’, ‘end_date’: ‘2019-08-18’},
headers: {‘X-CMC_PRO_API_KEY’: ‘MY APY KEY IS HERE’},
json: true, gzip: true};
var url=”https://pro-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?id=1&time_start=2019-06-01&interval=weekly”;
var result= UrlFetchApp.fetch(url, requestOptions);
var txt= result.getContentText();
var d=JSON.parse(txt); for (var i=0; i<10;i++) {sh1.getRange(i+2, 1).setValue(d.data.quotes[i].quote.USD.timestamp); sh1.getRange(i+2, 2).setValue(d.data.quotes[i].quote.USD.low); sh1.getRange(i+2, 3).setValue(d.data.quotes[i].quote.USD.open); sh1.getRange(i+2, 4).setValue(d.data.quotes[i].quote.USD.close); sh1.getRange(i+2, 5).setValue(d.data.quotes[i].quote.USD.high);}
Here is the error message I get:
SyntaxError: Invalid or unexpected token (ligne : 2, fichier : Coin price.gs)
I tried to follow CMC instructions but nothing works...
Can someone explain me what isn't working and why ?
Thx
I expect there is some lacks of quotes or apostrophes, especially after the uri/url. Try this and complete :
function ohlc_price() {
var sh1=SpreadsheetApp.getActiveSpreadsheet().getSheetByName('IDs');
var requestOptions = {
'method' : 'GET',
'uri': 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical’',
'qs': {'id': '1',
'time_period':'daily',
'interval':'2d',
'start_date': '2019-08-15',
'end_date': '2019-08-18'
},
'headers' : {'X-CMC_PRO_API_KEY': 'MY APY KEY IS HERE'},
'json': true,
'gzip': true};
var url = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?id=1&time_start=2019-06-01&interval=weekly”';
var result = UrlFetchApp.fetch(url, requestOptions);
var txt= result.getContentText();
}
Modification points:
There are no properties of uri and qs in the parameter of UrlFetchApp.
In your URL, id=1&time_start=2019-06-01&interval=weekly is used as the query parameter. But in your qs, {‘id’: ‘1’,’time_period’:’daily’,’interval’:’2d’, ‘start_date’: ‘2019-08-15’, ‘end_date’: ‘2019-08-18’} is used. So unfortunately, I cannot understand which do you want to use.
In this modification, interval=weekly, time_start=2019-06-01, and time_end=2019-08-18 are used. When you want to use other values, please modify the script.
In your script, for (var i = 0; i < 10; i++) {} is used for var d = JSON.parse(txt). In this case, when the data length is less than 10, an error occurs.
When above points are reflected to your script, it becomes as follows.
Modified script:
function ohlc_price() {
// This is from https://gist.github.com/tanaikech/70503e0ea6998083fcb05c6d2a857107
String.prototype.addQuery = function (obj) {
return this + Object.keys(obj).reduce(function (p, e, i) {
return p + (i == 0 ? "?" : "&") +
(Array.isArray(obj[e]) ? obj[e].reduce(function (str, f, j) {
return str + e + "=" + encodeURIComponent(f) + (j != obj[e].length - 1 ? "&" : "")
}, "") : e + "=" + encodeURIComponent(obj[e]));
}, "");
}
var url = "https://pro-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical";
var query = { 'id': '1', 'time_period': 'daily', 'interval': 'weekly', 'time_start': '2019-06-01', 'time_end': '2019-08-18' };
var endpoint = url.addQuery(query);
var requestOptions = {
method: 'GET',
headers: { 'X-CMC_PRO_API_KEY': 'MY APY KEY IS HERE' },
};
var result = UrlFetchApp.fetch(endpoint, requestOptions);
var txt = result.getContentText();
var d = JSON.parse(txt);
var sh1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("IDs");
var values = d.data.quotes.map(({ quote: { USD } }) => [USD.timestamp, USD.low, USD.open, USD.close, USD.high]);
sh1.getRange(2, 1, values.length, values[0].length).setValues(values);
}
Note:
In this answer, it supposes that your value of X-CMC_PRO_API_KEY is valid value. Please be careful this.
References:
fetch(url, params)
OHLCV Historical
Related
I was trying to fetch data from Clearbit API and I get this message : " Exception: The parameters (String,(class),(class)) don't match the method signature for UrlFetchApp.fetch."
Before writing this post I tried to search online but couldn't find the answer.
I share with you my code :
function linkedInUrl(domain) {
let url = `https://company.clearbit.com/v2/companies/find?domain=${domain}`
const api_keys = ""
const header = {
method: 'GET',
headers: {'Authorization':'Bearer ' + api_keys}
}
options = {muteHttpExceptions: true};
var response = UrlFetchApp.fetch(url,header,options)
var data = JSON.parse(response.getContentText())
return "https://www.linkedin.com/"+data.linkedin.handle
}
function techUsed(domain) {
let url = `https://company.clearbit.com/v2/companies/find?domain=${domain}`
const api_keys = ""
const header = {
method: 'GET',
headers: {'Authorization':'Bearer ' + api_keys}
}
options = {muteHttpExceptions: true};
var response = UrlFetchApp.fetch(url,header,options)
var data = JSON.parse(response.getContentText())
tech = ""
for(let i = 0; i < data.tech.length; i++) {
tech += data.tech[i] +","
}
return tech
}
Does anyone have a clue ?
Thank you for your help.
The arguments of fetch(url, params) are url and params. I think that this is the reason for your current issue. So, please modify your script as follows.
From:
let url = `https://company.clearbit.com/v2/companies/find?domain=${domain}`
const api_keys = ""
const header = {
method: 'GET',
headers: {'Authorization':'Bearer ' + api_keys}
}
options = {muteHttpExceptions: true};
var response = UrlFetchApp.fetch(url,header,options)
To:
let url = `https://company.clearbit.com/v2/companies/find?domain=${domain}`;
const api_keys = "###"; // Please set your access token.
options = {
method: 'GET',
headers: { 'Authorization': 'Bearer ' + api_keys },
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(url, options);
Note:
In this case, your api_keys is valid value for using the API. Please be careful about this.
Unfortunately, I cannot know the response value from the API you want to use. So, if your script below var response = UrlFetchApp.fetch(url, options); occurs an error, please provide the sample value. By this, I would like to confirm your script.
Reference:
fetch(url, params)
You can try this :
function linkedInUrl(domain) {
let url = `https://company.clearbit.com/v2/companies/find?domain=${domain}`
const api_keys = ""
const header = {
method: 'GET',
headers: {'Authorization':'Bearer ' + api_keys}
}
options = {muteHttpExceptions: true};
var res
fetch(url,header,options) //api for the get request
.then(response => response.json())
.then(data => console.log('response',data))
}
My function is showing this error for a few days, before it worked normally. I really don't know how to insert a fix for this problem. Thank you very much in advance.
Service invoked too many times in a short time: urlfetch. Try Utilities.sleep(1000) between calls.
myTrivia # TRIVIA.gs:14
This is my code:
function myTrivia() {
var f = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('TRIVIA');
var data = new Date();
data = Utilities.formatDate(data, "GMT-03:00", "yyyy/MM/dd");
f.getRange('F1').setValue(data);
var url = 'https://triviapw.com.br/cotacao/api/item/';
var [h, ...v] = f.getDataRange().getValues();
var reqs = v.map(([a]) => ({
url,
method: "post",
payload: {id: a, date: data, server: h[6]},
muteHttpExceptions: true
}));
var res = UrlFetchApp.fetchAll(reqs);
var values = res.map(r => {
var str = r.getContentText();
if (r.getResponseCode() == 200 && str != "Requisição inválida") {
var obj = JSON.parse(str);
return [obj.nome, obj.venda, obj.compra];
}
return Array(3).fill("");
});
f.getRange(2, 2, values.length, values[0].length).setValues(values);
}
After using the code suggested below (by #Tanaike), the system reports the following "Invalid request" and after "Exceeded maximum execution time"
I tested an alternative for just one line and it worked normally (this was the old code)
Here's the code:
function myTrivia() {
var f = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('TRIVIA');
var formData = {
'id': f.getRange('A2').getValue(), //A2 IDitem
'date': f.getRange('F1').getValue(), //F1 Date
'server': f.getRange('G1').getValue(), //G1 ServerName
};
var options = {
'method': 'post',
'payload': formData
};
var result = UrlFetchApp.fetch('https://triviapw.com.br/cotacao/api/item/', options);
var response = JSON.parse(result.getContentText());
var res_code = result.getResponseCode();
if (res_code == 200) {
f.getRange('B2').setValue(response.nome); //name item
f.getRange('C2').setValue((response.venda + response.compra) / 2); //midle price for test
}
}
From So my spreadsheet has 116 rows and I usually update it once or twice a day at most., I thought that in this case, your error message of Service invoked too many times in a short time: urlfetch. might not occur. So, I'm worried about other reasons.
But, if you want to use UrlFetchApp.fetch instead of UrlFetchApp.fetchAll, how about the following modified script?
Modified script:
function myTrivia() {
var f = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('TRIVIA');
var data = new Date();
data = Utilities.formatDate(data, "GMT-03:00", "yyyy/MM/dd");
f.getRange('F1').setValue(data);
var url = 'https://triviapw.com.br/cotacao/api/item/';
var [h, ...v] = f.getDataRange().getValues();
var values = v.map(([a]) => {
var r = UrlFetchApp.fetch(url, { method: "post", payload: { id: a, date: data, server: h[6] }, muteHttpExceptions: true });
var str = r.getContentText();
var res;
if (r.getResponseCode() == 200 && str != "Requisição inválida") {
var obj = JSON.parse(str);
res = [obj.nome, obj.venda, obj.compra];
} else {
console.log(str); // If an error occurs, you can see the error message at the log.
res = Array(3).fill("");
}
Utilities.sleep(2000);
return res;
});
f.getRange(2, 2, values.length, values[0].length).setValues(values);
}
In this modified script, each request is run with the synchronous process. And, each request is run by Utilities.sleep(2000). Please adjust the value of 2000 of Utilities.sleep(2000) for your actual situation.
Reference:
sleep(milliseconds)
Added:
When you want to use the script for retrieving one value from one row as a custom function, how about the following sample script? In this sample script, please put a custom function like =myTrivia(A2) to a cell. By this, the script is run for one row.
function myTrivia(id) {
var max = 2; // Number of retry request.
var [date, server] = SpreadsheetApp.getActiveSheet().getRange("F1:G1").getDisplayValues()[0];
var retry = 0;
do {
var url = 'https://triviapw.com.br/cotacao/api/item/';
var r = UrlFetchApp.fetch(url, { method: "post", payload: { id, date, server }, muteHttpExceptions: true });
var str = r.getContentText();
if (r.getResponseCode() == 200 && str != "Requisição inválida") {
var obj = JSON.parse(str);
return [[obj.nome, obj.venda, obj.compra]];
}
retry++;
Utilities.sleep(2000);
} while (retry < max);
return [Array(3).fill("")];
}
In this sample script, when 1st request occurs an error, the request is retried. Even when 2 requests are done, when an error occurs, the empty value is returned. You can adjust the number of retry with max.
With great SO help at previous step, I have writes to sheet almost working with URLFetchApp under service account credentials in a webapp. The code (below) only works with the "put" method; "post" generates an error. My understanding is that updates and inserts can both be done with "put" method. But the code is generating an error when the range is for a new row--that is, the last row in the sheet is not blank.
"range exceeds grid limits when inserting new row"
If it is necessary to have empty rows (e.g., add 1000 rows), does this become a manual maintenance job to monitor and periodically add new blank rows? I expected the "put" to simply add a new row. Is there another method with URLFetchApp to first add rows to the "grid" before inserting data? Thank you for any guidance!
function postData(ssID,updateRange,data) {
if (clientToken) {
var url= `https://sheets.googleapis.com/v4/spreadsheets/${ssID}/values/${updateRange}?valueInputOption=RAW`
var options = {
muteHttpExceptions: true,
contentType: 'application/json',
method:'put',
payload: JSON.stringify(data),
headers: { Authorization: 'Bearer ' + clientToken }
};
var response= UrlFetchApp.fetch(url,options);
var responseCode = response.getResponseCode();
var responseBody = response.getContentText();
if (responseCode === 200) {
var responseJson = JSON.parse(responseBody)
return responseJson;
} else {
Logger.log(Utilities.formatString("Request failed. Expected 200, got %d: %s", responseCode, responseBody))
return responseCode;
}
} else {//handle failed authorization }
} //end postData
Unfortunately, there is no method in the Sheets API V4 that can automatically add rows when the given range exceeds the sheet range.
What you can do is to get the rowCount of a specific sheet by using Method: spreadsheets.get then compare it with the range you will use to update values. If rowCount is less than the update range, use Method: spreadsheets.batchUpdate to update the sheet dimension.
Demo:
Example Sheet:
Code:
function request(ssID="spreadsheet id here",updateRange = "A1499:A1500",data) {
if (clientToken) {
var ssGetUrl= `https://sheets.googleapis.com/v4/spreadsheets/${ssID}`
var options = {
muteHttpExceptions: true,
contentType: 'application/json',
method:'get',
headers: { Authorization: 'Bearer ' + clientToken }
};
var ssGetresponse= JSON.parse(UrlFetchApp.fetch(ssGetUrl,options));
var sheets = ssGetresponse.sheets;
var rowCount = 0;
var sheetId = 0;
sheets.forEach(sheet => {
if(sheet.properties.sheetId == sheetId){
rowCount = sheet.properties.gridProperties.rowCount
}
})
var num = parseInt(updateRange.split(":")[1].replace(/[^0-9]/g,'')); //remove letters in updateRange and convert it to string
if(rowCount < num){
var diff = num - rowCount;
var resource = {
"requests": [
{
"appendDimension": {
"length": diff,
"dimension": "ROWS",
"sheetId": 0
}
}
]
};
var ssBatchUpdateUrl= `https://sheets.googleapis.com/v4/spreadsheets/${ssID}:batchUpdate`
var options = {
muteHttpExceptions: true,
contentType: 'application/json',
method:'post',
payload: JSON.stringify(resource),
headers: { Authorization: 'Bearer ' + clientToken }
};
var response= JSON.parse(UrlFetchApp.fetch(ssBatchUpdateUrl,options));
}
//insert code for updating range values
}
}
After executing code:
Note: The demo above is for increasing the number of rows when the update range is beyond the sheet's actual rows. For instance, if you have a range that the column is beyond the sheet's actual column, you can update the script to also read the columnCount, modify the parser to also get column part of A1 Notation and add another entry on appendDimension with COLUMN as dimension.
Try this:
function postData(ssID, updateRange, data) {
const ss = SpreadsheetApp.openById(ssID);
const sh = ss.getRange(updateRange).getSheet();//I assumed range is in A1 notation
const lr = sh.getLastRow();
if (lr == sh.getMaxRows()) {
sh.insertRowsAfter(lr, data.length);
}
if (clientToken) {
var url = `https://sheets.googleapis.com/v4/spreadsheets/${ssID}/values/${updateRange}?valueInputOption=RAW`
var options = {
muteHttpExceptions: true,
contentType: 'application/json',
method: 'put',
payload: JSON.stringify(data),
headers: { Authorization: 'Bearer ' + clientToken }
};
var response = UrlFetchApp.fetch(url, options);
var responseCode = response.getResponseCode();
var responseBody = response.getContentText();
if (responseCode === 200) {
var responseJson = JSON.parse(responseBody)
return responseJson;
} else {
Logger.log(Utilities.formatString("Request failed. Expected 200, got %d: %s", responseCode, responseBody))
return responseCode;
}
} else {//handle failed authorization }
} //end postData
I am trying to do a request to Gate.io cryptocurrency market and getting this error.
{"label":"INVALID_SIGNATURE","message":"Signature mismatch"}
I have managed to find a way to correctly encrypt all the parameters(my output is the same as they presented in their documentation), however, when I add a real secret key I got this error.
Please see the screenshot:
the right-hand side is a signature from their doc, in the GAS log you see my output so these are the same however when I add real timestamp and my real secret then it doesn't work
Screenshot.
Here is the fetch request I am using:
function getDateIo() {
var key = "xxx"
var sec = "xxx"
var timestamp = Math.floor(Date.now() / 1000)
var a = {"contract":"BTC_USD","type":"limit","size":100,"price":6800,"time_in_force":"gtc"}
a = JSON.stringify(a)
var body = {"text":"t-123456","currency_pair":"ETH_BTC","type":"limit","account":"spot","side":"buy","iceberg":"0","amount":"1","price":"5.00032","time_in_force":"gtc","auto_borrow":false}
body = JSON.stringify(body)
console.log(body)
var requestPayload = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_512, "")
requestPayload = requestPayload.map(function(e) {
var v = (e < 0 ? e + 256 : e).toString(16);
return v.length == 1 ? "0" + v : v;
}).join("");
console.log(requestPayload)
var meth = 'GET'
var pat = '/api/v4/futures/orders'
var sign = meth + "\n" + pat + "\n" + "contract=BTC_USD&status=finished&limit=50" + "\n" + requestPayload + "\n" + timestamp;
console.log(sign)
var signature = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, sign, sec);
signature = signature.map(function(e) {
var v = (e < 0 ? e + 256 : e).toString(16);
return v.length == 1 ? "0" + v : v;
}).join("");
var params = {
'method': "get",
'headers': {
'Accept': 'application/json',
'Content-Type': 'application/json',
'KEY': key,
'Timestamp': timestamp,
'SIGN': signature,
},
// 'body': body,
'muteHttpExceptions': true,
};
var data = UrlFetchApp.fetch("https://api.gateio.ws/api/v4/futures/orders?contract=BTC_USD&status=finished&limit=50", params);
}
Thanks for any advice
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;.