How to convert a Google Sheets-File to an Excel-File (XLSX) - google-apps-script

The image shows the code who is updated.
The var "xlsFile" is undefined, why? How can I convert the Google Sheets file to an Excel file with (Google Sheets) Script Editor
function googleOAuth_ (name, scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken? scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
return {oAuthServiceName:name, oAuthUseToken:"always"};
}
function test(){
var id = '#'
exportToXls(id)
}
function exportToXls(id){
var mute = {muteHttpExceptions: true };
var name = DriveApp.getFileById(id).getName()
var url = 'https://docs.google.com/feeds/';
var doc = UrlFetchApp.fetch(url+'download/spreadsheets/Export?key='+id+'&exportFormat=xls', mute).getBlob()
var xlsfile = DocsList.createFile(doc).rename(name+'.xlsx')
}

Using the Drive API, we can get more information about files than is available through the DriveApp methods. Check out the file data, especially exportLinks. Those links contain the magic that will let us get an XLS file. (For fun, put a breakpoint after file is assigned, and check what information you have to play with.)
This script uses the Advanced Drive Service, which must be enabled. A more complete version, with error checking, is available in this gist.
/**
* Downloads spreadsheet with given file id as an Excel file.
* Uses Advanced Drive Service, which must be enabled. * Throws if error encountered.
*
* #param {String} fileId File ID of Sheets file on Drive.
*/
function downloadXLS(fileId) {
var file = Drive.Files.get(fileId);
var url = file.exportLinks[MimeType.MICROSOFT_EXCEL];
var options = {
headers: {
Authorization:"Bearer "+ScriptApp.getOAuthToken()
},
muteHttpExceptions : true /// Get failure results
}
var response = UrlFetchApp.fetch(url, options);
var status = response.getResponseCode();
var result = response.getContentText();
if (status != 200) {
// Get additional error message info, depending on format
if (result.toUpperCase().indexOf("<HTML") !== -1) {
var message = strip_tags(result);
}
else if (result.indexOf('errors') != -1) {
message = JSON.parse(result).error.message;
}
throw new Error('Error (' + status + ") " + message );
}
var doc = response.getBlob();
//DocsList.createFile(doc).rename(file.title + '.xlsx') // Deprecated
DriveApp.createFile(doc).setName(file.title + '.xlsx');
}

The code below uses oAuthConfig which is now deprecated. Use Mogsdad answer instead. The importXLS function uses the drive API and still works.
You'll find many post saying this is not possible and (a few) others saying that you can...and obviously you can !
Mogsdad's answer here (simultaneously) brings an elegant solution using drive service, here is another one so you have a choice ;-)
As a bonus, I added the reverse process, if ever you need it.
Use a function call similar to what I use in the test function to make it work.
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
return {oAuthServiceName:name, oAuthUseToken:"always"};
}
function test(){
var id = 'spreadsheet_ID'
exportToXls(id)
}
function exportToXls(id){
var name = DriveApp.getFileById(id).getName()
var url = 'https://docs.google.com/feeds/';
var doc = UrlFetchApp.fetch(url+'download/spreadsheets/Export?key='+id+'&exportFormat=xls',
googleOAuth_('docs',url)).getBlob()
var xlsfile = DocsList.createFile(doc).rename(name+'.xls')
}
function importXLS(){
var files = DriveApp.searchFiles('title contains ".xls"');
while(files.hasNext()){
var xFile = files.next();
var name = xFile.getName();
if (name.indexOf('.xls')>-1){
var ID = xFile.getId();
var xBlob = xFile.getBlob();
var newFile = { title : name+'_converted',
key : ID
}
file = Drive.Files.insert(newFile, xBlob, {
convert: true
});
}
}
}

Related

App script for pdf converter exceeded maximum execution time

This is my app script code that converts google docs in a folder into pdf format. The script stops after converting around 60 documents with maximum execution time error. I am converting around hundreds of files in a run. What can I do to avoid this error?
//Module to convert doc to pdf
function gdocToPDF() {
var documentRootfolder = DriveApp.getFolderById("xx") // replace this with the ID of the folder that contains the documents you want to convert
var pdfFolder = DriveApp.getFolderById("xx"); // replace this with the ID of the folder that the PDFs should be put in.
var documentRootFiles = documentRootfolder.getFiles()
while(documentRootFiles.hasNext()) {
createPDF(documentRootFiles.next().getId(), pdfFolder.getId(), function (fileID, folderID) {
if (fileID) createPDFfile(fileID, folderID);
})
}
}
function createPDF(fileID, folderID, callback) {
var templateFile = DriveApp.getFileById(fileID);
var templateName = templateFile.getName();
var existingPDFs = DriveApp.getFolderById(folderID).getFiles();
//in case no files exist
if (!existingPDFs.hasNext()) {
return callback(fileID, folderID);
}
for (; existingPDFs.hasNext();) {
var existingPDFfile = existingPDFs.next();
var existingPDFfileName = existingPDFfile.getName();
if (existingPDFfileName == templateName + ".pdf") {
Logger.log("PDF exists already. No PDF created")
return callback();
}
if (!existingPDFs.hasNext()) {
Logger.log("PDF is created")
return callback(fileID, folderID)
}
}
}
function createPDFfile(fileID, folderID) {
var templateFile = DriveApp.getFileById(fileID);
var folder = DriveApp.getFolderById(folderID);
var theBlob = templateFile.getBlob().getAs('application/pdf');
var newPDFFile = folder.createFile(theBlob);
var fileName = templateFile.getName().replace(".", ""); //otherwise filename will be shortened after full stop
newPDFFile.setName(fileName + ".pdf");
}
I generate a lot of files. What I do to avoid this error is open a dialog and run a function that creates one file at a time. I write the number of remaining files in a cell in the sheet, update it with every run. I use the success and failure handlers to decide whether to continue with file generation or close the dialog. You can generate files for hours in this way.

Downloading a Google Slides presentation as PowerPoint doc using Google Apps Script?

The GUI of Google Slides offers to download a GSlides presentation as a Powerpoint (myFile.pptx). I could not find the equivalent in the Google Apps Script documentation - any pointer?
EDIT
Thanks to comments and answers, I tried this snippet:
function testFileOps() {
// Converts the file named 'Synthese' (which happens to be a Google Slide doc) into a pptx
var files = DriveApp.getFilesByName('Synthese');
var rootFolder = DriveApp.getRootFolder();
while (files.hasNext()) {
var file = files.next();
var blobPptx = file.getBlob().getAs('application/vnd.openxmlformats-officedocument.presentationml.presentation');
var result = rootFolder.createFile(blobPptx);
}
}
It returns an error:
Converting from application/vnd.google-apps.presentation to
application/vnd.openxmlformats-officedocument.presentationml.presentation
is not supported. (line 7, file "Code")
SECOND EDIT
As per another suggestion in comments, I tried to make an http call from Google App Script, that would directly convert the gslides into pptx, without size limit. It produces a file on G Drive, but this file is corrupted / unreadable. The GAS script:
function convertFileToPptx() {
// Converts a public Google Slide file into a pptx
var rootFolder = DriveApp.getRootFolder();
var response = UrlFetchApp.fetch('https://docs.google.com/presentation/d/1Zc4-yFoUYONXSLleV_IaFRlNk6flRKUuAw8M36VZe-4/export/pptx');
var blobPptx = response.getContent();
var result = rootFolder.createFile('test2.pptx',blobPptx,MimeType.MICROSOFT_POWERPOINT);
}
Notes:
I got the mime type for pptx here
using the mime type 'pptx' returns the same error message
How about this modification?
Modification point:
response.getContent() returns byte array. So please use response.getBlob().
Modified script:
function convertFileToPptx() {
var fileId = "1Zc4-yFoUYONXSLleV_IaFRlNk6flRKUuAw8M36VZe-4";
var outputFileName = "test2.pptx";
var url = 'https://docs.google.com/presentation/d/' + fileId + '/export/pptx';
var rootFolder = DriveApp.getRootFolder();
var response = UrlFetchApp.fetch(url);
var blobPptx = response.getBlob();
var result = rootFolder.createFile(blobPptx.setName(outputFileName));
}
Note:
If you want to convert Google Slides, which are not published, in your Google Drive, please use access token. At that time please modify url as follows.
var url = 'https://docs.google.com/presentation/d/' + fileId + '/export/pptx?access_token=' + ScriptApp.getOAuthToken();
DriveApp.createFile() creates a file on root folder as the default.
References:
Class HTTPResponse
getOAuthToken()
As mentioned by tehhowch, you could get the Google Slide file from your Drive and get it as a .pptx. (Not sure of mime type.)
File#getAs:
I add all modifications with token part and specific folder
function convertFileToPptx() {
var fileId = "Your File ID";
var outputFileName = "name.pptx";
var url = 'https://docs.google.com/presentation/d/' + fileId + '/export/pptx';
//var rootFolder = DriveApp.getRootFolder();
var rootFolder = DriveApp.getFolderById("Your Folder ID")
var params = {method:"GET", headers:{"authorization":"Bearer "+ ScriptApp.getOAuthToken()}};
var response = UrlFetchApp.fetch(url,params);
var blobPptx = response.getBlob();
var result = rootFolder.createFile(blobPptx.setName(outputFileName));
}
To get the byte[] do:
function downloadAsPPTX(){
var presentation = SlidesApp.getActivePresentation();
var fileId = presentation.getId();
var url = 'https://docs.google.com/presentation/d/' + fileId + '/export/pptx';
var response = UrlFetchApp.fetch(url);
var blobPptx = response.getBlob();
Logger.log("size: "+blobPptx.getBytes().length);
}

How to send XML request with Google Apps Script?

I'm trying to use Google Apps Script to retrieve data from Google Apps Reporting API which specify me to send XML request
My goal is to retrieve disk_space_report an put that data into spreadsheet so I can monitor the disk space in that spreadsheet and also process some data.
Anyone can give me an example on how to do that kind of stuff?
Thanks in advanced.
Here is a little code which I have written and using to fetch Google Apps users account report.
function startHere(){
var domain = UserManager.getDomain();
var fDate = '2012-12-18';//Utilities.formatDate(new Date(), Session.getTimeZone(), 'yyyy-MM-dd');
var url = 'https://www.google.com/hosted/services/v1.0/reports/ReportingData';
//Build API request parameters
var fetchArgs = googleOAuth_('Reporting', url);
fetchArgs.method = 'POST';
var rawXML = '<?xml version="1.0" encoding="UTF-8"?>'
+'<rest xmlns="google:accounts:rest:protocol" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance ">'
+'<type>Report</type>'
+'<domain>'+domain+'</domain>'
+'<date>'+fDate+'</date>'
+'<page>1</page>'
+'<reportType>daily</reportType>'
+'<reportName>accounts</reportName>'
+'</rest>';
fetchArgs.payload = rawXML;
fetchArgs.contentType = "application/xml";
fetchArgs.headers = {"Content-type": "application/atom+xml charset=UTF-8"};
//Fetch CSV data
var csvData = UrlFetchApp.fetch(url, fetchArgs).getContentText();
//Parse CSV data and make a 2D array
var recs = csvData.split('\n');
var data = []; //this is actual 2D data
for(var i=0; i<recs.length-1; i++){
var temp = recs[i].split(',');
if(i==0) temp.push('percent_disk_usage');
else{
var usage = (parseInt(temp[5])*100)/(parseInt(temp[4])*1024*1024);
temp.push(usage);
}
data.push(temp);
}
//Write data to spreadsheet
}
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey("anonymous");
oAuthConfig.setConsumerSecret("anonymous");
return {oAuthServiceName:name, oAuthUseToken:"always"};
}
Just a quick sample. Inside your script create a new HTML file called: xmlRequest with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<rest xmlns="google:accounts:rest:protocol"
xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance ">
<type>Report</type>
<domain>YOURDOMAIN.COM</domain>
<date>2012-12-01</date>
<page>1</page>
<reportType>daily</reportType>
<reportName>accounts</reportName>
</rest>
Change YOURDOMAIN.COM with your Google Apps domain. Inside Code.gs paste the following code:
/**
* Script configuration
*/
var SCOPE = 'https://www.google.com/hosted/services/v1.0/reports/ReportingData';
var APPNAME = "disk_space_report";
var URL = 'https://www.google.com/hosted/services/v1.0/reports/ReportingData';
function testit() {
// Generate the new entry from a template
var template = HtmlService.createHtmlOutputFromFile("xmlRequest").getContent();
var response = UrlFetchApp.fetch(URL,googleOAuth_('POST', template));
Logger.log(response.getContentText());
}
/**
* Google authentication loader
* #param {String} method the HTTP method to use for the UrlFetch operation, possible values are: GET, POST, PUT, DELETE
* #param {String} payload the payload to use if needed
* #return {Object} configuration options for UrlFetch, including oAuth parameters
*/
function googleOAuth_(method, payload) {
// Shared configuration for all methods
var oAuthConfig = UrlFetchApp.addOAuthService(APPNAME);
oAuthConfig.setRequestTokenUrl('https://www.google.com/accounts/OAuthGetRequestToken?scope='+encodeURIComponent(SCOPE));
oAuthConfig.setAuthorizationUrl('https://www.google.com/accounts/OAuthAuthorizeToken');
oAuthConfig.setAccessTokenUrl('https://www.google.com/accounts/OAuthGetAccessToken');
oAuthConfig.setConsumerKey('anonymous');
oAuthConfig.setConsumerSecret('anonymous');
// Detect the required method
switch(method) {
case "GET":
return {oAuthServiceName:APPNAME, oAuthUseToken:'always'};
break;
case "POST":
return {oAuthServiceName:APPNAME, oAuthUseToken:'always', payload: payload, contentType: 'application/atom+xml', method: "POST"};
break;
case "PUT":
return {oAuthServiceName:APPNAME, oAuthUseToken:'always', payload: payload, contentType: 'application/atom+xml', method: "PUT"};
break;
case "DELETE":
return {oAuthServiceName:APPNAME, oAuthUseToken:'always', method: "DELETE"};
break;
default:
return {oAuthServiceName:APPNAME, oAuthUseToken:'always'};
break;
}
}
Now run the testit function and inside the logger you should get the raw disk usage stats to get parsed.

To get user's profile information in google script

I want to get my domain's user's profile information..I am using profile API for this..
Profile API gives only a few fields like (Family Name, Given Name,Email etc)..But i also want to get these fields also:
occupation,department,Phone [Work], Phone [Mobile], Relation [Manager]...
i am not able to get these fields..So please give me suggestion to get these fields.
I got my all fields by Profile API.... Actually if any field is empty then Profile API doesn't give that field as an output.....
So using Profile API, we can get a user's full information....
Code :
var username="user "
var base = 'https://www.google.com/m8/feeds/';
var fetchArgs = googleOAuth_('contacts', base);
fetchArgs.method='GET'
var url=base+'profiles/domain/'+domainName+'/full/'+username+'?v=3&alt=json'
var name=""
var occupation=""
var department=""
var email=""
var contactNumber_1=""
var contactNumber_2=""
var relation=""
var account=""
var office=""
var personal_account=""
var current_account=""
var language=""
var blog=""
var image=""
try{
var urlFetch = UrlFetchApp.fetch(url, fetchArgs)
var json=Utilities.jsonParse(urlFetch.getContentText())
var profileInfo = json.entry
try{
name=profileInfo.gd$name.gd$fullName.$t
}catch(err){}
try{
occupation=profileInfo.gContact$occupation.$t
}catch(err){}
try{
department=profileInfo.gd$organization[0].gd$orgDepartment.$t
}catch(err){}
try{
var emaillist=profileInfo.gd$email
for(var i=0;i<emaillist.length;i++){
if(emaillist[i].rel.split("#")[1]=='work')
email=profileInfo.gd$email[i].address
}
}catch(err){}
try{
var phonelist=profileInfo.gd$phoneNumber
for(var i=0;i<phonelist.length;i++){
if(phonelist[i].rel.split("#")[1]=='work')
contactNumber_1=phonelist[i].$t
else if(phonelist[i].rel.split("#")[1]=='mobile')
contactNumber_2=phonelist[i].$t
}
}catch(err){}
try{
relation=profileInfo.gContact$relation[0].$t+" ["+profileInfo.gContact$relation[0].rel+"]"
}catch(err){}
}catch(err){}
}
/*
Oauth Authentication
*/
function googleOAuth_(name,scope) {
var oAuthConfig = UrlFetchApp.addOAuthService(name);
oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oAuthConfig.setConsumerKey(consumerKey);
oAuthConfig.setConsumerSecret(consumerSecret);
return {oAuthServiceName:name, oAuthUseToken:"always"};
}
If any field is empty then that tag will not be found thats why all the fields are written in try - catch block...
There isn't a built in API for that in Apps Script directly, but if you are using a Google Apps for Business or Education, you can use the Google Apps through UrlFetch and oAuth. That should expose any profile information that is stored in Google Apps.

exporting spreadsheet to pdf then saving the file in google drive

I'm having problems saving to google drive after printing a google spreadsheet to pdf.
If i just put the "printurl" string into a browser, it will automatically give me the file. But I want it to be saved to google drive automatically. I've tried this code by borrowing code from other posts that emails a spreadsheet as PDF. But this produces a pdf that is unable to be opened. What am I doing wrong?
function printpdf() {
var spreadsheet_id="0Aiy1DTQRndx6dDRidXoxNzlXZFhxd2FITTlBbnUybnc";
var settings = '&fitw=true&portrait=false&exportFormat=pdf&gid=0&gridlines=false';
var printurl = 'https://spreadsheets.google.com/feeds/download/spreadsheets/Export? key=' + spreadsheet_id + settings;
var result=UrlFetchApp.fetch(printurl);
var content=result.getContent();
var file=DocsList.createFile("temp",content,"application/pdf");
}
Here is an update to this question under the new oauth2 format.
Printing spreadsheet to PDF then saving file in Drive using OAuth2
You can do it in a much simpler fashion
function printpdf(){
var spreadsheet_id="0Aiy1DTQRndx6dDRidXoxNzlXZFhxd2FITTlBbnUybnc";
var spreadsheetFile = DocsList.getFileById(spreadsheet_id);
var blob = spreadsheetFile.getAs('application/pdf');
DocsList.createFile(blob);
}
Note that the DocsList.createFile(blob) works only with Google Apps accounts.
did you mean it like that?
var id = SpreadsheetApp.getActiveSpreadsheet().getId();
var sheetName = getConfig(SHEET_NAME_CELL);
var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
if (!dataSheet) {
Browser.msgBox("Can't find sheet named:" + sheetName);
return;
}
var dataSheetIndex = dataSheet.getSheetId();
//this is three level authorization
var oauthConfig = UrlFetchApp.addOAuthService("google");
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope=https://spreadsheets.google.com/feeds/");
oauthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
//even better code
//oauthConfig.setConsumerKey(ScriptProperties.getProperty("consumerKey"));
//oauthConfig.setConsumerSecret(ScriptProperties.getProperty("consumerSecret"));
var requestData = {
"method": "GET",
"oAuthServiceName": "google",
"oAuthUseToken": "always"
};
var url = "https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=" + id + "&gid=" + dataSheetIndex + "&fitw=true&size=A4&portrait=true&sheetnames=false&printtitle=false&exportFormat=pdf&format=pdf&gridlines=false";
//Save File to Google Drive
var seplogoBlob = UrlFetchApp.fetch(url, requestData).getBlob().setName("Filename.pdf");
DocsList.createFile(seplogoBlob);