Convert entire Google Sheet to xlsx file - javascript

I have tried to amend the below script to essentially convert a entire google sheet to xlsx file, keeping tab names the same and locating them to a folder,
The issue I am experiencing with the below is that is is splitting out each tab into separate files but I would like to keep them all together in one file
https://webapps.stackexchange.com/questions/58615/export-all-sheets-in-a-spreadsheet-to-csv-in-google-apps
function saveAsxlsx() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
// create a folder from the name of the spreadsheet
var folder = DriveApp.getFolderById('xxxxxxx');
for (var i = 0 ; i < sheets.length ; i++) {
var sheet = sheets[i];
// append ".xlsx" extension to the sheet name
fileName = sheet.getName() + ".xlsx";
// convert all available sheet data to xlsx format
var xlsxFile = convertRangeToxlsxFile_(fileName, sheet);
// create a file in the Docs List with the given name and the xlsx data
folder.createFile(fileName, xlsxFile);
}
Browser.msgBox('Files are waitig in a folder named ' + folder.getName());
}
function convertRangeToxlsxFile_(xlsxFileName, sheet) {
// get available data range in the spreadsheet
var activeRange = sheet.getDataRange();
try {
var data = activeRange.getValues();
var xlsxFile = undefined;
// loop through the data in the range and build a string with the xlsx data
if (data.length > 1) {
var xlsx = "";
for (var row = 0; row < data.length; row++) {
for (var col = 0; col < data[row].length; col++) {
if (data[row][col].toString().indexOf(",") != -1) {
data[row][col] = "\"" + data[row][col] + "\"";
}
}
// join each row's columns
// add a carriage return to end of each row, except for the last one
if (row < data.length-1) {
xlsx += data[row].join(",") + "\r\n";
}
else {
xlsx += data[row];
}
}
xlsxFile = xlsx;
}
return xlsxFile;
}
catch(err) {
Logger.log(err);
Browser.msgBox(err);
}
}

The script you're using was designed to get each sheet as a separate file. You can refer to this example instead that will convert Google Sheet to Excel XLSX Spreadsheet. I added a couple of lines to the code to save the file to a folder instead of sending an email as the example does.
function getGoogleSpreadsheetAsExcel() {
try {
var ss = SpreadsheetApp.getActive();
var url = 'https://docs.google.com/feeds/download/spreadsheets/Export?key=' + ss.getId() + '&exportFormat=xlsx';
var folder = DriveApp.getFolderById('folderID'); //Add the folder ID of the folder where you want to save the file
var params = {
method: 'get',
headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() },
muteHttpExceptions: true,
};
var blob = UrlFetchApp.fetch(url, params).getBlob();
blob.setName(ss.getName() + '.xlsx');
folder.createFile(blob)
} catch (f) {
Logger.log(f.toString());
}
}

Related

How to append all spreadsheets in the same folder?

I am trying to append all spreadsheets from the same folder to a master sheet.
I have found a similar code here but I can append the spreadsheets only when the master sheet is also in the selected folder. How could it be modified so that it could be able to applicable to other folders?please advise~
function appendData() {
var sheet = SpreadsheetApp.getActiveSheet();
var folder = DriveApp.getFolderById("1UQ5J3xdNnqyHvC-CJ1vAu5YPSxq9Sya9");
var files = folder.getFiles();
var cnt=0;
while (files.hasNext()) {
var file = files.next();
cnt++;
// if the file is not a Sheet, skip it
if (file.getMimeType() != "application/vnd.google-apps.spreadsheet") {
continue;
}
var importSheet = SpreadsheetApp.openById(file.getId())
// assuming you only want to append the first sheet of each Spreadsheet:
var range = importSheet.getSheets()[0].getDataRange();
// extend the main sheet if you need to:
try {
sheet.getRange(1, 1, sheet.getDataRange().getNumRows() + range.getNumRows(), 1);
}
catch (e) {
sheet.insertRowsAfter(sheet.getDataRange().getNumRows(), range.getNumRows() + 1);
}
// remove the headers from the data to copy:
range = importSheet.getSheets()[0].getRange(2, 1, range.getNumRows() - 1, range.getNumColumns())
// copy the data:
sheet.getRange(sheet.getDataRange().getNumRows() + 1, 1, range.getNumRows(), range.getNumColumns()).setValues(range.getValues());
}
}
Try this:
function appendData() {
var sheet=SpreadsheetApp.getActiveSheet();
var folder=DriveApp.getFolderById("1UQ5J3xdNnqyHvC-CJ1vAu5YPSxq9Sya9");
var files=folder.getFilesByType(MimeType.GOOGLE_SHEETS);
while (files.hasNext()) {
var file = files.next();
var importSheet=SpreadsheetApp.openById(file.getId())
var values=importSheet.getSheets()[0].getDataRange().getValues();
sheet.getRange(sheet.getLastRow()+1,1,values.length,values[0].length).setValues(values);
Logger.log(file.getName());
}
}
Append both spreadsheets and Excel files to the same master sheet
If you need to append not only sheets from Google spreadsheets, but also form Excel files, you need to convert the latter ones to Google Sheets first.
For this, you can modify your existing code as following:
function appendData() {
var sheet = SpreadsheetApp.getActiveSheet();
var folder = DriveApp.getFolderById("1fUpTphVpYGfLv6SjWxZdbcIK7PHCZOnt");
var files = folder.getFiles();
var cnt=0;
while (files.hasNext()) {
var file = files.next();
cnt++;
// if the file is an excel - convert it to sheet
if (file.getMimeType() != "application/vnd.google-apps.spreadsheet") {
Logger.log(file.getMimeType());
//here is the additional part
//define here mime-types of interest and convert them
if (file.getMimeType() == "application/vnd.ms-excel" || file.getMimeType() == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") {
var fileId = file.getId();
var folderId = folder.getId();
var blob = file.getBlob();
var resource = {
title: file.getName(),
mimeType: MimeType.GOOGLE_SHEETS,
parents: [{id: folderId}],
};
var file = Drive.Files.insert(resource, blob);
}else{
continue;
}
}
var importSheet = SpreadsheetApp.openById(file.getId())
// assuming you only want to append the first sheet of each Spreadsheet:
var range = importSheet.getSheets()[0].getDataRange();
// extend the main sheet if you need to:
try {
sheet.getRange(1, 1, sheet.getDataRange().getNumRows() + range.getNumRows(), 1);
}
catch (e) {
sheet.insertRowsAfter(sheet.getDataRange().getNumRows(), range.getNumRows() + 1);
}
// remove the headers from the data to copy:
range = importSheet.getSheets()[0].getRange(2, 1, range.getNumRows() - 1, range.getNumColumns())
Logger.log("range.getA1Notation():" + range.getA1Notation());
// copy the data:
sheet.getRange(sheet.getDataRange().getNumRows() + 1, 1, range.getNumRows(), range.getNumColumns()).setValues(range.getValues());
}
}

0 numeral not recognized when copying data from sheet to a file

I'm trying to create a my own CSV file using info in a google sheet. The info copies correctly, however any time there is a 0 in a cell, it gets ignored and I get a blank spot in my CSV file. Any suggestions? Code below.
function saveAsCSV() {
var filename = "trainingImport"; // CSV file name
var folder = "1vzTFeLwwR35XluyE39Uk9mzbLVJHE3XB"; // Folder ID
var sprdSheet = SpreadsheetApp.getActiveSpreadsheet();
var outPut = sprdSheet.getSheetByName("Output");
var range = outPut.getDataRange();
var values = range.getValues();
var csv = "";
for (var i = 0; i < values.length; i++) {
var row = "";
for (var j = 0; j < values.length[i]; j++) {
if (values[i][j]) {
row = row + values[i][j];
}
if (outPut.getRange((i+1),(j+2)).isBlank()) {
break;
}
row = row + ",";
}
csv += row + " \n";
}
var url = DriveApp.getFolderById(folder)
.createFile(filename, csv, MimeType.CSV)
.getDownloadUrl()
.replace("?e=download&gd=true","");
return url;
}
The problem lies in the if statement just in the inner for loop:
if (values[i][j]) {
row = row + values[i][j];
}
The statement will be false, if values[i][j] is 0, beacause 0 is falsy.
That means, that when converted to a Boolean, 0 acts like literal false, this also applies to empty strings, null, undefined and NaN.
If you change it to
if (values[i][j] || values[i][j] === 0) {
row = row + values[i][j];
}
0 will be added to the row.

How to export all the sheets of a workbook from google by drive api

I want to download all the sheets of an excel document in csv format. presently, only the first sheet data is accessible. code is given below:
function downloadGDriveFile (file) {
var request1 = gapi.client.drive.files.export({
'fileId': '1VLFgD8CNvXTVdHKyBdZPUmgFmhWMzg7qWLbxzLUTtSo',
'mimeType': 'text/csv'
})
request1.then(function(response) {
//console.log(response);
}, function(err) {
console.log('Error');
console.log(err.result.error);
});
}
presently I am using a static id. The excel gave two sheets. But the code shows only first sheet data. how to download all the sheets with in a workbook.
I've read from this tutorial blog that this is indeed the behavior when you try to export files.
However, there's a way to get all sheets from your spreadsheet using Apps Script. After executing custom menu "csv->export as csv file", the sheets will be placed inyour Google Drive inside a folder. Here's the code from the blog:
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var csvMenuEntries = [{name: "export as csv files", functionName: "saveAsCSV"}];
ss.addMenu("csv", csvMenuEntries);
};
function saveAsCSV() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
// create a folder from the name of the spreadsheet
var folder = DriveApp.createFolder(ss.getName().toLowerCase().replace(/ /g,'_') + '_csv_' + new Date().getTime());
for (var i = 0 ; i < sheets.length ; i++) {
var sheet = sheets[i];
// append ".csv" extension to the sheet name
fileName = sheet.getName() + ".csv";
// convert all available sheet data to csv format
var csvFile = convertRangeToCsvFile_(fileName, sheet);
// create a file in the Docs List with the given name and the csv data
folder.createFile(fileName, csvFile);
}
Browser.msgBox('Files are waiting in a folder named ' + folder.getName());
}
function convertRangeToCsvFile_(csvFileName, sheet) {
// get available data range in the spreadsheet
var activeRange = sheet.getDataRange();
try {
var data = activeRange.getValues();
var csvFile = undefined;
// loop through the data in the range and build a string with the csv data
if (data.length > 1) {
var csv = "";
for (var row = 0; row < data.length; row++) {
for (var col = 0; col < data[row].length; col++) {
if (data[row][col].toString().indexOf(",") != -1) {
data[row][col] = "\"" + data[row][col] + "\"";
}
}
// join each row's columns
// add a carriage return to end of each row, except for the last one
if (row < data.length-1) {
csv += data[row].join(",") + "\r\n";
}
else {
csv += data[row];
}
}
csvFile = csv;
}
return csvFile;
}
catch(err) {
Logger.log(err);
Browser.msgBox(err);
}
}

Export JQGrid data to Excel using javascript

I want to download the grid data in csv format , by looking at the link http://jsfiddle.net/hybrid13i/JXrwM/ and using JSONToCSVConvertor($("#reportGrid").jqGrid("getGridParam", "data"),"Report",true);
you can download a csv file but its column name are variable names not label any idea how can i fix this , or there is another solution
You can use $("#reportGrid").jqGrid("getGridParam", "colNames") to get column headers.
By the way you can use jQuery.extend to make copy of the data, returned from $("#reportGrid").jqGrid("getGridParam", "data"), and then modify the data before calling of JSONToCSVConvertor.
UPDATED: The object which you get by $("#reportGrid").jqGrid("getGridParam", "data") is the reference to internal data parameters. So it contains all what it should contains. To have less properties in the items of the data you should first make a copy of the object and the modify it like you want. For example to delete Id property from all items of the data you can do the following:
var myData = $.extend(true, [],
$("#reportGrid").jqGrid("getGridParam", "data"));
$.each(myData, function () { delete this.Id; });
UPDATED: One can use SheetJS, for example, to export data to Excel. See the demo https://jsfiddle.net/OlegKi/ovq05x0c/6/, created for the issue. The corresponding code of the Export to Excel button used in the demo is the following
.jqGrid("navButtonAdd", {
caption: "",
title: "Export to Excel(.XLSX)",
onClickButton: function () {
var data = $(this).jqGrid("getGridParam", "lastSelectedData"), i, item,
dataAsArray = [
["Client", "Date", "Amount", "Tax", "Total", "Closed", "Shipped via"]
];
for (i = 0; i < data.length; i++) {
item = data[i];
dataAsArray.push([
item.name, new Date(item.invdate),
item.amount, item.tax, item.total,
item.closed, item.ship_via
]);
}
var ws_name = "SheetJS", filename = "jqGrid.xlsx";
var wb = XLSX.utils.book_new(),
ws = XLSX.utils.aoa_to_sheet(dataAsArray);
XLSX.utils.book_append_sheet(wb, ws, ws_name);
XLSX.writeFile(wb, filename);
}
});
Thanks to Oleg and the man who posted http://jsfiddle.net/hybrid13i/JXrwM/ with little enhancement in it this is my final solution
function JSONToCSVConvertor(JSONData, ReportTitle, ShowLabel,headers,excludeColumns,
fileName) {
//If JSONData is not an object then JSON.parse will parse the JSON string in an Object
var arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData;
var CSV = '';
//Set Report title in first row or line
CSV += ReportTitle + '\r\n\n';
//This condition will generate the Label/Header
if (ShowLabel) {
var row = "";
if(headers)
{
row = headers.join(',');
}
else
{
//This loop will extract the label from 1st index of on array
for (var index in arrData[0]) {
//Now convert each value to string and comma-seprated
row += index + ',';
}
}
row = row.slice(0, -1);
//append Label row with line break
CSV += row + '\r\n';
}
//1st loop is to extract each row
for (var i = 0; i < arrData.length; i++) {
var row = "";
//2nd loop will extract each column and convert it in string comma-seprated
for (var colName in arrData[i]) {
if(excludeColumns && excludeColumns.indexOf(colName))
continue;
row += '"' + arrData[i][colName] + '",';
}
row.slice(0, row.length - 1);
//add a line break after each row
CSV += row + '\r\n';
}
if (CSV == '') {
alert("Invalid data");
return;
}
if(!fileName)
{
//Generate a file name
fileName = "MyReport_";
//this will remove the blank-spaces from the title and replace it with an underscore
fileName += ReportTitle.replace(/ /g,"_");
}
if (navigator.appName == "Microsoft Internet Explorer") {
var oWin = window.open();
oWin.document.write('sep=,\r\n' + CSV);
oWin.document.close();
oWin.document.execCommand('SaveAs', true, fileName + ".csv");
oWin.close();
}
else
{
//Initialize file format you want csv or xls
var uri = 'data:text/csv;charset=utf-8,' + escape(CSV);
// Now the little tricky part.
// you can use either>> window.open(uri);
// but this will not work in some browsers
// or you will not get the correct file extension
//this trick will generate a temp <a /> tag
var link = document.createElement("a");
link.href = uri;
//set the visibility hidden so it will not effect on your web-layout
link.style = "visibility:hidden";
link.download = fileName + ".csv";
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
Usage:
JSONToCSVConvertor($(grid).jqGrid("getGridParam", "data"), $("#reportHeader").text().trim(),true,$(grid).jqGrid("getGridParam", "colNames"),["_id_"],"Report");
NOTE Please note that this solution will not work in IE

Deleting a file in Google Script .setTrashed 'You do not have authorization to perform that action.'

I am trying to create a csv file from a Google spreadsheet every day or so. for some reason, I can delete files using the .setTrashed(True) and the file will delete, but i get an error saying 'You do not have authorization to perform that action. '
here is my code. any help would be appreciated.
function saveAsCSV() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
// create a folder from the name of the spreadsheet
var folder = DocsList.getFolder(ss.getName().toLowerCase().replace(/ /g,'_'));
for (var i = 0 ; i < sheets.length ; i++) {
var sheet = sheets[i];
// append ".csv" extension to the sheet name
fileName = sheet.getName() + ".csv";
// convert all available sheet data to csv format
var csvFile = convertRangeToCsvFile_(fileName, sheet);
// update a file in the Docs List with the given name and the csv data
var folder = DocsList.getFolder('fitbitdata_mk3');
folder.createFile(fileName, csvFile);
deleteDocByName('Sheet1.csv');
Logger.log('deleted');
// folder.createFile(fileName, csvFile); //i put it before the delete
}
Browser.msgBox('UPDATED Files are waiting in a folder named ' + folder.getName());
}
function deleteDocByName(fileName){
var docs=DocsList.find(fileName)
for(n=0;n<docs.length;++n){
if(docs[n].getName() == fileName){
var ID = docs[n].getId()
DocsList.getFileById(ID).setTrashed(true)
}
}
}
function convertRangeToCsvFile_(csvFileName, sheet) {
// get available data range in the spreadsheet
var activeRange = sheet.getDataRange();
try {
var data = activeRange.getValues();
var csvFile = undefined;
// loop through the data in the range and build a string with the csv data
if (data.length > 1) {
var csv = "";
for (var row = 0; row < data.length; row++) {
for (var col = 0; col < data[row].length; col++) {
if (data[row][col].toString().indexOf(",") != -1) {
data[row][col] = "\"" + data[row][col] + "\"";
}
}
// join each row's columns
// add a carriage return to end of each row, except for the last one
if (row < data.length-1) {
csv += data[row].join(",") + "\r\n";
}
else {
csv += data[row];
}
}
csvFile = csv;
}
return csvFile;
}
catch(err) {
Logger.log(err);
Browser.msgBox(err);
}
}
I had the same problem. Please star the issue on the issue tracker here.
https://code.google.com/p/google-apps-script-issues/issues/detail?id=4145&colspec=Stars%20Opened%20ID%20Type%20Status%20Summary%20Component%20Owner

Categories