1

I want to convert a few google spreadsheets to Excel (xlsx preferred).
I've read several threads about how to achieve this, but I can't get it running.
Amongst the threads I've read are Google Apps Script: Save Spreadsheet as ODS for Local Backup and Google apps script to email google spreadsheet excel version

In order to stay close to code I've found AND get more info about why it doesn't work, I modified code I found such that it just handles a few files and also try-catch has been removed.

****************** Not working code **************
function contentODS(key, gid) 
{
   var file = DocsList.getFileById(key); 

   var fetchParameters = oAuth();

   var url = "https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=" + key + "&gid=" + gid + "&exportFormat=ods";
   var response = UrlFetchApp.fetch(url, fetchParameters);

   var fileBlob = response.getBlob();  
   return fileBlob;
}

function oAuth()
{ // https://stackoverflow.com/questions/24493203/google-apps-script-save-spreadsheet-as-ods-for-local-backup
  var oauthConfig = UrlFetchApp.addOAuthService("spreadsheets");
  var scope = "https://spreadsheets.google.com/feeds" 
  oauthConfig.setConsumerKey("anonymous");
  oauthConfig.setConsumerSecret("anonymous");
  oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope=" + scope);
  oauthConfig.setAuthorizationUrl("https://accounts.google.com/OAuthAuthorizeToken");    
  oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");   

  var requestData =
  {
    "oAuthServiceName":   "spreadsheets",
    "oAuthUseToken":      "always",
    "muteHttpExceptions": true,
    "method":             "DELETE",
  };
  return requestData;
}

function eachSheet(key, newFolderId)
{
  var ss = SpreadsheetApp.openById(key);
  var ssId = ss.getId();
  var ssName = ss.getName();
  var howManySheets = ss.getNumSheets();

  for (var sheetIndex=0; sheetIndex < howManySheets; sheetIndex++)
  {   
     var activeSheet = ss.getSheets()[sheetIndex];
     var activeName = activeSheet.getName();
     var activeId = activeSheet.getSheetId();
     var time = new Date();
     var fileName = time + " Backup: " + ssName + " " + activeName + ".ods";
     var blob = contentODS(ssId, activeId);
     var folder = DocsList.getFolderById(newFolderId);  
     folder.createFile(blob).rename(fileName);
   } 
}

function backUpMaker()
{
  var backupDirectory = 'Backup';
  var folders = DriveApp.getRootFolder().getFoldersByName(backupDirectory);
  var backupFolderId = undefined;
  if (folders.hasNext()) backupFolderId = folders.next().getId();
  else return;  // File doe not exist

  var timeNow = new Date();  
  var newFolder = DocsList.createFolder(timeNow);
  var newFolderId = newFolder.getId();
  newFolder.addToFolder(DocsList.getFolderById(backupFolderId));
  newFolder.removeFromFolder(DocsList.getRootFolder());
  var sheets = DriveApp.getFilesByType(MimeType.GOOGLE_SHEETS);
  while (sheets.hasNext())
  {
    var sheet = sheets.next();
    var name = sheet.getName();

    var filesToSave = [ 'My-Agenda', 'My-Kalender' ];
    var numFiles = filesToSave.length;

    for (var i=0; i<numFiles; i++)
    {
       if (name == filesToSave[i])
       {
          var sheetId = sheet.getId();
          var csv = eachSheet(sheetId, newFolderId); 
          break;
       }  
    }   
  }
  var backupFolder = DocsList.getFolderById(backupFolderId);
  var newFiles = newFolder.getFiles();
  var numFiles = newFiles.length;

  if (numFiles > 0)
  {
     var nameZipFile = timeNow + '.zip';
     backupFolder.createFile(Utilities.zip(newFiles, nameZipFile));
  } 

  newFolder.setTrashed(true);
}

Running backupmaker fails at var response = UrlFetchApp.fetch(url, fetchParameters);
and indicates verification for service spreadsheets failed

Waht should I do to make it work.

Community
  • 1
  • 1
SoftwareTester
  • 1,048
  • 1
  • 10
  • 25
  • Are you using new version of spreadsheet? – Serge insas Jul 27 '14 at 21:15
  • @SergeInsas I must say "I don't know" . I created spreadsheets using SpreadsheetApp and also using the red "create" button on Google Drive. Can you be more specific so I CAN provide a real answer – SoftwareTester Jul 28 '14 at 11:47
  • 2
    The new version has a small green icon at the bottom with a "v" in it (like a sort of check box) and defaults to 1000 rows instead of 100 among other differences...it is also the version that has an add on menu. – Serge insas Jul 28 '14 at 11:54
  • Yes, indeed I'm using the new version. – SoftwareTester Jul 28 '14 at 15:13
  • 1
    That's why the code you are referencing to does not work actually... The url used to call the urlFetch are only useable with old version. I searched for a solution but although I found the code for pdf conversion all the tests I made to get xls conversion have failed... so, for now, I can't provide a solution for you, sorry. – Serge insas Jul 28 '14 at 15:34
  • Another codebreaker by Google..... The PDF conversion can be useful as well. Did you post it already? Thanks for the reference – SoftwareTester Jul 28 '14 at 15:40
  • 1
    I found it on Amit Agarwal's site : [http://ctrlq.org/code/19699-email-google-spreadsheet-as-pdf](http://ctrlq.org/code/19699-email-google-spreadsheet-as-pdf) I tested it successfully ;) – Serge insas Jul 28 '14 at 15:43
  • 1
    btw, you have 2 pending questions I answered, are these answers not acceptable in your opinion ? – Serge insas Jul 28 '14 at 15:52
  • Sorry, I missed those answers. I upvoted the comments now. – SoftwareTester Aug 11 '14 at 21:07

1 Answers1

4

You can use the Advanced Drive Service to get the export URL and use the script's OAuth2 token to download the file.

function exportAsExcel(spreadsheetId) {
  var file = Drive.Files.get(spreadsheetId);
  var url = file.exportLinks['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
  var token = ScriptApp.getOAuthToken();
  var response = UrlFetchApp.fetch(url, {
    headers: {
      'Authorization': 'Bearer ' +  token
    }
  });
  return response.getBlob();
}

function test() {
  var spreadsheetId = 'SPREADSHEET ID HERE';
  DriveApp.createFile(exportAsExcel(spreadsheetId));
}
Eric Koleda
  • 12,420
  • 1
  • 33
  • 51
  • As a follow up question : is it possible to create an Excel spreadsheet and writing to it like to a Google spreadsheet? I tried `DriveApp.createFile('newExcelFile', '','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' );` This does create the file, it doesn't have a sheet in it nor can I use it with SpreadsheetApp. – SoftwareTester Aug 09 '14 at 11:41
  • Unfortunately there is no API to do cell-by-cell manipulations of an Excel file stored in Drive. You would have to download the file, edit it locally using a library, and re-upload it. Alternatively, you could upload one and convert it to a Google Spreadsheet using `convert: true` in the request. – Eric Koleda Aug 11 '14 at 13:29