I'm fairly new to the world of aumating sheets with scripts and ma still firmly in the 'cobble other peoples code together' phase of writing scripts.
I have a schedule in Google Sheets that display's different department overviews based on the contents of a cell ('B1'). I'm attempting to iterate a list of values through that cell and in each instance export the resulting sheet to pdf.
So far I've got it working, my next hurdle is getting it to export the pdf in landscape rather than portrait. I can see implementations using url export but I'm not confident enough (read keep breaking everything) to implement that in to the script below.
Any help greatly appreciated!
function PrintPDF(){
var df = DriveApp.getFolderById("folderID");
var arr = new Array();
var files = df.getFiles();
while( files.hasNext() ) {
var f = files.next();
arr.push( [ [ f.getId() ] , [ f.getLastUpdated() ] ] );
}
arr.sort( sortFunction );
function sortFunction( a , b ) {
var aDate = new Date(a[1]);
var bDate = new Date(b[1]);
if ( aDate === bDate ) return 0;
else if ( aDate < bDate ) return 1;
else return -1;
};
for( var i=0 ; i<arr.length ; i++ )
DriveApp.getFileById( arr[i][0] ).setTrashed( true );
//Create array of show codes
var Dss = SpreadsheetApp.getActive().getSheetByName('Value Lists')
var Tss = SpreadsheetApp.getActive().getSheetByName('PrintSheet')
var Shows = Dss.getRange('K3:K11').getValues()
var Count = Shows.length
var Code = Tss.getRange('B1')
Logger.log(Count)
Logger.log(Shows)
for (i=0;i<Count;i++){
Code.setValue(Shows[i])
HideBlankRows ()
const folderName = `foldername`;
var ss =SpreadsheetApp.getActiveSpreadsheet()
var name = "Department - "+ss.getRange('B1').getValue()
Logger.log(name)
DriveApp.getFoldersByName(folderName)
.next()
.createFile(ss
.getBlob()
.getAs(`application/pdf`)
.setName(name)
);
}
Code.setValue('')
}
function HideBlankRows() {
var ss = SpreadsheetApp.getActive();
var sheets = ss.getSheets(); // array of all sheet objects in ss
var numSheets = ss.getNumSheets(); // count of sheets
for(sheet in sheets) {
if(sheets[sheet].getSheetName() == "AA") continue;
//show all the rows
sheets[sheet].showRows(1, sheets[sheet].getMaxRows());
//get data from column A
var data = sheets[sheet].getRange('A:A').getValues();
Logger.log(data)
//iterate over all rows
for(var i=0; i< data.length; i++){
//compare column, if no, then hide row
if(data[i][0] == 'Yes'){
sheets[sheet].hideRows(i+1);
}
}
}
}
Your code looks a bit cryptic to me. I don't understand why do you need the arr array if you nowhere use it. Etc.
But whatever. Suppose the code works fine and all you need is to save a PDF file with landscape orientation. In this case you need to replace these lines in your code:
DriveApp.getFoldersByName(folderName)
.next()
.createFile(ss
.getBlob()
.getAs(`application/pdf`)
.setName(name)
);
With this:
savePDFs(name);
And add at the end of your script the function savePDFs():
function savePDFs(name) {
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var url = ss.getUrl();
//remove the trailing 'edit' from the url
url = url.replace(/edit$/, '');
//additional parameters for exporting the sheet as a pdf
var url_ext = 'export?exportFormat=pdf&format=pdf' + //export as pdf
//below parameters are optional...
'&size=a4' + //paper size
'&portrait=false' + //orientation, false for landscape, true for portrait
'&fitw=true' + //fit to width, false for actual size
'&sheetnames=false&printtitle=false&pagenumbers=false' + //hide optional headers and footers
'&gridlines=false' + //hide gridlines
'&fzr=false' + //do not repeat row headers (frozen rows) on each page
'&gid=' + sheet.getSheetId(); //the sheet's Id
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url + url_ext, {
headers: { 'Authorization': 'Bearer ' + token }
});
var blob = response.getBlob().setName(name + '.pdf');
DriveApp.createFile(blob);
}
This function was taken from here: Change document orientation when exporting to PDF
Related
I am currently new to the google sheet script. I'm doing a simple report generator in google sheet using script. I already have a script that saves a generated pdf file to the google drive. In my google sheet there is a cell referenced to the main data source with dropdown data validation selecting the email of the person and will generate the other details (it a reference also based from that email in the same sheet). what I want is, when I run the script to save pdf file, it should automatically generate pdf file for each item in the dropdown validation list. Is this possible? Anyone who know this please.
this is my code that generate pdf file to the drive (i got this also from the net and made some changes)... thank you so much in advance.
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet2 = ss.getSheetByName('ID');
var gdid1 = sheet2.getRange('B1').getValue();
var gdid2 = sheet2.getRange('B4').getValue();
function onOpen() {
var ui = SpreadsheetApp.getUi()
ui.createMenu('ExportGDrive')
.addItem('Export BasicED', 'exportBasicED')
.addItem('Export College', 'exportCollege')
.addToUi()
}
function _exportBasic(blob, fileName, spreadsheet) {
blob = blob.setName(fileName)
var folder = DriveApp.getFolderById(gdid1)
var pdfFile = folder.createFile(blob)
// Display a modal dialog box with custom HtmlService content.
const htmlOutput = HtmlService
.createHtmlOutput('<p>Click to open ' + fileName + '</p>')
.setWidth(300)
.setHeight(80)
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Export Successful')
}
function _exportCollege(blob, fileName, spreadsheet) {
blob = blob.setName(fileName)
var folder = DriveApp.getFolderById(gdid2)
var pdfFile = folder.createFile(blob)
// Display a modal dialog box with custom HtmlService content.
const htmlOutput = HtmlService
.createHtmlOutput('<p>Click to open ' + fileName + '</p>')
.setWidth(300)
.setHeight(80)
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Export Successful')
}
function exportAsPDF() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
var blob = _getAsBlob(spreadsheet.getUrl())
_exportBlob(blob, spreadsheet.getName(), spreadsheet)
}
function _getAsBlob(url, sheet, range) {
var rangeParam = ''
var sheetParam = ''
if (range) {
rangeParam =
'&r1=' + (range.getRow() - 1)
+ '&r2=' + range.getLastRow()
+ '&c1=' + (range.getColumn() - 1)
+ '&c2=' + range.getLastColumn()
}
if (sheet) {
sheetParam = '&gid=' + sheet.getSheetId()
}
// A credit to https://gist.github.com/Spencer-Easton/78f9867a691e549c9c70
// these parameters are reverse-engineered (not officially documented by Google)
// they may break overtime.
var exportUrl = url.replace(/\/edit.*$/, '')
+ '/export?exportFormat=pdf&format=pdf'
+ '&size=LETTER'
+ '&portrait=true'
+ '&fitw=true'
+ '&top_margin=0.75'
+ '&bottom_margin=0.75'
+ '&left_margin=0.7'
+ '&right_margin=0.7'
+ '&sheetnames=false&printtitle=false'
+ '&pagenum=UNDEFINED' // change it to CENTER to print page numbers
+ '&gridlines=FALSE'
+ '&fzr=FALSE'
+ sheetParam
+ rangeParam
Logger.log('exportUrl=' + exportUrl)
var response
var i = 0
for (; i < 5; i += 1) {
response = UrlFetchApp.fetch(exportUrl, {
muteHttpExceptions: true,
headers: {
Authorization: 'Bearer ' + ScriptApp.getOAuthToken(),
},
})
if (response.getResponseCode() === 429) {
// printing too fast, retrying
Utilities.sleep(3000)
} else {
break
}
}
if (i === 5) {
throw new Error('Printing failed. Too many sheets to print.')
}
return response.getBlob()
}
function exportCurrentSheetAsPDF() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
var currentSheet = SpreadsheetApp.getActiveSheet()
// Change the Cell for the name of the file (example: B3 for current sheet)
var blob = _getAsBlob(spreadsheet.getUrl(), currentSheet)
_exportBlob(blob, SpreadsheetApp.getActiveSheet().getRange('B3').getValue(), spreadsheet)
}
function exportBasicED() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
var sheet1 = spreadsheet.getSheetByName('Generate-Basic Ed');
var name = sheet1.getRange('B3').getValue();
// Change the Cell for the name of the file (example: B3 for current sheet)
var blob = _getAsBlob(spreadsheet.getUrl(), sheet1)
_exportBasic(blob, name, spreadsheet)
}
function exportCollege() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
var sheet1 = spreadsheet.getSheetByName('Generate-College');
var name = sheet1.getRange('B3').getValue();
// Change the Cell for the name of the file (example: B3 for current sheet)
var blob = _getAsBlob(spreadsheet.getUrl(), sheet1)
_exportCollege(blob, name, spreadsheet)
}
Try
function nextItem() {
var sh = SpreadsheetApp.getActive();
var data = sh.getRange('myValidationList').getValues();
for (var i = 0; i < data.length; i++) {
sh.getRange('A2').setValue(data[i][0]);
SpreadsheetApp.flush();
// here you can call the script to send pdf
Utilities.sleep(1000);
}
};
assuming that myValidationList is the list of valid data, avd A2 the cell in wich the validation applies.
I have a sheet, with some tabs, in one tab i make statement for my clients, there i select a customer in B2 and using a query formula i get the desired data, after that i have a script to first hide blank rows and then send that email with the pdf as attachment, and i do thins only when need send that email.
this is my script:
function HideEdoCta() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName('Edo Cta');
var lastRow = sheet.getLastRow();
var range = sheet.getRange(1, 4, lastRow, 1);
var data = range.getValues();
//Rows
for (var i = 0; i < data.length; i++) {
if (data[i][0] == 1) {
sheet.hideRows(i + 1)
}
}
sheet.hideColumns(4, 1)
}
function UnHideEdoCta() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Edo Cta');
sheet.unhideRow(sheet.getDataRange());
}
function MailEdoCta(email, subject, body, sheetName) {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getSheetByName('Edo Cta');
var valueToCheck = sheet.getRange('C1').getValue();
if (valueToCheck == true && casa != '') {
HideEdoCta()
SpreadsheetApp.flush()
var email = sheet.getRange('D1').getValue(); // Enter the required email address here
var casa = sheet.getRange('B2').getValue();
var subject = 'Estado de Cuenta Sky';
var body =
"Hola, <strong>" + casa + "</strong><br><br>" +
"xxx.<br>" +
"-- <br>" +
"<strong>xxx</strong><br>"
;
// Base URL
var url = "https://docs.google.com/spreadsheets/d/SS_ID/export?".replace("SS_ID", ss.getId());
var url_ext = 'exportFormat=pdf&format=pdf' // export as pdf / csv / xls / xlsx
+ '&size=letter' // paper size legal / letter / A4
+ '&portrait=true' // orientation, false for landscape
+ '&scale=1' // 1= Normal 100% / 2= Fit to width / 3= Fit to height / 4= Fit to Page
+ '&fitw=true&source=labnol' // fit to page width, false for actual size
+ '&sheetnames=false&printtitle=false' // hide optional headers and footers
+ '&pagenumbers=true&gridlines=false' // hide page numbers and gridlines
+ '&fzr=false' // do not repeat row headers (frozen rows) on each page
+ '&gid='; // the sheet's Id
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url + url_ext + sheet.getSheetId(), {
headers: {
'Authorization': 'Bearer ' + token
}
}).getBlob().setName(sheet.getName() + ".pdf");
// Uncomment the line below to save the PDF to the root of your drive.
// var newFile = DriveApp.createFile(response).setName(sheet.getName() + ".pdf")
GmailApp.sendEmail(email, subject, "",
{ name: 'xxx', htmlBody: body, attachments: [response] }
);
SpreadsheetApp.flush()
UnHideEdoCta()
sheet.getRange('C1').setValue(false)
sheet.getRange('B2').clearContent()
}
else {
sheet.getRange('C1').setValue(false)
}
}
in this script i have a validation that if there is a customer selected in B2 and C1 is true, send the email, because the trigger is set to run every minute.
now what i need is send the same email, every 5th of the month to all my customers automatically (i only have 24 customers)
how can i make this possible without selecting one by one ?
any help please ?
here is a sample sheet with sample data
Try this
function mailing() {
var doc = SpreadsheetApp.getActive();
var sh = SpreadsheetApp.getActiveSheet();
var data = doc.getRange('listOfCustomers').getValues();
for (var i = 0; i < data.length; i++) {
if (data[i][1]) {
sh.getRange('B2').setValue(data[i][0]);
SpreadsheetApp.flush();
Utilities.sleep(1000);
}
}
};
a copy of your spreadsheet would have been appreciated for testing.
In response to your comment from above:
This is the basic script that reads the information spreadsheet and calls the email function along with an object that identifies the template and other important information.
function sendEmails() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Emails');
const [hA, ...dt] = sh.getDataRange().getValues();
const vs = dt.filter(r => r[0] && r[1] && r[2] && r[3] && r[4] == 'Send' && r[5]);
const idx = {};
hA.forEach((h, i) => { idx[h] = i; });
vs.forEach(function (r) {
let obj = { index: idx, row: r }
this[r[5]](obj);//This executes the function named in r[5] and passes it obj
});
}
This is one of the functions that sends emails or creates a draft:
function sendEmails103(obj) {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('libImages');
const [hA, ...dt] = sh.getDataRange().getValues();
let idx = {};
hA.forEach((h, i) => idx[h] = i);
let imgObj = {};
vs = dt.filter(r => r[idx['filename']] == obj.row[obj.index['htmlFile']])
vs.forEach((r, i) => {
let params = { muteHttpExceptions: true, headers: { "Authorization": "Bearer " + ScriptApp.getOAuthToken() } };
let aurl = "https://photoslibrary.googleapis.com/v1/mediaItems/" + r[idx['mediaItemId']]
let resp = JSON.parse(UrlFetchApp.fetch(aurl, params).getContentText());
let burl = `${resp.baseUrl}=w${r[idx['maxwidth']]}-h${r[idx['maxheight']]}`
imgObj[r[idx['Key']]] = UrlFetchApp.fetch(burl).getBlob();
});
let htmlTemplate = HtmlService.createTemplateFromFile(obj.row[obj.index['htmlFile']]);
let html = htmlTemplate.evaluate().getContent();
if (html) {
if (obj.row[obj.index['operation']] == 'Create Draft') {
GmailApp.createDraft(obj.row[obj.index['Recipients']], obj.row[obj.index['Subject']], '', { htmlBody: html, inlineImages: imgObj, replyTo: obj.row[obj.index['replyTo']] });
} else {
GmailApp.sendEmail(obj.row[obj.index['Recipients']],obj.row[obj.index['Subject']],'',{htmlBody:html,inlineImages:imgObj,replyTo: obj.row[obj.index['replyTo']]});
}
}
}
This probably not for everyone, but I like having more room to customize my letters and having been a web developer for a long time I'm quite comfortable composing letters in html which is probably not true of everyone.
I have a Google Apps Script that automatically extracts data from a Google Sheet and inserts it into a pre specified template. The data is found using unique tagNumbers/identifiers.
The data being extracted includes 3 signatures. I can only extract one of these signatures before I encounter the aforementioned error: TypeError: Cannot read property 'getBlob' of undefined.
This code is being used in two different functions, using all the same variables and names. I have tried changing variable names but this has resulted in the same TypeError.
The spreadsheet can be found here.
The script is here.
And the document template being filled is here.
Here is the code.
function electInstallSignature(row, body){
var signature = row[17];
var sign = signature.substring(signature.indexOf("/") + 1);
var sigFolder = DriveApp.getFolderById("16C0DR-R5rJ4f5_2T1f-ZZIxoXQPKvh5C");
var files = sigFolder.getFilesByName(sign);
var n = 0;
var file;
while(files.hasNext()){
file = files.next();
n++;
} if(n>1){
SpreadsheetApp.getUi().alert('there is more than one file with this name' + sign);
}
var sigElectInstaller = "%SIGNELECTINSTALL%";
var targetRange = body.findText(sigElectInstaller); // Finding the range we need to focus on
var paragraph = targetRange.getElement().getParent().asParagraph(); // Getting the Paragraph of the target
paragraph.insertInlineImage(1, file.getBlob());// As there are only one element in this case you want to insert at index 1 so it will appear after the text // Notice the .getBlob()
paragraph.replaceText(sigElectInstaller, ""); // Remove the placeholder
}
function commEngineerSignature(row, body){
var signature = row[35];
var sign = signature.substring(signature.indexOf("/") + 1);
var sigFolder = DriveApp.getFolderById("16C0DR-R5rJ4f5_2T1f-ZZIxoXQPKvh5C");
var files = sigFolder.getFilesByName(sign);
var n = 0;
var file;
while(files.hasNext()){
file = files.next();
n++;
} if(n>1){
SpreadsheetApp.getUi().alert('there is more than one file with this name' + sign);
}
var sigCommEngineer = "%SFCE%";
var targetRange = body.findText(sigCommEngineer); // Finding the range we need to focus on
var paragraph = targetRange.getElement().getParent().asParagraph(); // Getting the Paragraph of the target
paragraph.insertInlineImage(1, file.getBlob());// As there are only one element in this case you want to insert at index 1 so it will appear after the text // Notice the .getBlob()
paragraph.replaceText(sigCommEngineer, ""); // Remove the placeholder
}
As you can see, the code is the exact same in both functions, but only works in the electInstallSignature(row, body) function.
Below you can find where the row and body parameters are declared.
function chooseRowMethodI(templateId, rowNumber){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
var data = sheet.getRange(2, 2, 10, 41).getValues();//starting with row 2 and column 1 as our upper-left most column, get values from cells from 1 row down, and 15 columns along - hence (2,1,1,15)
var docTitle = sheet.getRange(2, 2, 10, 1).getValues();//this is grabbing the data in field B2
var docTitleTagNumber = sheet.getRange(2, 5, 11, 1).getValues();
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1;
var yyyy = today.getFullYear();
today = dd + '/' + mm + '/' + yyyy;
for(var i = 0; i < values.length; i++){
for(var j = 0; j < values[i].length; j++){
if(values[i][j] == response){
Logger.log(i);
var row = data[rowNumber];
var docId = DriveApp.getFileById(templateId).makeCopy().getId();
var doc = DocumentApp.openById(docId);
var body = doc.getActiveSection();
//************************** All Instruments data in here**********************
instrumentDetails(body, row);
electInstallSignature(row, body);
commEngineerSignature(row, body);
doc.saveAndClose();
var file = DriveApp.getFileById(doc.getId());
var newFolder = DriveApp.getFolderById("1Jylk3uO_WU0ClLQdm9y-mwRfHxlh2Ovn");
newFolder.addFile(file);
var newDocTitle = docTitle[i - 1][0];
var newDocTagNumber = docTitleTagNumber[i - 1][0];
doc.setName(newDocTitle + " " + newDocTagNumber + " " + today);
}
}
}
}
Should it be required, I have included the function where everything is run from (note that any ui and user input code is tabbed out to avoid having to navigate back to the spreadsheet every time the code is run).
var response = "FT101";
function chooseRow(){
// var ui = SpreadsheetApp.getUi(); // Same variations.
// var result = ui.prompt('Please enter the Tag number of the row you wish to print.', ui.ButtonSet.OK_CANCEL);
//
// // Process the user's response.
// var button = result.getSelectedButton();
// response = result.getResponseText();
// if (button == ui.Button.OK) {
// // User clicked "OK".
// ui.alert('Your tag number is' + response + '.');
// } else if (button == ui.Button.CANCEL) {
// // User clicked X in the title bar.
// ui.alert('You closed the dialog.');
// return 'the end';
// }
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getDataRange();
var values = dataRange.getValues();
var category = sheet.getRange(2, 3, 11, 1).getValues();//Needs to be verified to ensure correct cell is chosen by script
var tags = sheet.getRange(2, 5, 11, 1).getValues();//Needs to be verified to ensure correct cell is chosen by script
for(var i = 0; i < tags.length; i++){
if(tags[i][0] == response && category[i][0] == "Instrument"){
var templateId = "1N3o951ECS5CAVGE6UgqBiCPC7H7LiJbL7Cd59G1xTnA";
chooseRowMethodI(templateId, i);
return "";
} else if(tags[i][0] == response && category[i][0] == "Motor" || tags[i][0] == response && category[i][0] == "Valve"){
var templateId = "1cSPD23qFd-34-IIr5eJ5a5OgHp9YR6xav9T28Y4Msec";
chooseRowMethodMV(templateId, i);
return "";
}
}
}
This errors TypeError: Cannot read property 'getBlob' of undefined means that the object you are trying to getBlob from it does not have any blob data.
The only difference with the frist function and the second one is the first line: row[17] instead of row[35] this means the following:
var signature = row[17];
var sign = signature.substring(signature.indexOf("/") + 1);
var sigFolder = DriveApp.getFolderById("16C0DR-R5rJ4f5_2T1f-ZZIxoXQPKvh5C");
var files = sigFolder.getFilesByName(sign);
var n = 0;
var file;
while(files.hasNext()){
file = files.next();
n++;
} if(n>1){
SpreadsheetApp.getUi().alert('there is more than one file with this name' + sign);
}
So, you are probably never accessing to the while loop:
while(files.hasNext())
because var files = sigFolder.getFilesByName(sign); never had a next, and thus, as file is not initialized, it is undefined.
In summary, the error you are getting is:
file is undefined
This means that you never assigned anything on this variable, which only happens if you never accessed the while, which only happens if files never had a next.
Which happens because there aren't any files at all there, this means that there isn't any file with the name sign on the sigFolder. Or that the row[17] does not contain any substantial information about the filename you want to access.
So, check this.
Also, take into account the following documentation about iterators like the one you are handling on files:
When you do files.next() you are accesing the first element of the iterator:
File iterator
General documentation on JavaScript iterators:
Iterators and generators on Javascript
My script is looping through a list, at each index it is saving a sheet in my workbook as a PDF, then saving it to my google drive folder. There are 7 people in the list. The problem is that my script throws a 429 Error after the 6th PDF is exported. I am trying to figure out how to solve this error but I am quite new to google scripting so I need some help in the right direction.
Error Image
function ToPortrait() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var validation_sheet = ss.getSheetByName('ValidDSM');
var lastRow = validation_sheet.getLastRow();
var inputs = ss.getSheetByName('ValidDSM').getRange('A2:A'+lastRow).getValues();
var sheet2 = ss.getSheetByName('DSM');
var tab = ss.getSheetByName('DSMD');
var url = ss.getUrl().replace(/edit$/,'');
var sheets = ss.getSheets();
var optSheetId = 1123194386;
var options = {
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()
}
}
// Loop through List of 7
for (var i = 0; i < inputs.length; i++){
sheet2.getRange('B3').setValue(inputs[i][0]);
SpreadsheetApp.flush();
Utilities.sleep(500);
// Loop through all sheets, generating PDF files.
//for (var i=0; i<sheets.length; i++) {
//var sheet = sheets[i];
// If provided a optSheetId, only save it.
// if (optSheetId && optSheetId !== sheet.getSheetId()) continue;
//additional parameters for exporting the sheet as a pdf
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+ '&gid=' + tab.getSheetId() //the sheet's Id
// following parameters are optional...
+ '&size=letter' // paper size
+ '&portrait=false' // orientation, false for landscape
+ '&fitw=true' // fit to width, false for actual size
+ '&sheetnames=false&printtitle=false&pagenumbers=false' //hide optional headers and footers
+ '&gridlines=false' // hide gridlines
+ '&fzr=false'; // do not repeat row headers (frozen rows) on each page
// Get folder containing spreadsheet, for later export
var name = sheet2.getRange('B3').getValue();
var folderID = "1IsffOYYQOHZJKggUzRTntfjmJKN0F6ga"; // Folder id to save in a folder.
var folder = DriveApp.getFolderById(folderID);
var response = UrlFetchApp.fetch(url + url_ext, options)
var blob = response.getBlob().setName(name);
//save the pdf to drive
folder.createFile(blob);
}
}
I expect all 7 PDFs to be exported but only 6 are.
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.