Copying XLSX file to GSheet in Google Drive - google-apps-script

I'm trying to copy over an XLSX sheet to an existing Gsheet, both are in the same GDrive folder. This script works when I run it as Drive.Files.insert() but that causes multiple version of the file to be created each time the script is run - so I switched it over to Drive.Files.update() like below....
function importXLS(){
var myFolder= "XXXXXXXXXX"; // Set the folder ID of "FolderB" if you want to copy over to a different folder
var files = DriveApp.getFolderById(myFolder).searchFiles('title = "XXXXX.xlsx"');
while(files.hasNext()){
var xFile = files.next();
var name = xFile.getName();
if (name.indexOf('.xlsx')>-1){
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = {
title : name + '_converted',
parents: [{'id': myFolder}],
supportsAllDrives: true
};
file = Drive.Files.update(newFile, xBlob, { //Originally using Drive.Files.insert() but was creating multiple versions. I want to overwrite the existing version.
convert: true, supportsAllDrives: true
});
}
}
}
But I'm getting the following error when this runs...
Exception: The mediaData parameter only supports Blob types for upload.
Any idea on what I'm doing wrong? This is my first time using Google Apps Script and javascript so I'm kinda flying blind here.

I believe your goal is as follows.
You have a folder in Google Drive. There are XLSX files and Google Spreadsheets in the folder.
You want to overwrite the Google Spreadsheet with the XLSX file by searching the filename.
Filename of the XLSX file is like XXXXX.xlsx.
Filename of the Google Spreadsheet file is like XXXXX.xlsx_converted.
Modification points:
In the case of Drive.Files.update, it is required to include the file ID of the target file.
In your script, the file ID of the target Spreadsheet is not retrieved.
The 2nd argument of Drive.Files.update is required to be the file ID. But, your script uses blob. I thought that this might be the reason for your current issue.
When these points are reflected in your script, how about the following modification?
Modified script:
function importXLS() {
var myFolder = "XXXXXXXXXX"; // Please set the folder ID.
var filename = "XXXXX.xlsx"; // Please set the filename of XLSX file.
var folder = DriveApp.getFolderById(myFolder);
var files = folder.searchFiles(`title="${filename}" and mimeType="${MimeType.MICROSOFT_EXCEL}" and trashed=false`);
while (files.hasNext()) {
var xFile = files.next();
var name = xFile.getName();
if (name.indexOf('.xlsx') > -1) {
var xBlob = xFile.getBlob();
var spreadsheetFileName = name + '_converted';
var spreadsheet = folder.searchFiles(`title="${spreadsheetFileName}" and mimeType="${MimeType.GOOGLE_SHEETS}" and trashed=false`);
if (spreadsheet.hasNext()) {
Drive.Files.update(null, spreadsheet.next().getId(), xBlob, { convert: true, supportsAllDrives: true });
} else {
var newFile = { title: spreadsheetFileName, parents: [{ 'id': myFolder }] };
file = Drive.Files.insert(newFile, xBlob, { convert: true, supportsAllDrives: true });
}
}
}
}
When this script is run, the XLSX file of XXXXX.xlsx is retrieved from the specific folder. And, Google Spreadsheet of the filename of XXXXX.xlsx_converted is searched from the same folder. When the Spreadsheet is found, the Spreadsheet is overwritten by the XLSX file. When the Spreadsheet is not found, a new Spreadsheet is created by converting the XLSX file.
Reference:
Files: update

Related

Appscript - Multiple excel files conversion to gsheets and updating data without creating a new gsheet

sorry for bad english.
I have a folder with multiple excel files that I need in Gsheets format. I also need to update the data (converting the same file again and again), but the output must remain the same. (the GSHEET id for example).
I actually have this code but this works for 1 xlsx file.
function importData() {
var xlsxName = "QM12.XLSX"; //Change source file name accordingly
var convertID = convert(xlsxName).toString();
var xLSX = SpreadsheetApp.openById(convertID).getSheetByName("Sheet1"); // SaĆ­da
var ss = SpreadsheetApp.openById("15GvvEYH8zuHI6cmhNxHqBWywrqQU32t6kaAbAJcclBk").getSheetByName("QM12 CGH"); // entrada
var lastColumn = xLSX.getLastColumn();
var lastRow = xLSX.getLastRow();
ss.getRange(1, 1, lastRow, lastColumn).setValues(xLSX.getDataRange().getValues()); //Sets values from converted xlsx data to output sheet
//DriveApp.getFileById(convertID).setTrashed(true); //deletes temporary file
Drive.Files.remove(convertID)
}
function convert(xlsxName) {
var files = DriveApp.getFilesByName("xlsxName");
var excelFile = (files.hasNext()) ? files.next() : null;
var blob = excelFile.getBlob();
var config = {
title: "[Converted File] " + excelFile.getName(), //sets the title of the converted file
parents: [{ id: excelFile.getParents().next().getId() }],
mimeType: MimeType.GOOGLE_SHEETS
};
var spreadsheet = Drive.Files.insert(config, blob);
return (spreadsheet.id); //Returns the ID of the converted file
}
I would like to use this for multiple xlsx.
Basically I need to:
-> FolderA with xlsx files. FolderB as the destination for the gsheets converted files.
-> If there is no gsheet with the same name as the xlsx file, it should create a new gsheet but if there it is a gsheet with the same name, just update the data on it.
I've been searching but couldn't find anything close to this.
Anyway, thank you in advance.

Is it possible to save an excel attachment as a "proper" google sheet file? [duplicate]

I know it is possible to convert excel files to Google Sheets using script and drive API, but I'm looking for script to convert the excel sheet and move the converted file to a different folder.
So the required steps are as follows:
Convert excel (.xls/.xlsx) to Google Sheet from FolderA.
Move converted file from FoldarA to FolderB.
Delete original excel file from FolderA
Hopefully step 3 avoids this, but avoid duplicating already converted file.
The excel files are being pasted into a local folder that is being synced to google drive, and the files are no larger than 3mb. The current script is as follows. This is converting the files but placing them in the root folder, and will duplicate the conversion when the script runs again.
function importXLS(){
var files = DriveApp.getFolderById('1hjvNIPgKhp2ZKIC7K2kxvJjfIeEYw4BP').searchFiles('title != "nothing"');
while(files.hasNext()){
var xFile = files.next();
var name = xFile.getName();
if (name.indexOf('.xlsx')>-1){
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = { title : name+'_converted',
key : ID
}
file = Drive.Files.insert(newFile, xBlob, {
convert: true
});
}
}
}
You want to create the converted Google Spreadsheet files to "FolderB".
You want to delete the XLSX files in "FolderA" after the files were converted.
You want to achieve above using Google Apps Script.
If my understanding correct, how about this modification? In this modification, I modified your script.
Modification points:
You can directly create the file to the specific folder using the property of parents in the request body.
You can delete the file using Drive.Files.remove(fileId).
Modified script:
Before you use this script, please enable Drive API at Advanced Google services.
function importXLS(){
var folderBId = "###"; // Added // Please set the folder ID of "FolderB".
var files = DriveApp.getFolderById('1hjvNIPgKhp2ZKIC7K2kxvJjfIeEYw4BP').searchFiles('title != "nothing"');
while(files.hasNext()){
var xFile = files.next();
var name = xFile.getName();
if (name.indexOf('.xlsx')>-1){
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = {
title : name+'_converted',
parents: [{id: folderBId}] // Added
};
file = Drive.Files.insert(newFile, xBlob, {
convert: true
});
// Drive.Files.remove(ID); // Added // If this line is run, the original XLSX file is removed. So please be careful this.
}
}
}
Note:
If the number of XLSX files is large, the execution time might be over 6 minutes.
About // Drive.Files.remove(ID);, when you run this script, please be careful. Because the original XLSX files are completely deleted when the script is run. So I commented this. At first, please test the script using sample files.
References:
Files: insert
Files: delete

Save gmail attachment as google sheets in gdrive [duplicate]

I know it is possible to convert excel files to Google Sheets using script and drive API, but I'm looking for script to convert the excel sheet and move the converted file to a different folder.
So the required steps are as follows:
Convert excel (.xls/.xlsx) to Google Sheet from FolderA.
Move converted file from FoldarA to FolderB.
Delete original excel file from FolderA
Hopefully step 3 avoids this, but avoid duplicating already converted file.
The excel files are being pasted into a local folder that is being synced to google drive, and the files are no larger than 3mb. The current script is as follows. This is converting the files but placing them in the root folder, and will duplicate the conversion when the script runs again.
function importXLS(){
var files = DriveApp.getFolderById('1hjvNIPgKhp2ZKIC7K2kxvJjfIeEYw4BP').searchFiles('title != "nothing"');
while(files.hasNext()){
var xFile = files.next();
var name = xFile.getName();
if (name.indexOf('.xlsx')>-1){
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = { title : name+'_converted',
key : ID
}
file = Drive.Files.insert(newFile, xBlob, {
convert: true
});
}
}
}
You want to create the converted Google Spreadsheet files to "FolderB".
You want to delete the XLSX files in "FolderA" after the files were converted.
You want to achieve above using Google Apps Script.
If my understanding correct, how about this modification? In this modification, I modified your script.
Modification points:
You can directly create the file to the specific folder using the property of parents in the request body.
You can delete the file using Drive.Files.remove(fileId).
Modified script:
Before you use this script, please enable Drive API at Advanced Google services.
function importXLS(){
var folderBId = "###"; // Added // Please set the folder ID of "FolderB".
var files = DriveApp.getFolderById('1hjvNIPgKhp2ZKIC7K2kxvJjfIeEYw4BP').searchFiles('title != "nothing"');
while(files.hasNext()){
var xFile = files.next();
var name = xFile.getName();
if (name.indexOf('.xlsx')>-1){
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = {
title : name+'_converted',
parents: [{id: folderBId}] // Added
};
file = Drive.Files.insert(newFile, xBlob, {
convert: true
});
// Drive.Files.remove(ID); // Added // If this line is run, the original XLSX file is removed. So please be careful this.
}
}
}
Note:
If the number of XLSX files is large, the execution time might be over 6 minutes.
About // Drive.Files.remove(ID);, when you run this script, please be careful. Because the original XLSX files are completely deleted when the script is run. So I commented this. At first, please test the script using sample files.
References:
Files: insert
Files: delete

Converting Excel to Gsheet and then importrange them without needing Auth

I receive files in .xlsx which is updated about daily. To use the importrange function I need to have the xlsx file converted to gSheet. I've completed the conversion as per drive API
function importXLS(){
var folderBId = "redacted"; // This is the folder where we will save the gsheet converted files
fileID = SpreadsheetApp.getActiveSpreadsheet().getRangeByName("DataFile").getValue();
var xFile = DriveApp.getFileById(fileID);
var name = xFile.getName();
if (name.indexOf('.xlsx')>-1){
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = {
title : name+'_converted',
parents: [{id: folderBId}] // Added
};
file = Drive.Files.insert(newFile, xBlob, {
convert: true
});
SpreadsheetApp.getActiveSpreadsheet().getRangeByName("GDatafile").setValue(file.id); // **Notes below**
// Drive.Files.remove(ID); // Added // If this line is run, the original XLSX file is removed. So please be careful this.
}
So I save the new gSheet ID in my spreadsheet so I can use importrange to import it. But because it's a new gsheet file for every update, and not an overwritten version of the old one, I need to explicitly give access to the file. The point here is to automate, and having to click "allow" for every time you access it is not ideal.
Can I somehow (since I have the fileID at my disposal here anyway, and the spreadsheet that will want to access it) allow access right there? Or is there a way that I can set up this 'converting' code to overwrite the old gsheet (so that I only have to allow access once).
This worked for me:
function importXLS(){
var folderBId = "redacted"; // This is the folder where we will save the gsheet converted files
fileID = SpreadsheetApp.getActiveSpreadsheet().getRangeByName("DataFile").getValue();
var xFile = DriveApp.getFileById(fileID);
var name = xFile.getName();
if (name.indexOf('.xlsx')>-1){
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = {
title : name+'_gsheet',
parents: [{id: folderBId}]
};
var GDataFile = SpreadsheetApp.getActiveSpreadsheet().getRangeByName("GDatafile").getValue();
if (GDataFile == "" ){
file = Drive.Files.insert(newFile, xBlob, {
convert: true
})
Logger.log("New File Created: " + file.id);
SpreadsheetApp.getActiveSpreadsheet().getRangeByName("GDatafile").setValue(file.id);
}
else{
file = Drive.Files.update(newFile,GDataFile,xBlob); // <--- this is the update code
Logger.log("File in theory updated... " + GDataFile);
}
// Drive.Files.remove(ID); // Added // If this line is run, the original XLSX file is removed. So please be careful this.
}
}

Converting all files in drive folder from sheets to CSV and add to new folder

I have:
.xlsx files being automatically imported on a daily basis to a google drive folder
I want:
each file converted to a CSV and saved to a different folder
each file converted to a Google Sheet and saved to a different folder
the original xlsx file deleted once done processing
Currently my process is this:
Convert xlsx to 2 new files: CSV & Google Sheet
Save CSVs to CSV Folder
Save Google Sheets to Sheets folder
I was originally using this https://ctrlq.org/code/20248-convert-excel-to-csv tutorial to convert to CSV until I realized it saved an "Untitled" copy of each .xlsx sheet as Drive spreadsheet to my root folder. I could not figure out how to assign a title or folder location to those untitled. Being able to do that would also fix my immediate problem.
Then I attempted using a modified version of this (below) https://ctrlq.org/code/20500-convert-microsoft-excel-xlsx-to-google-spreadsheet with the MimeType .CSV which correctly placed my CSV's in the right folder with the right name, but the data wasn't parsed correctly and looked corrupted.
function exceltoSheets() {
var SOURCE_XLS_FOLDER = '123465';
var SHEET_FOLDER = '789456';
var CSV_TEST = '456123';
var sourceFolderID = DriveApp.getFolderById(SOURCE_XLS_FOLDER),
mimes = [MimeType.MICROSOFT_EXCEL, MimeType.MICROSOFT_EXCEL_LEGACY];
for (var m = 0; m < mimes.length; m++) {
var sourceFiles = sourceFolderID.getFilesByType(mimes[m]);
while (sourceFiles.hasNext()) {
try {
var sourceFile = sourceFiles.next();
var sourceName = sourceFile.getName().replace(".xlsx","");
var sourceNameTC = sourceName + ".csv"
var sourceNameDS = "ds_data_import_" + sourceName;
var fileId = sourceFile.getId();
var blob = sourceFile.getBlob();
var resourceDS = {
title: sourceNameDS,
mimeType: MimeType.GOOGLE_SHEETS,
convert: true,
parents: [{id: SHEET_FOLDER}]
};
var resourceTC = {
title: sourceNameTC,
mimeType: MimeType.CSV,
convert: true,
parents: [{id: CSV_TEST}],
};
Drive.Files.insert(resourceDS, blob);
Drive.Files.insert(resourceTC, blob);
} catch (f) {
Logger.log(f.toString());
}
sourceFile.setTrashed(true);
}
}
}
If I parse the CSVs correctly I end up with Untitled sheets in my root folder, if I parse the Sheets correctly I end up with corrupted CSVs. I want the result:
xlsx converted to CSV in designated folder
xlsx converted to Google Sheet in designated folder
xlsx deleted off drive once processing complete
You want to convert XLSX files in the specific folder to Google Spreadsheet.
You want to put the converted Spreadsheet to the specific folder.
You want to achieve this by modifying your script.
If my understanding is correct, how about this modification? Please think of this as just one of several answers.
Modification points:
In order to retrieve the files of MimeType.MICROSOFT_EXCEL and MimeType.MICROSOFT_EXCEL_LEGACY, I used searchFiles().
In order to convert from XLSX file to Google Spreadsheet and put it to the specific folder, I used Drive.Files.copy().
Modified script:
When you use this, please confirm whether Drive API is enabled at Advanced Google services.
function exceltoSheets() {
var SOURCE_XLS_FOLDER = '###'; // Please set the source folder ID here.
var dstFolderId = '####'; // Please set the destination folder ID here.
var sourceFolderID = DriveApp.getFolderById(SOURCE_XLS_FOLDER);
var searchQuery = "mimeType='" + MimeType.MICROSOFT_EXCEL + "' or mimeType='" + MimeType.MICROSOFT_EXCEL_LEGACY + "'";
var sourceFiles = sourceFolderID.searchFiles(searchQuery);
while (sourceFiles.hasNext()) {
var sourceFile = sourceFiles.next();
var fileId = sourceFile.getId();
Drive.Files.copy({mimeType: MimeType.GOOGLE_SHEETS, parents: [{id: dstFolderId}]}, fileId);
sourceFile.setTrashed(true);
}
}
Note:
If you want to directly delete the XLSX file, you can use Drive.Files.remove(fileId) instead of sourceFile.setTrashed(true).
References:
searchFiles()
Files: copy
Advanced Google services
Edit:
You want to convert from XLSX files to CSV and Google Spreadsheet files.
You want to put the converted XLSX files and CSV files to each folder.
For this situation, the modified script is as follows.
function exceltoSheets() {
var SOURCE_XLS_FOLDER = '###'; // Please set the source folder ID here.
var dstFolderIdForSpreadsheet = '###'; // Please set the destination folder ID for Spreadsheet here.
var dstFolderIdForCSV = '###'; // Please set the destination folder ID for CSV here.
var sourceFolder = DriveApp.getFolderById(SOURCE_XLS_FOLDER);
var destinationFolderForCSV = DriveApp.getFolderById(dstFolderIdForCSV);
var searchQuery = "mimeType='" + MimeType.MICROSOFT_EXCEL + "' or mimeType='" + MimeType.MICROSOFT_EXCEL_LEGACY + "'";
var sourceFiles = sourceFolder.searchFiles(searchQuery);
while (sourceFiles.hasNext()) {
var sourceFile = sourceFiles.next();
var fileId = sourceFile.getId();
var spreadsheet = Drive.Files.copy({mimeType: MimeType.GOOGLE_SHEETS, parents: [{id: dstFolderIdForSpreadsheet}]}, fileId);
var sheets = SpreadsheetApp.openById(spreadsheet.id).getSheets();
sheets[0].getDataRange().getValues()
var csv = sheets.map(function(sheet) {return sheet.getDataRange().getValues().reduce(function(csv, row) {return csv += row.join(",") + "\n"}, "")});
destinationFolderForCSV.createFile(spreadsheet.title + ".csv", csv, MimeType.CSV)
sourceFile.setTrashed(true);
}
}