I have been working on creating a script to allow employees in our shipping department to operate more efficiently. We use a barcode scanner to generate a CSV file - we use the following script to specify cells for the CSV; I'm looking to improve this so that the file is saved in a specific folder for easy sharing.
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var searchMenuEntries = [ {name: "Search in all files", functionName: "search"}];
var csvMenuEntries = [{name: "Save as CSV file", functionName: "saveAsCSV"},
{name: "Load from CSV file", functionName: "importFromCSV"}];
ss.addMenu("Search Google Drive", searchMenuEntries);
ss.addMenu("CSV", csvMenuEntries);
}
function saveAsCSV() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Primary Time');
// append ".csv" extension to the sheet name
// Prompts the user for the file name
var fileName = Browser.inputBox("Save CSV file as (e.g. myCSVFile):");
// Check that the file name entered wasn't empty
if (fileName.length !== 0) {
// Add the ".csv" extension to the file name
fileName = fileName + ".csv";
// Convert the range data to CSV format
var csvFile = convertRangeToCsvFile_(fileName);
// Create a file in Drive with the given name, the CSV data and MimeType (file type)
DriveApp.createFile(fileName, csvFile, MimeType.CSV);
else {
Browser.msgBox("Error: Please enter a CSV file name.");
}
}
function convertRangeToCsvFile_(csvFileName) {
// Get the selected range in the spreadsheet
var ws = SpreadsheetApp.getActiveSpreadsheet().getActiveSelection();
try {
var data = ws.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 have 2 options for you:
Use File.moveTo(destination) to move your newly created file to your target folder.
Sample code:
function option1(){
var targetFolderId ='1QHe2zCebXBZxiplAfVZpO1dhxxxx';
var csvFile = "Sample Content";
var folder = DriveApp.getFolderById(targetFolderId);
var file = DriveApp.createFile("SampleFile1.csv", csvFile, MimeType.CSV);
file.moveTo(folder);
}
Use Advanced Drive Service to create a file within a specific parent folder
Sample Code:
function option2(){
var targetFolderId ='1QHe2zCebXBZxiplAfVZpO1dhxxxx';
var content = "Sample Content";
var resource = {
title: "SampleFile2.csv",
mimeType: "text/csv",
parents: [{id:targetFolderId}]
}
var blob = Utilities.newBlob(content,"text/csv");
var file = Drive.Files.insert(resource,blob);
Logger.log(file);
}
Output:
Related
I have a sheet named "IMS Import" and I am trying to export the range A3:E to a CSV file by a Google Apps script which will be triggered by a button. The length of the range to be exported changes from week to week so I only want to capture the last populated row. I have the following script but I get a Google error "403. That’s an error. We're sorry, but you do not have access to this page. That’s all we know.":
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var csvMenuEntries = [{name: "Download IMS Import File", functionName: "saveAsCSV"}];
ss.addMenu("Creating a Timetable", csvMenuEntries);
};
function saveAsCSV() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('IMS Import');
// create a folder from the name of the spreadsheet
var folder = DriveApp.createFolder(ss.getName().toLowerCase().replace(/ /g,'_') + '_csv_' + new Date().getTime());
// 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
var file = folder.createFile(fileName, csvFile);
//File downlaod
var downloadURL = file.getDownloadUrl().slice(0, -8);
showurl(downloadURL);
}
function showurl(downloadURL) {
//Change what the download button says here
var link = HtmlService.createHtmlOutput('Click here to download');
SpreadsheetApp.getUi().showModalDialog(link, 'Your CSV file is ready!');
}
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 = 2; 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 get the error at this point in the script:
SpreadsheetApp.getUi().showModalDialog(link, 'Your CSV file is ready!');
I am hoping someone can help me to get a functioning script so that it creates a CSV from A3 to the last populated row.
If you only want the last row of the range change this
var activeRange = sheet.getDataRange();
to this:
var activeRange = sheet.getRange(sheet.getLastRow(),1,1,sheet.getLastColumn());
As far as page access goes I can't be sure. Perhaps you're logged into to two different accounts.
This is an additional question off of the related post: Adding Replace Existing File to GmailToDrive App Script answered by #Tanaike.
I'm trying to use the code from the previous post with the Edit function with an xlsx file. Everything seems to be working fine where it grabs the file and saves it and it even updated the modified date in the google drive folder. However, the content of the excel file does not change from the original. I've enabled the Drive API. Is this compatible with xlsx file types? Is there something additional needed to actually update the content in the file and not just the metadata?
// GLOBALS
//Array of file extension which you would like to extract to Drive
var fileTypesToExtract = ['xlsx'];
//Name of the folder in google drive i which files will be put
var folderName = 'YourfolderName;
//Name of the label which will be applied after processing the mail message
var labelName = 'Saved2';
function GmailToDrive(){
//build query to search emails
var query = '';
//filename:jpg OR filename:tif OR filename:gif OR fileName:png OR filename:bmp OR filename:svg'; //'after:'+formattedDate+
for(var i in fileTypesToExtract){
query += (query === '' ?('filename:'+fileTypesToExtract[i]) : (' OR filename:'+fileTypesToExtract[i]));
}
query = 'in:inbox label:MyCustomLabel has:attachment ' + query;
var threads = GmailApp.search(query);
var label = getGmailLabel_(labelName);
var parentFolder;
if(threads.length > 0){
parentFolder = getFolder_(folderName);
}
var root = DriveApp.getRootFolder();
for(var i in threads){
var mesgs = threads[i].getMessages();
for(var j in mesgs){
//get attachments
var attachments = mesgs[j].getAttachments();
for(var k in attachments){
var attachment = attachments[k];
var isDefinedType = checkIfDefinedType_(attachment);
if(!isDefinedType) continue;
var attachmentBlob = attachment.copyBlob();
var existingFile = DriveApp.getFilesByName(attachment.getName());
if (existingFile.hasNext()) {
var file = existingFile.next();
Drive.Files.update({}, file.getId(), attachmentBlob);
} else { // Added
var file = DriveApp.createFile(attachmentBlob); // Added
parentFolder.addFile(file); // Added
root.removeFile(file); // Added
}
}
}
threads[i].addLabel(label);
}
}
//This function will get the parent folder in Google drive
function getFolder_(folderName){
var folder;
var fi = DriveApp.getFoldersByName(folderName);
if(fi.hasNext()){
folder = fi.next();
}
else{
folder = DriveApp.createFolder(folderName);
}
return folder;
}
//getDate n days back
// n must be integer
function getDateNDaysBack_(n){
n = parseInt(8);
var date = new Date();
date.setDate(date.getDate() - n);
return Utilities.formatDate(date, Session.getScriptTimeZone(), 'yyyy/MM/dd');
}
function getGmailLabel_(name){
var label = GmailApp.getUserLabelByName(name);
if(!label){
label = GmailApp.createLabel(name);
}
return label;
}
//this function will check for filextension type.
// and return boolean
function checkIfDefinedType_(attachment){
var fileName = attachment.getName();
var temp = fileName.split('.');
var fileExtension = temp[temp.length-1].toLowerCase();
if(fileTypesToExtract.indexOf(fileExtension) !== -1) return true;
else return false;
}
Because .xlsx is the Excel format, Apps Script can't modify its content because it's not a Google product, it's like trying to modify a pdf using Apps Script, but don't worry, you could convert the .xlsx file into the native Google Spreadsheet format and then handle it like a normal Google Spreadsheet. This function will do the conversion for you:
// this Function will convert your .xlsx files into native Google Spreadsheet format
function convertExceltoGoogleSpreadsheet(parentFolder) {
var files = parentFolder.getFiles();
while(files.hasNext()){
var file = files.next();
// If the file contains the .xlsx extention in its name
// then it will return an array with length 2
var filename = file.getName().split(/.xlsx?/);
if(filename.length > 1){
// build info to create the new file with Google Spreadsheet format
var resource = {
title: filename[0],
mimeType: MimeType.GOOGLE_SHEETS,
parents: [{id: parentFolder.getId()}],
};
// Return the response after creating the file
return Drive.Files.insert(resource, file.getBlob());
}
}
}
Then, use that function in this part of your code:
...
var attachmentBlob = attachment.copyBlob();
var existingFile = DriveApp.getFilesByName(attachment.getName());
if (existingFile.hasNext()) {
var file = existingFile.next();
Drive.Files.update({}, file.getId(), attachmentBlob);
} else {
var file = DriveApp.createFile(attachmentBlob)
parentFolder.addFile(file);
root.removeFile(file);
}
// Let's change the format and insert a "Hello world" message
// ----START----
var spreadSheetResponse = convertExceltoGoogleSpreadsheet(parentFolder);
var spreadSheetId = spreadSheetResponse.getId()
var sheet = SpreadsheetApp.openById(spreadSheetId).getSheets()[0];
sheet.getRange(1, 1).setValue("Hello world");
// ----END----
...
Notice
In my code I left the .xlsx file in the Drive, if you want you could delete it after converting it iinto the native Google Spreadsheet format
Docs
This is what I used to help you:
SpreadsheetApp
Drive - Class File
I have a Google sheet want to export as CSV file. But there are 2 columns in the sheet I don't want to export.
For example, in the picturecolumn, I don't want to export column "N" and "P"
Here are the Apps Script code I wrote for export
function menu() {
var ui = SpreadsheetApp.getUi();
var menu = ui.createMenu('Menu');
var item = menu.addItem('PICC', 'picc');
var item2 = menu.addItem('Export to CSV', 'csv');
item.addToUi();
item2.addToUi()
};
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var csvMenuEntries = [{name: "Download Primary Time File", functionName: "saveAsCSV"}];
//ss.addMenu("Creating a Timetable", csvMenuEntries);
var ui = SpreadsheetApp.getUi();
var menu = ui.createMenu('Menu');
var item = menu.addItem('PICC', 'picc');
var item2 = menu.addItem('Export to CSV', 'csv');
item.addToUi();
item2.addToUi()
};
function saveAsCSV() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("sheet1");
// create a folder from the name of the spreadsheet
var folder = DriveApp.createFolder(ss.getName().toLowerCase().replace(/ /g,'_') + '_csv_' + new Date().getTime());
// 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
var file = folder.createFile(fileName, csvFile);
//File downlaod
var downloadURL = file.getDownloadUrl().slice(0, -8);
showurl(downloadURL);
}
function showurl(downloadURL) {
var app = UiApp.createApplication().setHeight('60').setWidth('150');
//Change what the popup says here
app.setTitle("Your timetable CSV is ready!");
var panel = app.createPopupPanel()
//Change what the download button says here
var link = app.createAnchor('Click here to download', downloadURL);
panel.add(link);
app.add(panel);
var doc = SpreadsheetApp.getActive();
doc.show(app);
}
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 = 1; 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);
}
}
As you can see, I used for loop to export the rows and columns, how can I make change to let the two columns not showing in the export CSV
How about this modification?
Modification points :
Modify convertRangeToCsvFile_().
From data retrieved by getValues(), it removes the columns "N" and "P".
In order to reflect this, please modify as follows.
From :
var data = activeRange.getValues();
var csvFile = undefined;
To :
var data = activeRange.getValues();
data = data.map(function(e){return e.filter(function(_, i){return i != 13 && i != 15})}); // Added
var csvFile = undefined;
If I misunderstand your question, please tell me. I would like to modify it.
I have an spreadsheet with 4 sheets that I need in .CSV format. By now, I have a script that sends me the .csv files to my email, but I need to automacally save it into a google drive folder, do you have any ideas ?
This is my actual script:
function Csv(){
var ss = SpreadsheetApp.openById('spreadsheetID');
var url1 = "https://docs.google.com/spreadsheets/d/spreadsheetID/gviz/tq?tqx=out:csv&sheet=Sheet1";
var url2 = "https://docs.google.com/spreadsheets/d/spreadsheetID/gviz/tq?tqx=out:csv&sheet=Sheet2";
var url3 = "https://docs.google.com/spreadsheets/d/spreadsheetID/gviz/tq?tqx=out:csv&sheet=Sheet3";
var url4 = "https://docs.google.com/spreadsheets/d/spreadsheetID/gviz/tq?tqx=out:csv&sheet=Sheet4";
var params = {
method : "get",
headers : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
muteHttpExceptions: true
};
var blob1 = UrlFetchApp.fetch(url1, params).getBlob();
blob1.setName("File1" +".csv");
var blob2 = UrlFetchApp.fetch(url2, params).getBlob();
blob2.setName("File2" +".csv");
var blob3 = UrlFetchApp.fetch(url3, params).getBlob();
blob3.setName("File3" +".csv");
var blob4 = UrlFetchApp.fetch(url4, params).getBlob();
blob4.setName("File4" +".csv");
MailApp.sendEmail("myemail#gmail.com", "Subject", "Body", {attachments: [blob1,blob2,blob3,blob4]});
}
Thanks!
you can check out the below script. Hope it will help you to manage your sheets as you expected.
/*
* script to export data in all sheets in the current spreadsheet as individual csv files
* files will be named according to the name of the sheet
* author: Shotez
*/
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);
}
}
After running the script just check your google drive for the folder which is containing the .csv files.
I use the Query https://www.googleapis.com/drive/v3/files/FileID/export?mimeType=text/tab-separated-values to download Google Sheets. My sheet has different tabs in it. Is there a way that I can download all the tabs in the sheet or a particular sheet with the name? Thanks in advance.
Based from this link, you can download a specific sheet using gID. Each sheet has a gID and you can find the gID of specific sheet in the URL of spreadsheet. You can use this link to download specific sheet https://docs.google.com/spreadsheets/d/<KEY>/export?format=xlsx&gid=<GID>.
Example:
https://docs.google.com/spreadsheets/d/1D5vzPaOJOx402RAEF41235qQTOs28_M51ee5glzPzj0/export?format=xlsx&gid=1990092150
KEY is the unique ID of spreadsheet.
You may also refer with this thread on how to export sheets in a spreadsheet to csv in Google Apps using Google Apps Script.
Couldn't find any built in way to do it so I wrote a script to use in Google Sheets
Just paste it in script editor and run
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 = DocsList.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 waitig 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);
}
}