Converting from word document to native google doc - google-apps-script

So I have some 2000 word documents I can generate with c#, however, I need them uploaded to google docs, in the native google docs format.
I looked at This guide to try to convert them, however, the code fails on the second to last line.
(My code below)
function myFunction() {
var folder = DriveApp.getFoldersByName("test").next();
var contents = folder.getFiles();
while (contents.hasNext()){
var file = contents.next();
var fileName = file.getName();
var officeFile = DriveApp.getFilesByName(fileName).next();
// Use the Advanced Drive API to upload the Excel file to Drive
// convert = true will convert the file to the corresponding Google Docs format
var uploadFile = JSON.parse(UrlFetchApp.fetch(
"https://www.googleapis.com/upload/drive/v2/files?uploadType=media&convert=true",
{
method: "POST",
contentType: officeFile.getMimeType(),
payload: officeFile.getBlob().getBytes(),
headers: {
"Authorization" : "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true
}
).getContentText());
// Remove the file extension from the original file name
var fileName2 = officeFile.getName();
fileName2 = fileName2.substr(0, fileName2.lastIndexOf("."));
// Update the name of the Google Sheet created from the Excel sheet
DriveApp.getFileById(uploadFile.getID()).setName(fileName2); // FAILS HERE
//Logger.log(uploadFile.alternateLink);
}}
TypeError: Cannot find function getID in object [object Object]. (line 33, file "Code")
I understand what kind of error this is, however, I do not necessarily know how to solve it.

You don't need any UrlFetchApp manipulations. The Advanced Drive Service provides conversion as a part of copy method. Takes two lines of code:
var fileId = 'ID_of_Word_file';
Drive.Files.copy({}, fileId, {'convert': true});
You will need to enable this service in the scropt menu: see Resources > Advanced Services.
If iterating through a folder, get each file from file iterator with .next() and use getId() to get its id; the proceed as above.
The empty object in the first argument can be used to name the new file: e.g., it could be {'title': 'Name of new file'}

Related

How can i REPLACE a file with another file (if their name is the same) using 'Trash' ing in Google App Script?

I am accessing a list of folders from a shared drive.
In here, I am converting a few excel files into spreadsheet. My issue is to replace the old converted files with the new file. This is because every time i run the script the new converted file(with same name) keeps on multiplying in the same folder together with the old one.
Here is the code:
function ConvertFiles() {
var sheet =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var r= 2;
for(r= 2;r < sheet.getLastRow(); r++){
// Use getValue instead of getValues
var fileId = sheet.getRange(r,1).getValue();
var folderID = sheet.getRange(r,8).getValue();
var files = DriveApp.getFileById(fileId);
var name = files.getName().split('.')[0];
var blob = files.getBlob();
var newFile = {
// Remove '_converted' from name if existing to avoid duplication of the string before adding '_converted'
// This will allow to have newly converted file "replace" the old converted file properly
title: name.replace('_converted','') + '_converted',
parents: [{
id: folderID
}]
};
var destinationFolderId = DriveApp.getFolderById(folderID);
var existingFiles = destinationFolderId.getFilesByName(newFile.title);
// GOAL #1: To replace/update the old converted file into the latest one everytime the script runs (if it has the same filename)
// Find the file with same name of the file to be converted
while(existingFiles.hasNext()) {
// ID of the file with same converted name
var oldConvertedFileWithSameNameID = existingFiles.next().getId();
// Delete before writing
Drive.Files.remove(oldConvertedFileWithSameNameID);
//DriveApp.getFileById(oldConvertedFileWithSameNameID.getId()).setTrashed(true);
}
// Create new converted file then get ID
var newFileID = Drive.Files.insert(newFile, blob, { convert: true,supportsAllDrives: true }).id;
Logger.log(newFileID);
//var sheetFileID = newFileID.getId();
//var Url = "https://drive.google.com/open?id=" + sheetFileID;
var Url = "https://drive.google.com/open?id=" + newFileID;
// Add the ID of the converted file
sheet.getRange(r,9).setValue(newFileID);
sheet.getRange(r,10).setValue(Url);
}
}
My goal is
To replace the old converted file with the new one(if they have the same name) into the shared drive folder
To get to know how can i implement the setTrashed() inside the above code
I have tried using the Drive.Files.remove(oldConvertedFileWithSameNameID); but I am getting an error message GoogleJsonResponseException: API call to drive.files.delete failed with error: File not found:("fileid"). Then i saw an question on this [https://stackoverflow.com/questions/55150681/delete-files-via-drive-api-failed-with-error-insufficient-permissions-for-this]...so i guess that method is not suitable to implemented in shared folder.
So i how can i use setTrashed() method inside the above code?
I think you need to set the supportsAllDrives parameter:
Drive.Files.remove(oldConvertedFileWithSameNameID, {supportsAllDrives: true});
References:
Files:delete | Google Drive API | Google Developers - Parameters

Google Apps Script - XLSX from E-mail to specific Google Sheet

I'm getting an e-mail daily with an XLSX file that I need to then export over to a specific Google Sheet.
The code simply searches the GMAIL for a specific query, where it then gets the body (which contains a URL), which it then downloads with the doGet function, that uses the Url.FetchApp.fetch(url).getBlob()
After that, using the variable fileInfo, it defines, the title, mimeType of the file and the "parents" which is the ID of the folder where I need to deposit the converted file.
Then, I insert the file with the Drive.Files.insert(fileInfo, file, {convert: true}) which should convert my Excel file and deposit it in my folder.
The export works (a file is exported). If I append a .xlsx extension manually and try to open in Excel,it opens perfectly with all the required information.
But, the issue is that I don't need to open in an Excel file, so I'm trying to export it to a Google Sheet or even parse it as a CSV, but it doesn't work.
When trying to open this exported file by ID, it says that it is missing or don't have permissions, but it is there and I do have permissions.
When checking the mime type of the file, it says "application/x-zip".
Is there anyway for me to upload the file data to my Google Sheet with the ID "1HMXgJuuRFaGK11sfR38mKh6rk4ta_Qgtlljk6HBjLkE"?
function CostDSP() {
var sheetId="1HMXgJuuRFaGK11sfR38mKh6rk4ta_Qgtlljk6HBjLkE";
var threads = GmailApp.search("from:no-reply#amazon.com subject:Cost - DSP in:inbox newer_than:1d");
var message = threads[0].getMessages()[0];
var attachment = message.getPlainBody();
var regex= new RegExp("\<(.*)\>");
var url=regex.exec(attachment)[1];
Logger.log(url);
var file=doGet(url);
var fileInfo = {
title: "Cost - DSP",
mimeType: "MICROSOFT_EXCEL",
"parents": [{'id': "19jrt0DyfvsDz5WAdKhkekHkJ_wP7qP7f"}],
};
Drive.Files.insert(fileInfo, file, {convert: true});
var sourceFile = DriveApp.getFilesByName("Cost - DSP").next();
Logger.log(sourceFile.getMimeType());
Logger.log(sourceFile);
var source=SpreadsheetApp.openById("1lIVb9YM9IK7f8dKuC1RpXjP7nLnMNXm1");
var sheet = sourceFile.getSheets()[0];
var destination = SpreadsheetApp.openById("1HMXgJuuRFaGK11sfR38mKh6rk4ta_Qgtlljk6HBjLkE").getSheetByName('Data Intake');
sheet.copyTo(destination);
}
function doGet(e) {
// e.parameter["file"] //returns ?file=filelink.com/file.xlsx
var file = UrlFetchApp.fetch(e).getBlob();
return file;
}
It seems you need to use the correct mime type for import
mimeType:
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
The next code works fine for me
var file = UrlFetchApp.fetch(
'https://ec.europa.eu/eurostat/statistics-explained/images/9/9f/Country_Codes_and_Names.xlsx'
);
var fileInfo = {
title: 'Cost - DSP',
mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
parents: [{
id: 'root'
}],
};
Drive.Files.insert(fileInfo, file, {
convert: true
})
As #Raserhin said it works without the mimeType parameter.
var fileInfo = {
title: 'Cost - DSP',
// mimeType:
// 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
parents: [{ id: 'root' }],
}
;
Also you can't use doGet as you're using now. doGet is a reserved function.
Turns out I also had to set the mimetype in the doGet function to the xlsx mimetype for it to work.
As an optimization I also removed the mimetype specification in the file info variable.
I'm managing to use this doGet function despite it being reserved, so I guess I'll stick to it for now?
As for calling the drive api directly, I need to use the advanced service to be able to convert the xlsx file.

Google Script - How to use unzip

I am downloading a .zip from a website. It contains one .txt file. I would like to access the data in the txt and write it to a spreadsheet. I'm open to either accessing it directly and not extracting the zip OR extracting the zip, saving the txt to a Google Drive Folder, and accessing it once it is saved.
When I use Utilities.unzip(), I can never get it to unzip the file and usually end up with an "Invalid argument" error. In the code below, the last section before else contains the unzip command. It successfully saves the file to the correct Google Folder but then I can't extract it.
function myFunction() {
// define where to gather data from
var url = '<insert url here>';
var filename = "ReportUploadTesting05.zip";
var response = UrlFetchApp.fetch(url, {
// muteHttpExceptions: true,
// validateHttpsCertificates: false,
followRedirects: true // Default is true anyway.
});
// get spreadsheet for follow up info
var Sp = SpreadsheetApp.getActiveSpreadsheet();
if (response.getResponseCode() === 200) {
// get folder details of spreadsheet for saving future files
var folderURL = getParentFolder(Sp);
var folderID = getIdFromUrl(folderURL);
var folder = DriveApp.getFolderById(folderID);
// save zip file
var blob = response.getBlob();
var file = folder.createFile(blob);
file.setName(filename);
file.setDescription("Downloaded from " + url);
var fileID = file.getId();
Logger.log(fileID);
Logger.log(blob)
// extract zip (not working)
file.setContent('application/zip')
var fileUnzippedBlob = Utilities.unzip(file); // invalid argument error occurs here
var filename = 'unzipped file'
var fileUnzipped = folder.createFile(fileUnzippedBlob)
fileUnzipped.setName(filename)
}
else {
Logger.log(response.getResponseCode());
}
}
I've followed the instructions on the Utilities page. I can get their exact example to work. I've tried creating a .zip on my computer, uploading it to Google Drive and attempted to open it unsuccessfully. Obviously there are some subtleties of using the unzip that I'm missing.
Could you help me understand this?
I was running into the same "Invalid arguments" error in my testing, so instead of using:
file.setContent('application/zip')
I used:
file.setContentTypeFromExtension();
And, that solved the problem for me. Also, as #tukusejssirs mentioned, a zip file can contain multiple files, so unzip() returns an array of blobs (as documented here). That means you either need to loop through the files, or if you know you only have one, explicitly reference it's position in the array, like this:
var fileUnzipped = folder.createFile(fileUnzippedBlob[0])
Here's my entire script, which covers both of these issues:
/**
* Fetches a zip file from a URL, unzips it, then uploads a new file to the user's Drive.
*/
function uploadFile() {
var url = '<url goes here>';
var zip = UrlFetchApp.fetch('url').getBlob();
zip.setContentTypeFromExtension();
var unzippedFile = Utilities.unzip(zip);
var filename = unzippedFile[0].getName();
var contentType = unzippedFile[0].getContentType();
var csv = unzippedFile[0];
var file = {
title: filename,
mimeType: contentType
};
file = Drive.Files.insert(file, csv);
Logger.log('ID: %s, File size (bytes): %s', file.id, file.fileSize);
var fileId = file.id;
// Move the file to a specific folder within Drive (Link: https://drive.google.com/drive/folders/<folderId>)
var folderId = '<folderId>';
var folder = DriveApp.getFolderById(folderId);
var driveFile = DriveApp.getFileById(fileId);
folder.addFile(driveFile);
}
I think the answer to your question may be found here. Is there a size limit to a blob for Utilities.unzip(blob) in Google Apps Script?
If the download is over 100 mb the full file cannot be downloaded. Due to that it will not be in the proper zip format. Throwing the cannot unzip file error.
I believe that the creation of the blob from a file (in this case the .zip file) requires the .next(); otherwise it did not work for me.
Also note that the .zip file might contain more than one file, therefore I included a for cycle.
Anyway, my working/tested solution/script is the following:
function unzip(folderName, fileZipName){
// Variables
// var folderName = "folder_name";
// var fileZipName = "file_name.zip";
var folderId = getFolderId(folderName);
var folder = DriveApp.getFolderById(folderId);
var fileZip = folder.getFilesByName(fileZipName);
var fileExtractedBlob, fileZipBlob, i;
// Decompression
fileZipBlob = fileZip.next().getBlob();
fileZipBlob.setContentType("application/zip");
fileExtractedBlob = Utilities.unzip(fileZipBlob);
for (i=0; i < fileExtractedBlob.length; i++){
folder.createFile(fileExtractedBlob[i]);
}
}

Google Apps Script returns file from drive as application/pdf instead of original filetype

When running my script I get the error Converting from application/pdf to application/vnd.google-apps.spreadsheet is not supported. (line 6, file "Code")
The original file is no PDF but an excel worksheet. I tried different file with different types and every file returned as PDF.
Here is my code:
function sendTimelist() {
var emailAddress = 'some#mail.com';
var mailReplyTo = 'somemore#mail.com';
var subject = 'Timelist';
var message = 'Here is my timelist!';
var timelist = SpreadsheetApp.openById("1v7EShuCrjrEa8BxW2JGCRDUwuIsUk03fnvvYEVntlvM").getAs(MimeType.GOOGLE_SHEETS);
var optAdvancedArgs = {replyTo: mailReplyTo, name: attachmentName, attachments: [timelist] };
var attachmentName = 'Timelist.xlsx';
GmailApp.sendEmail(emailAddress, subject, message, optAdvancedArgs);
}
What am I missing?
I focused on the length of your file ID. Your file ID is 1v7EShuCrjrEa8BxW2JGCRDUwuIsUk03fnvvYEVntlvM. The length is 44. In the case of Excel file in Google Drive, the length of ID is 28. And the case of Google Docs (Spreadsheet, Document, Slide), the length of ID is 44.
When Google Docs files are downloaded without the assignment of export format, the format automatically becomes PDF.
I thought that you might try to send Spreadsheet of Google Docs. In order to confirm this, can you try to run a following script?
var id = "1v7EShuCrjrEa8BxW2JGCRDUwuIsUk03fnvvYEVntlvM";
Logger.log(DriveApp.getFileById(id).getMimeType());
If the log shows application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, the file is Excel file. If the log shows application/vnd.google-apps.spreadsheet, the file is Spreadsheet file.
In the case of Excel file, when the file is sent as an attachment file of gmail, it is not converted. Excel file can be sent. In the case of Spreadsheet file, it is converted to PDF and sent as an attachment file.
If your file was a Spreadsheet file, in order to send it as Excel file, you can use the following sample script.
Sample script :
function sendTimelist() {
var emailAddress = 'some#mail.com';
var mailReplyTo = 'somemore#mail.com';
var subject = 'Timelist';
var message = 'Here is my timelist!';
var attachmentName = 'Timelist.xlsx';
var fileId = "1v7EShuCrjrEa8BxW2JGCRDUwuIsUk03fnvvYEVntlvM";
var timelist = UrlFetchApp.fetch(
"https://docs.google.com/feeds/download/spreadsheets/Export?key=" + fileId + "&exportFormat=xlsx",
{
"headers": {Authorization: "Bearer " + ScriptApp.getOAuthToken()},
"muteHttpExceptions": true
}
).getBlob().setName(attachmentName);
var optAdvancedArgs = {replyTo: mailReplyTo, name: attachmentName, attachments: [timelist] };
GmailApp.sendEmail(emailAddress, subject, message, optAdvancedArgs);
}
If I misunderstand your situation, I'm sorry.
I think the source of the problem is using SpreadsheetApp to open the file. To preserve original data type, open it as DriveApp.getFileById(...) which returns a File object. You shouldn't need getAs either.

Add convert xls to Google sheets feature to function of download

I have working code for download any file in google docs by link. Most of files in xlx or xlsx format and need to be convert in google sheets type. Ive been tried to use some methods, that I find in Internet, but they dont work for me. In code below, I comment with code wich I test. And I guess, that google had changed some documentation
function downloadFile(fileURL,folder) {
var fileName = "";
var fileSize = 0;
var fileId = "";
var response = UrlFetchApp.fetch(fileURL, {muteHttpExceptions: true});
var rc = response.getResponseCode();
if (rc == 200) {
var fileBlob = response.getBlob() //.getAs(MimeType.GOOGLE_SHEETS) - get error
var folder = DriveApp.getFolderById(folder);
if (folder != null) {
var file = folder.createFile(fileBlob);//.getAs(MimeType.GOOGLE_SHEETS) - get error
fileName = file.getName();
fileSize = file.getSize();
fileId = file.getId();
}
}
//file.setMimeType("application/vnd.google-apps.spreadsheet") - not work
//makeCopy('ssssss', folder, {convert: true}) - get error
var fileInfo = [ rc, fileName, fileSize, fileId ];
return fileInfo;
}
I call function like this:
downloadFile("http://www.beltools.ru/prais_rar/price%20TD%20RI.xls","0B_E2P3ZhQySBY3BBMzdlazBLcTA")
In order to convert Excel to Spreadsheet, DriveApp cannot do it. So Drive API has to be used. You can use Drive API v2 from Advanced Google services. "Drive API v2" can be used at Google Apps Script by enabling Drive API of Advanced Google services and of Google API Console.
How to use it is as follows.
In the script editor, select Resources > Advanced Google services
In the dialog that appears, click the on/off switch for Drive API v2.
At the bottom of the dialog, click the link for the Google API Console.
In the console, click into the filter box and type part of the name of the API "Drive API", then click the name once you see it.
On the next screen, click Enable API.
Close the Developers Console and return to the script editor. Click OK in the dialog. The advanced service you enabled is now available in autocomplete.
The detail information is https://developers.google.com/apps-script/guides/services/advanced.
At the sample script, at first, a file is downloaded by fileURL, which is Excel file, as blob. The blob data is uploaded to Google Drive using Drive API. In this case, access token is not required. For downloadFile(), the Input data and output data are same to your downloadFile(). File name is retrieved from fileURL.
Script :
function downloadFile(fileURL, folder) {
var filename = fileURL.match(".+/(.+?)([\?#;].*)?$")[1];
var response = UrlFetchApp.fetch(fileURL);
var rc = response.getResponseCode();
var blob = response.getBlob();
var resource = {
"mimeType": "application/vnd.google-apps.spreadsheet",
"parents": [{id: folder}],
"title": filename
};
var res = Drive.Files.insert(resource, blob);
var fileInfo = [rc, res.title, blob.getBytes().length, res.id];
return fileInfo;
}
Result :
[
200,
sample.xlsx,
10000.0,
## file id ##
]
If I misunderstand your question, I'm sorry.