Converting spreadsheet into microsoft excel using Google Apps, but not working - google-apps-script

Used below code to convert spreadsheet into xlsx.
Though looks to be working fine, But doesn't works same as Microsoft Excel. Looking help on alternative to convert spreadsheet into microsoft xlsx file or Blob.
Objective:
I have an API that accepts only Microsoft .xlsx with data available in Google Spreadsheet; and hence trying to convert spreadsheet into Microsoft xlsx.
My Code:
function exportToXlsx(){
var fileId = "{{fileID_of_spreadsheet}}";
var targetFolderID = "{{target_folderID}}";
Logger.log("Input File ID: " + fileId);
try {
var url = "https://docs.google.com/feeds/download/spreadsheets/Export?key=" + fileId + "&exportFormat=xlsx";
var params = {
method : "get",
headers : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
};
var blob = UrlFetchApp.fetch(url, params).getBlob();
//set name to blob
blob.setName(DriveApp.getFileById(fileId).getName() + ".xlsx");
//create the xlsx file
var newFile = DriveApp.createFile(blob);
} catch (f) {
Logger.log(f.toString());
}
}

Related

Get the blob of a drive file using Drive api

I used below script to get the blob of abc.dat file which is generated via my Apps Script project. With the Drive service, it is easy.
Used oauthScope is https://www.googleapis.com/auth/drive.readonly
function ReadData() {
var files;
var folders = DriveApp.getFoldersByName("Holder");
if (folders.hasNext()) {
var folder = folders.next();
var files = folder.getFiles();
while (files.hasNext()){
file = files.next();
if(file.getName()=='abc.dat'){
var content = file.getBlob().getDataAsString();
return content;
}
}
}
return '';
}
In order to reduce the authentication scope, Now I am modifying the code to fully remove the https://www.googleapis.com/auth/drive.readonly oauthScope and use only the https://www.googleapis.com/auth/drive.file oauthScope.
Using the Drive api, I didn't found a direct way to get the blob of a file.
I used this below script to get the blob of a word document file. But it is not working for the .dat file with error fileNotExportable, Export only supports Docs Editors files, code 403
function getBlob(fileID, format){
var url = "https://www.googleapis.com/drive/v3/files/" + fileID + "/export?mimeType="+ format;
var blob = UrlFetchApp.fetch(url, {
method: "get",
headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
}).getBlob();
return blob;
}
Found this article and tried changing the export with get in the url. The returning blob.getDataAsString() gives "Not found" now.
The mimeType I used when creating the abc.dat file is application/octet-stream .dat. But when check the generated file, its mimeType is text/plain. So I used the 'text/plain' as the input for 'format' parameter in getBlob function.
.dat file creation code :
var connectionsFile = {
title: filename,
mimetype: "application/octet-stream .dat",
parents: [{'id':folder.getId()}],
};
var blobData = Utilities.newBlob(contents);
file = Drive.Files.insert(connectionsFile,blobData);
}
How can I modify this code to get the blob from the file? or is there any other way around?
Thanks in advance!
I think that in your situation, it is required to use get method instead of export method. Because export method is used for Google Docs files (Document, Spreadsheet, Slides and so on). When your script is modified, how about the following modification?
Modified script:
function getBlob(fileID) {
var url = "https://www.googleapis.com/drive/v3/files/" + fileID + "?alt=media";
var blob = UrlFetchApp.fetch(url, {
method: "get",
headers: { "Authorization": "Bearer " + ScriptApp.getOAuthToken() },
muteHttpExceptions: true
}).getBlob();
return blob;
}
Reference:
Download files

Export Google Sheet as .xlsx and send file to server

My company manages non-confidential information in a Google Sheet. Every day, I export that sheet to .xlsx format and then upload it to various services for data syndication.
Normally, such a process could be automated using the "Publish to Web" feature. But for security reasons, that option is locked for all users.
I do have full permissions for Google Apps Script, though. So, I'd like to write a script for this. The particulars don't matter. Somehow, I need to export the sheet on a schedule and send it to an AWS server, where it can be automatically retrieved.
At the AWS side, I can easily set up an email server, FTP server, rclone, whatever. I just need to figure out what to do on the Google side first.
Can this be done?
What I have tried so far:
Export a Google Sheet to Google Drive in Excel format with Apps Script
function makeCopy() {
var formattedDate = Utilities.formatDate(new Date(), "CET", "yyyy-MM-dd' 'HH:mm");
var name = "Backup Copy " + formattedDate;
var destination = DriveApp.getFolderById("1vFL98cgKdMHLNLSc542pUt4FMRTthUvL");
// Added
var sheetId = "2SqIXLiic6-gjI2KwQ6OIgb-erbl3xqzohRgE06bfj2c";
var url = "https://docs.google.com/spreadsheets/d/" + sheetId + "/export?format=xlsx&access_token=" + ScriptApp.getOAuthToken();
var blob = UrlFetchApp.fetch(url).getBlob().setName(name + ".xlsx"); // Modified
destination.createFile(blob);
}
--- OR ---
function convertSheetToXLSX() {
var sheetId = "2SqIXLiic6-gjI2KwQ6OIgb-erbl3xqzohRgE06bfj2c";
var spreadsheetName = "My Spreadsheet";
var destination = DriveApp.getFolderById("1vFL98cgKdMHLNLSc542pUt4FMRTthUvL");
var url = "https://docs.google.com/feeds/download/spreadsheets/Export?key=" + sheetId + "&exportFormat=xlsx";
var params = {
method : "get",
headers : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
};
var blob = UrlFetchApp.fetch(url, params).getBlob();
blob.setName(spreadsheetName + ".xlsx");
destination.createFile(blob);
}
I have tried these scripts from the URL posted above but it results in "An unknown error has occurred, please try again later."
Take a look at this thread. It is about sending a spreadsheet in PDF format, but if you just change the ExportOptions to xlsx, you should be able to make it.

documentapp.getactivedocument().getBlob gives pdf

i am trying to send the google document's content to my backend service.
In the app script i am using
if(host == 'sheets'){
var content = SpreadsheetApp.getActiveSpreadsheet().getBlob();
}else if (host == 'docs') {
var content = DocumentApp.getActiveDocument().getBlob();
}
I take the blob and sent it through multi part form request in URLFetchApp.fetch() through the payload parameter.
But the content for both the docs and sheets is converted/sent to my service as pdf.
Is there any way to preserve/send the files in google format itself ?
if not in google format then in Microsoft office formats ?
Best Regards,
Saurav
As mentioned in the similar post, this behavior is expected. If you want to get the file's content in Microsoft office formats,
you can check the following options:
(OPTION 1): Get export URL from Advanced Drive Service
Sample Code:
function getDocument(){
var host = "docs";
var fileId;
var exportFormat;
if(host == 'sheets'){
fileId = SpreadsheetApp.getActiveSpreadsheet().getId();
exportFormat = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
}else if (host == 'docs') {
fileId = DocumentApp.getActiveDocument().getId();
exportFormat = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
}
var url = Drive.Files.get(fileId).exportLinks[exportFormat];
Logger.log(url);
var oauthToken = ScriptApp.getOAuthToken();
var content = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + oauthToken
}
}).getBlob();
Logger.log(content.getContentType());
content.setName("TestFile");
MailApp.sendEmail("email#sample.com", "Test", "Test", {attachments: content});
}
Pre-requisite:
You need to enable Advanced Drive Service to get the export links of the file using Drive.Files.get(). This request will return a File Resource where you can get the exportLinks that can be accessed using a key based on the supported export MIME Types
What it does?
Depending on the host set, get the file id and export format based on supported export MIME Types
Get the file resource using Drive.Files.get() and get the export link based on the export format key set in step 1.
Use UrlFetchApp.fetch(url, params) and get the file's blob using HTTPResponse.getBlob()
Output:
(OPTION 2):Create export URL manually using the template url
Sample Code:
function getDocument(){
var host = "docs";
var fileId;
var url;
if(host == 'sheets'){
fileId = SpreadsheetApp.getActiveSpreadsheet().getId();
url = "https://docs.google.com/spreadsheets/export?id="+fileId+"&exportFormat=xlsx"
}else if (host == 'docs') {
fileId = DocumentApp.getActiveDocument().getId();
url = "https://docs.google.com/feeds/download/documents/export/Export?id="+fileId+"&exportFormat=docx";
}
Logger.log(url);
var oauthToken = ScriptApp.getOAuthToken();
var content = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + oauthToken
}
}).getBlob();
Logger.log(content.getContentType());
}
What it does?
Depending on the host set, get the file id and create an export link using this templates:
EXCEL: https://docs.google.com/spreadsheets/export?id=<fileId>&exportFormat=xlsx
WORD: https://docs.google.com/feeds/download/documents/export/Export?id=<fileId>&exportFormat=docx
Use UrlFetchApp.fetch(url, params) and get the file's blob using HTTPResponse.getBlob()
Note:
Based on Quotas for Google Services, Url Fetch Call has a daily quota of 20,000 for Consumer and G Suite free edition, while 100,000 for Google Workspace accounts

Save Document without closing

How do I save the current document as docx without closing through saveAndClose() first? I want to create multiple docx files from the same original Google Docs document on which my Script is running.
You can export a docs to docx with URL fetch:
function myFunction() {
var doc_id = 'YOUR DOCUMENT ID';
var url = 'https://docs.google.com/feeds/download/documents/export/Export?id=' + doc_id + '&exportFormat=docx';
var options = {
headers: {
Authorization: "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true
}
var response = UrlFetchApp.fetch(url, options);
var doc = response.getBlob();
DriveApp.createFile(doc).setName('myDocxFile1');
DriveApp.createFile(doc).setName('myDocxFile2');
}

Manipulating RTF files with GAS (to gdoc, en masse)

Is there a way to programmatically convert RTF files to gdocs, or if you can't convert then just copy the contents? I have hundreds to store in gdrive so I'd prefer to convert them to make them easier to manipulate and merge later.
You want to convert RTF file to Google Document.
There are several hundreds of RTF files.
If my understanding is correct, how about this sample script?
As a simple conversion, you can use the script of Drive.Files.copy({mimeType: MimeType.GOOGLE_DOCS}, fileId) using Advanced Google Service. But from your question, I thought that when a lot of files are converted, the execution time might be over 6 minutes. So in this sample script, I conver the files with the files.copy method of Drive API using Batch request.
Sample script:
When you run the script, please set the parameters to the function of main(). And run main().
// Get file IDs of Microsoft Excel files in a specific folder including subfolders.
function getFileIds(folder, fileIds, q) {
var files = folder.searchFiles(q);
while (files.hasNext()) {
fileIds.push(files.next().getId());
}
var folders = folder.getFolders();
while (folders.hasNext()) {
getFileIds(folders.next(), fileIds, q);
}
return fileIds;
}
// Convert Microsoft Docs to Google Docs
function convertToGoogleDocs(fileIds, dest, to) {
var limit = 100;
var split = Math.ceil(fileIds.length / limit);
var reqs = [];
for (var i = 0; i < split; i++) {
var boundary = "xxxxxxxxxx";
var payload = fileIds.splice(0, limit).reduce(function(s, e, i) {
s += "Content-Type: application/http\r\n" +
"Content-ID: " + i + "\r\n\r\n" +
"POST https://www.googleapis.com/drive/v3/files/" + e + "/copy" + "\r\n" +
"Content-Type: application/json; charset=utf-8\r\n\r\n" +
JSON.stringify({"parents": [dest], "mimeType": to}) + "\r\n" +
"--" + boundary + "\r\n";
return s;
}, "--" + boundary + "\r\n");
var params = {
method: "post",
contentType: "multipart/mixed; boundary=" + boundary,
payload: payload,
headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true,
};
var req = UrlFetchApp.getRequest("https://www.googleapis.com/batch/drive/v3", params);
reqs.push(req);
}
return UrlFetchApp.fetchAll(reqs);
}
// Please run this function.
function main() {
var sourceFolderId = "###"; // Folder ID including source files. Please set this.
var destinationFolderId = "###"; // Folder ID that the converted files are put. Please set this.
var from = [MimeType.RTF, MimeType.MICROSOFT_WORD_LEGACY]; // Source mimeType
var to = MimeType.GOOGLE_DOCS; // Destination mimeType
var q = from.reduce(function(q, e, i) {return q += "mimeType='" + e + "'" + (i < from.length - 1 ? " or " : "")}, "");
var fileIds = getFileIds(DriveApp.getFolderById(sourceFolderId), [], q);
Logger.log(fileIds)
var res = convertToGoogleDocs(fileIds, destinationFolderId, to);
Logger.log(res);
}
Note:
If the file size is large, an error might occur.
When RTF file is retrieved by Drive API, there was the case that the mimeType becomes application/msword. So I searched both application/rtf and application/msword.
Unfortunately, in the current stage, the batch request cannot use the media blob. So I used the files.copy method. In this case, the files can be converted without using the media blob.
References:
Files: copy
Batch request
If I misunderstood your question and this was not the result you want, I apologize.