Google Script: Script Error, but Script functions properly - google-apps-script

I'm trying to convert all CSV and Excel files in a folder to Google Sheet format. The code works, but debugging it produces an error.
function fileToSheet(fileId) {
var file = DriveApp.getFileById(fileId);
var fileInfo = {
title: "(" + Utilities.formatDate(new Date(), "IST", "yyyy.mm.dd") + ") " + file.getName(),
mimeType: MimeType.GOOGLE_SHEETS,
parents: [{id: file.getParents().next().getId()}]
}
var blob = file.getBlob();
var mimeType = blob.getContentType();
if (mimeType == MimeType.CSV || mimeType == MimeType.MICROSOFT_EXCEL || mimeType == MimeType.MICROSOFT_EXCEL_LEGACY) {
var spreadsheet = Drive.Files.insert(fileInfo, blob);
Logger.log(spreadsheet.id)
}
return ""
}
function convertFiles(folderId) {
var folder = DriveApp.getFolderById(folderId);
var files = folder.getFiles();
Logger.log(files.length)
while (files.hasNext()) {
var file = files.next()
var fileId = file.getId()
fileToSheet(fileId)
}
}
Debugging and running it to the end still produces an error (Error Exception: Invalid argument: id fileToSheet # Code.gs:2), but the code still works when I use it on folders.
Is there any way to shorten the code to make it more concise? (still new to coding)
Thank you!

Insert the following in the beginning of the fileToSheet() function:
function fileToSheet(fileId) {
if (!fileId) {
throw new Error(
'Please do not run the fileToSheet() function in the script editor window. '
+ 'See https://stackoverflow.com/a/46860052/13045193 to learn how to '
+ 'debug the function properly.'
);
}
var file = DriveApp.getFileById(fileId);
// ...

Related

Uploading a file to Google Shared Drive via Spreadsheet

I'm trying to use google spreadsheets to upload files to a certain folder on a Shared Drive. I've found this code online and it didn't actually work to start with but I played with it and it would still not initiate the upload.
The code I used came from this website.
I've modified the upload function:
folderId = 'my folder ID'
driveId = 'my shared drive ID'
function onOpen(e){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var menuEntries = [];
menuEntries.push({name: "File", functionName: "doGet"});
ss.addMenu("Attach", menuEntries);
}
//the upload script
function upload(obj) {
var metadata = {
"parents": [{
"id": folderId,
"kind": "drive#parentReference"
}],
"teamDriveId": driveId };
var optionalParams = {
"supportsAllDrives": true
};
file = Drive.Files.insert(metadata, optionalParams);
var activeSheet = SpreadsheetApp.getActiveSheet();
var File_name = file.getName()
var value = 'hyperlink("' + file.getUrl() + '";"' + File_name + '")'
var activeSheet = SpreadsheetApp.getActiveSheet();
var selection = activeSheet.getSelection();
var cell = selection.getCurrentCell()
cell.setFormula(value)
return {
fileId: file.getId(),
mimeType: file.getMimeType(),
fileName: file.getName(),
};
}
I think the obj refers to the type of file you are uploading maybe, you can review the proper code in this documentation https://developers.google.com/drive/api/v3/manage-uploads#multipart
Just make sure to select "Java."
Here is the example in that KB:
File fileMetadata = new File();
fileMetadata.setName("photo.jpg");
java.io.File filePath = new java.io.File("files/photo.jpg");
FileContent mediaContent = new FileContent("image/jpeg", filePath);
File file = driveService.files().create(fileMetadata, mediaContent)
.setFields("id")
.execute();
System.out.println("File ID: " + file.getId());

Google Script CSV Downloader Project - How to specify Folder

I have been working on creating a script to allow employees in our shipping department to operate more efficiently. We use a barcode scanner to generate a CSV file - we use the following script to specify cells for the CSV; I'm looking to improve this so that the file is saved in a specific folder for easy sharing.
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var searchMenuEntries = [ {name: "Search in all files", functionName: "search"}];
var csvMenuEntries = [{name: "Save as CSV file", functionName: "saveAsCSV"},
{name: "Load from CSV file", functionName: "importFromCSV"}];
ss.addMenu("Search Google Drive", searchMenuEntries);
ss.addMenu("CSV", csvMenuEntries);
}
function saveAsCSV() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Primary Time');
// append ".csv" extension to the sheet name
// Prompts the user for the file name
var fileName = Browser.inputBox("Save CSV file as (e.g. myCSVFile):");
// Check that the file name entered wasn't empty
if (fileName.length !== 0) {
// Add the ".csv" extension to the file name
fileName = fileName + ".csv";
// Convert the range data to CSV format
var csvFile = convertRangeToCsvFile_(fileName);
// Create a file in Drive with the given name, the CSV data and MimeType (file type)
DriveApp.createFile(fileName, csvFile, MimeType.CSV);
else {
Browser.msgBox("Error: Please enter a CSV file name.");
}
}
function convertRangeToCsvFile_(csvFileName) {
// Get the selected range in the spreadsheet
var ws = SpreadsheetApp.getActiveSpreadsheet().getActiveSelection();
try {
var data = ws.getValues();
var csvFile = undefined;
// Loop through the data in the range and build a string with the CSV data
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] + "\"";
}
}
// Join each row's columns
// Add a carriage return to end of each row, except for the last one
if (row < data.length-1) {
csv += data[row].join(",") + "\r\n";
}
else {
csv += data[row];
}
}
csvFile = csv;
}
return csvFile;
}
catch(err) {
Logger.log(err);
Browser.msgBox(err);
}
}
I have 2 options for you:
Use File.moveTo(destination) to move your newly created file to your target folder.
Sample code:
function option1(){
var targetFolderId ='1QHe2zCebXBZxiplAfVZpO1dhxxxx';
var csvFile = "Sample Content";
var folder = DriveApp.getFolderById(targetFolderId);
var file = DriveApp.createFile("SampleFile1.csv", csvFile, MimeType.CSV);
file.moveTo(folder);
}
Use Advanced Drive Service to create a file within a specific parent folder
Sample Code:
function option2(){
var targetFolderId ='1QHe2zCebXBZxiplAfVZpO1dhxxxx';
var content = "Sample Content";
var resource = {
title: "SampleFile2.csv",
mimeType: "text/csv",
parents: [{id:targetFolderId}]
}
var blob = Utilities.newBlob(content,"text/csv");
var file = Drive.Files.insert(resource,blob);
Logger.log(file);
}
Output:

Google Sheet: Replace file with the same name

I'm currently generating a PDF file from an active sheet. Is there a way to overwrite or replace the file in the google drive without putting it to trash? I have this code that I saw online.
if (files.hasNext()) {
files.next().setTrashed(true);
}
Am I using the code right or there is another way for me to do it?
I used that code on the function below.
function _exportBlob(blob, fileName) {
var timeZone = Session.getScriptTimeZone();
var date = Utilities.formatDate(new Date(), timeZone, "yyyy");
var ss = SpreadsheetApp.getActiveSpreadsheet();
var fileName = "FORM137 - " + ss.getRange("REPORT CARD!D12").getValue() + " - ARCS" + date;
var ssID = ss.getId();
var ssFile = DriveApp.getFileById(ssID);
blob = blob.setName(fileName)
var parentFolder = DriveApp.getFileById(ss.getId()).getParents().next();
var subFolder = parentFolder.getFoldersByName("CARDS").next();
var files = subFolder.getFilesByName(getFilename());
if (files.hasNext()) {
files.next().setTrashed(true);
}
var pdfFile = subFolder.createFile(blob);
if (pdfFile) {
const htmlOutput = HtmlService
.createHtmlOutput('<p>Click to open ' + fileName + '</p>')
.setWidth(300)
.setHeight(80)
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Export Successful')
}
}
Here's the getFilename function:
function getFilename() {
var ss = SpreadsheetApp.getActive();
var filename = "FORM137 - " + ss.getRange("REPORT CARD!D12").getValue() + " - ARCS" + date;
return filename;
}
I believe your goal as follows.
You want to overwrite blob to the existing file of getFilename().
In this case, I would like to propose to use the method of "Files: update" in Drive API.
Before you use this script, please enable Drive API at Advanced Google services.
From:
var files = subFolder.getFilesByName(getFilename());
if (files.hasNext()) {
files.next().setTrashed(true);
}
var pdfFile = subFolder.createFile(blob);
To:
var files = subFolder.getFilesByName(getFilename());
var pdfFile = files.hasNext() ? DriveApp.getFileById(Drive.Files.update({}, files.next().getId(), blob).id) : subFolder.createFile(blob);
In this modification, when the file of getFilename() is not existing, a new file is created.
Reference:
Files: update

Adding Replace Existing File to GmailToDrive App Script - Follow up Question

This is an additional question off of the related post: Adding Replace Existing File to GmailToDrive App Script answered by #Tanaike.
I'm trying to use the code from the previous post with the Edit function with an xlsx file. Everything seems to be working fine where it grabs the file and saves it and it even updated the modified date in the google drive folder. However, the content of the excel file does not change from the original. I've enabled the Drive API. Is this compatible with xlsx file types? Is there something additional needed to actually update the content in the file and not just the metadata?
// GLOBALS
//Array of file extension which you would like to extract to Drive
var fileTypesToExtract = ['xlsx'];
//Name of the folder in google drive i which files will be put
var folderName = 'YourfolderName;
//Name of the label which will be applied after processing the mail message
var labelName = 'Saved2';
function GmailToDrive(){
//build query to search emails
var query = '';
//filename:jpg OR filename:tif OR filename:gif OR fileName:png OR filename:bmp OR filename:svg'; //'after:'+formattedDate+
for(var i in fileTypesToExtract){
query += (query === '' ?('filename:'+fileTypesToExtract[i]) : (' OR filename:'+fileTypesToExtract[i]));
}
query = 'in:inbox label:MyCustomLabel has:attachment ' + query;
var threads = GmailApp.search(query);
var label = getGmailLabel_(labelName);
var parentFolder;
if(threads.length > 0){
parentFolder = getFolder_(folderName);
}
var root = DriveApp.getRootFolder();
for(var i in threads){
var mesgs = threads[i].getMessages();
for(var j in mesgs){
//get attachments
var attachments = mesgs[j].getAttachments();
for(var k in attachments){
var attachment = attachments[k];
var isDefinedType = checkIfDefinedType_(attachment);
if(!isDefinedType) continue;
var attachmentBlob = attachment.copyBlob();
var existingFile = DriveApp.getFilesByName(attachment.getName());
if (existingFile.hasNext()) {
var file = existingFile.next();
Drive.Files.update({}, file.getId(), attachmentBlob);
} else { // Added
var file = DriveApp.createFile(attachmentBlob); // Added
parentFolder.addFile(file); // Added
root.removeFile(file); // Added
}
}
}
threads[i].addLabel(label);
}
}
//This function will get the parent folder in Google drive
function getFolder_(folderName){
var folder;
var fi = DriveApp.getFoldersByName(folderName);
if(fi.hasNext()){
folder = fi.next();
}
else{
folder = DriveApp.createFolder(folderName);
}
return folder;
}
//getDate n days back
// n must be integer
function getDateNDaysBack_(n){
n = parseInt(8);
var date = new Date();
date.setDate(date.getDate() - n);
return Utilities.formatDate(date, Session.getScriptTimeZone(), 'yyyy/MM/dd');
}
function getGmailLabel_(name){
var label = GmailApp.getUserLabelByName(name);
if(!label){
label = GmailApp.createLabel(name);
}
return label;
}
//this function will check for filextension type.
// and return boolean
function checkIfDefinedType_(attachment){
var fileName = attachment.getName();
var temp = fileName.split('.');
var fileExtension = temp[temp.length-1].toLowerCase();
if(fileTypesToExtract.indexOf(fileExtension) !== -1) return true;
else return false;
}
Because .xlsx is the Excel format, Apps Script can't modify its content because it's not a Google product, it's like trying to modify a pdf using Apps Script, but don't worry, you could convert the .xlsx file into the native Google Spreadsheet format and then handle it like a normal Google Spreadsheet. This function will do the conversion for you:
// this Function will convert your .xlsx files into native Google Spreadsheet format
function convertExceltoGoogleSpreadsheet(parentFolder) {
var files = parentFolder.getFiles();
while(files.hasNext()){
var file = files.next();
// If the file contains the .xlsx extention in its name
// then it will return an array with length 2
var filename = file.getName().split(/.xlsx?/);
if(filename.length > 1){
// build info to create the new file with Google Spreadsheet format
var resource = {
title: filename[0],
mimeType: MimeType.GOOGLE_SHEETS,
parents: [{id: parentFolder.getId()}],
};
// Return the response after creating the file
return Drive.Files.insert(resource, file.getBlob());
}
}
}
Then, use that function in this part of your code:
...
var attachmentBlob = attachment.copyBlob();
var existingFile = DriveApp.getFilesByName(attachment.getName());
if (existingFile.hasNext()) {
var file = existingFile.next();
Drive.Files.update({}, file.getId(), attachmentBlob);
} else {
var file = DriveApp.createFile(attachmentBlob)
parentFolder.addFile(file);
root.removeFile(file);
}
// Let's change the format and insert a "Hello world" message
// ----START----
var spreadSheetResponse = convertExceltoGoogleSpreadsheet(parentFolder);
var spreadSheetId = spreadSheetResponse.getId()
var sheet = SpreadsheetApp.openById(spreadSheetId).getSheets()[0];
sheet.getRange(1, 1).setValue("Hello world");
// ----END----
...
Notice
In my code I left the .xlsx file in the Drive, if you want you could delete it after converting it iinto the native Google Spreadsheet format
Docs
This is what I used to help you:
SpreadsheetApp
Drive - Class File

Optimize Google Scripts - Triggers not working

Problem
My Google Script triggers aren't running because it "uses to much CPU time", according to error emails I receive. How can I optimize my scripts to use less CPU time?
I've separated sortGsheetFiles into different trigger, but it still uses to much time. It used to be combined with the importXLSXtoGsheet function.
Scripts 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.
Triggers
importXLSXtoGsheet - every day - between 6 am and 7 am
sortGsheetFiles - every day - between 7 am and 8 am
collectAndExportXLS - every day - between 10 pm and 11 pm
Script
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());
}
}
}
How about this modification? Please think of this as just one of several answers.
And as an important point, please test the script using a test situation, before you run with your actual situation.
About your script:
collectAndExportXLS(): Abou this function name, I didn't modify collectAndExportXLS(). Because I thought that you might be using this function name at other script or triggers.
Delete all files in gsheetFolder.
Convert a Google Spreadsheet in each folder ID retrieved from "B2:B53" of the sheet with the 1st index in the active Spreadsheet to XLSX format.
Filename is like sample.xlsx.
All converted files are put in XLSXfolder.
Delete all files in all folder IDs.
XLSX files in XLSXfolder are put in importXLSXfolder by other script.
importXLSXtoGsheet(): Abou this function name, I didn't modify collectAndExportXLS(). Because I thought that you might be using this function name at other script or triggers.
Delete all files in XLSXfolder.
Convert all XLSX files in importXLSXfolder to Google Spreadsheet.
Filename is like sample.xlsx.
Converted Google Spreadsheets are put in gsheetFolder.
Delete all files in importXLSXfolder.
sortGsheetFiles()
Move Google Spreadsheets in gsheetFolder to each folder ID retrieved from "B2:B53" of the sheet with the 1st index in the active Spreadsheet.
In order to match the folder ID, the filenames of Google Spreadsheet and the values retrieved from "A2:A53".
Delete all files in importXLSXfolder.
I understood that from your question, the filenames of column "A2:A53" of the active Spreadsheet are the same with the filenames of Google Spreadsheets which were put in the folders of folder IDs of the column "B2:B53".
I understood that the number of all files is less than 100.
I understand like above. If my understanding is correct, how about this modification? In my modification, I used the Batch request of Drive API and the fetchAll method of UrlFetchApp with the type of multipart/form-data for your situation. The batch request and fetchAll method can work with the asynchronous process. By this, I thought that your process cost might be reduced.
In order to use these methods, I used 2 GAS libraries. Before you run the script, please install these 2 libraries for your script. You can see how to install the library as follows.
Install a library for running the fetchAll method of UrlFetchApp with the type of multipart/form-data.
Install a library for running batch request.
Modification points:
collectAndExportXLS()
File IDs in each folder are retrieved by the batch request.
Blobs (XLSX format) from each file ID are retrieved by the fetchAll method of UrlFetchApp.
Files of XLSX format are created by FetchApp.
importXLSXtoGsheet()
File list is retrieved by the files.list method of Drive API.
Files of XLSX format are converted to Google Spreadsheet by the batch request.
sortGsheetFiles()
File list is retrieved by the files.list method of Drive API.
Files of Google Spreadsheet are moved to each folder ID retrieved from the column "B2:B53" of the active Spreadsheet using the batch request.
deleteFolder()
Files in the folder are deleted by the batch request.
When above points are reflected to your script, it becomes as follows.
Modified script:
After installed 2 libraries, please run the following 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);
}
Note:
In this modification, the error handling is not reflected, because I couldn't test your situation. So please add it, if you are required.
If the file size of XLSX files is large, the error might occur.
References:
Batch request of Drive API
BatchRequest
FetchApp