Using Google Apps Script to save a single sheet from a spreadsheet as pdf in a specific folder - pdf

I am using a Google spreadsheet to prepare invoices and was looking for a simple script that saves a sheet, where the invoice is in, in a "invoices" folder to build an archive.
I "borrowed" code from numerous contributors on Stackoverflow and youtube and came up with a code that works. I had to copy the invoice to a newly created spreadsheet, because it seems to be impossible to create a pdf from one single sheet in type spreadsheet. I also had to use a piece of code to move the pdf from the root to an "invoices" folder
The only thing I am not able to solve is that the spreadsheet created in line 6 consistes of 2 sheets. An empty one and a correctly copied one. The created pdf thus alsa has 2 sheets, one empty and one correct sheet.
Anyone got a clue how to solve this ?
By the way sometimes it takes some minutes before the pdf shows in the folders.
Below is the code
function generatePdf(){
//Create a temporary spreadsheet, to store the desired sheet from the spreadsheet in.
var originalSpreadsheet = SpreadsheetApp.getActive();
originalSpreadsheet.setActiveSheet(originalSpreadsheet.getSheets()[4]);
var name = "Testname"
var newSpreadsheet = SpreadsheetApp.create(name);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
sheet = originalSpreadsheet.getActiveSheet();
sheet.copyTo(newSpreadsheet);
//Save the desired sheet as pdf
var pdf = DriveApp.getFileById(newSpreadsheet.getId()).getAs('application/pdf');
var saveCopy = DriveApp.createFile(pdf);
//Delete temporary spreadsheet
DriveApp.getFilesByName(name).next().setTrashed(true);
//Move the pdf file from the rootfolder to the folder where invoices are to be stored.
var files = DriveApp.getRootFolder().getFiles();
while (files.hasNext()) {
var file = files.next();
var destination = DriveApp.getFolderById("0B3ok04PZOVbgLXA2dy14MVlLRXM");
destination.addFile(file);
var pull = DriveApp.getRootFolder();
pull.removeFile(file);
}
}

I'm not sure if you have encountered this code but you can try this:
function checkSheet() {
var sheetName = "Sheet1";
var folderID = "FOLDER_ID"; // Folder id to save in a folder.
var pdfName = "Invoice "+Date();
var sourceSpreadsheet = SpreadsheetApp.getActive();
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
var folder = DriveApp.getFolderById(folderID);
//Copy whole spreadsheet
var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(sourceSpreadsheet.getId()).makeCopy("tmp_convert_to_pdf", folder))
//delete redundant sheets
var sheets = destSpreadsheet.getSheets();
for (i = 0; i < sheets.length; i++) {
if (sheets[i].getSheetName() != sheetName){
destSpreadsheet.deleteSheet(sheets[i]);
}
}
var destSheet = destSpreadsheet.getSheets()[0];
//repace cell values with text (to avoid broken references)
var sourceRange = sourceSheet.getRange(1,1,sourceSheet.getMaxRows(),sourceSheet.getMaxColumns());
var sourcevalues = sourceRange.getValues();
var destRange = destSheet.getRange(1, 1, destSheet.getMaxRows(), destSheet.getMaxColumns());
destRange.setValues(sourcevalues);
//save to pdf
var theBlob = destSpreadsheet.getBlob().getAs('application/pdf').setName(pdfName);
var newFile = folder.createFile(theBlob);
//Delete the temporary sheet
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
}
Note:
While testing this code, it creates the pdf in an instant, but it may depend on the invoice template.
References:
Simple Google Apps Script to export a single sheet to PDF and email it to a contact list
Sample Template - Professional Invoice Template (for Testing Purpose)
Hope this helps!
UPDATE

Related

I need to Set Value the get URL in a cell

I am now need to convert the Google Sheet page to PDF, email to user and save the PDF format straightway to Google Drive.
And i need the Google Drive link after save it to Google Drive.
The steps from convert the Google Sheet to PDF, and i've done but I've stuck at getting the URL to be paste on the specific cells.
i know to get the URL using this code Logger.log(fileUrl)
But how to paste on cell the command ?
var changedFlag = false;
var TEMPLATESHEET='Boom-Report';
function emailSpreadsheetAsPDF() {
//Utilities.sleep(300000); //to pause for 60 seconds . Make sure photo completely upload to google sheet
DocumentApp.getActiveDocument();
DriveApp.getFiles();
// This is the link to my spreadsheet with the Form responses and the Invoice Template sheets
// Add the link to your spreadsheet here
// or you can just replace the text in the link between "d/" and "/edit"
// In my case is the text: 17I8-QDce0Nug7amrZeYTB3IYbGCGxvUj-XMt8uUUyvI
const ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1NVJOdFLBAgNFqSHhnHJYybjUlSqhv4hKI_HXJyhJ88E/edit");
// We are going to get the email address from the cell "B7" from the "Invoice" sheet
// Change the reference of the cell or the name of the sheet if it is different
const value = ss.getSheetByName("Source Email-Boom").getRange("X3").getValue();
const email = value.toString();
// Subject of the email message
const subject = ss.getSheetByName("Source Email-Boom").getRange("B3").getValue();
// Email Text. You can add HTML code here - see ctrlq.org/html-mail
const body = "Boom Lifts Inspection Report - Sent via Auto Generate PDI Report from Glideapps";
// Again, the URL to your spreadsheet but now with "/export" at the end
// Change it to the link of your spreadsheet, but leave the "/export"
const url = 'https://docs.google.com/spreadsheets/d/1NVJOdFLBAgNFqSHhnHJYybjUlSqhv4hKI_HXJyhJ88E/export?';
const exportOptions =
'exportFormat=pdf&format=pdf' + // export as pdf
'&size=A4' + // paper size letter / You can use A4 or legal
'&portrait=true' + // orientation portal, use false for landscape
'&fitw=true' + // fit to page width false, to get the actual size
'&sheetnames=false&printtitle=false' + // hide optional headers and footers
'&pagenumbers=false&gridlines=false' + // hide page numbers and gridlines
'&fzr=false' + // do not repeat row headers (frozen rows) on each page
'&gid=1832955909'; // the sheet's Id. Change it to your sheet ID.
// You can find the sheet ID in the link bar.
// Select the sheet that you want to print and check the link,
// the gid number of the sheet is on the end of your link.
var params = {method:"GET",headers:{"authorization":"Bearer "+ ScriptApp.getOAuthToken()}};
// Generate the PDF file
var response = UrlFetchApp.fetch(url+exportOptions, params).getBlob();
// Send the PDF file as an attachement
GmailApp.sendEmail("biha#equip-inc.com", subject, body, {
htmlBody: body,
attachments: [{
fileName: ss.getSheetByName("Source Email-Boom").getRange("B3").getValue().toString() +".pdf",
content: response.getBytes(),
mimeType: "application/pdf"
}]
});
// Save the PDF to Drive. (in the folder) The name of the PDF is going to be the name of the Company (cell B5)
const nameFile = ss.getSheetByName("Source Email-Boom").getRange("B3").getValue().toString() +".pdf"
const folderID = "1ZKWq9jWmeEQlxncuTPHssCFXC3Fidmxn";
DriveApp.getFolderById(folderID).createFile(response).setName(nameFile);
// create file URL
var SpreadsheetID = "1NVJOdFLBAgNFqSHhnHJYybjUlSqhv4hKI_HXJyhJ88E";
var ss2 = SpreadsheetApp.openById(SpreadsheetID);
var Sheetname2= "BL-Inspection Report";
var sheet2 = ss2.getSheetByName(Sheetname2);
// Get the last row based on the data range of a single column.
var lastRow2 = sheet2.getLastRow();
var lastColumn2 = sheet2.getLastColumn();
//EXAMPLE: Get the data range based on our selected columns range.
var dataRange2 = sheet2.getRange(1,1, lastRow2, lastColumn2);
var dataValues2 = dataRange2.getValues();
var dataMatch=[];
//***** */
// Loop through array and if condition met, add relevant
// background color.
var p=34 ; //Column No. for Name column AI:AI (Report No)
var filename = encodeURI(nameFile);
var files = DriveApp.getFilesByName(nameFile);
while (files.hasNext()) {
var file = files.next();
if (file) {
var fileUrl = file.getUrl();
};
};
////////////////HELP THIS PART////////////////////////////////
for ( j = 0 ; j < lastRow2 ; j++){
var zz=j;
var yy=dataValues2[j][34];
if(dataValues2[j][34] == subject){
var doclink = Logger.log(fileUrl);
var range = sheet2.getRange(j+1, 128);
range.setValue(doclink);
};
};
}
If cell B3 value in First Source is find in Google Drive, paste the URL in Column DX where the AI is same with First Source.
I believe your goal is as follows.
You want to search the file of filename subject retrieved from the cell "B3" of "Source Email-Boom" sheet from your Google Drive, and when the value of subject is found from the column "AI" of "BL-Inspection Report" sheet, you want to put the URL of the file to the column "AJ".
For my question of For example, you want to put the URL of the just created file?, from Yes of your replying, I understood that you wanted to put the URL of the just created file in this script.
In this case, how about the following modification? I thought that in this case, the file URL of the just created file can be directly retrieved from DriveApp.getFolderById(folderID).createFile(response).setName(nameFile). So, how about the following modification?
From:
DriveApp.getFolderById(folderID).createFile(response).setName(nameFile);
To:
var fileUrl = DriveApp.getFolderById(folderID).createFile(response).setName(nameFile).getUrl();
And also, please modify as follows.
From:
var filename = encodeURI(nameFile);
var files = DriveApp.getFilesByName(nameFile);
while (files.hasNext()) {
var file = files.next();
if (file) {
var fileUrl = file.getUrl();
};
};
////////////////HELP THIS PART////////////////////////////////
for (j = 0; j < lastRow2; j++) {
if (dataValues2[j][34] == subject) {
var doclink = Logger.log(fileUrl);
var range = sheet2.getRange(j + 1, 128);
range.setValue(doclink);
};
};
To:
var range = sheet2.getRange("AI2:AI" + sheet2.getLastRow()).createTextFinder(subject).findNext();
if (range) {
range.offset(0, 1).setValue(fileUrl);
}
In this modification, the cell is searched using TextFinder.
Reference:
createTextFinder(findText)

pdf is created from google slide, but with the markers populated (via GAS)

The code below basically maps columns from a spreadsheet to a couple of markers I got on a google slide.
It generates copies of the google slide template, updates them with the row's data and I actually need it to be in pdf form to be emailed later.
The pdf files are created in the destination folder, with the right file names, but the markers within them are "empty". Later on, I will have to delete these google slide files, but the challenge here now is to have the pdf files correctly created.
Appreciate your time.
function mailMerge(templateID,ssID, sheetName, mapped, fileNameData, emailCol, rowLen = "auto"){
//Properties Services is Google Script Storage.
//This clears out the storage.
PropertiesService.getScriptProperties().deleteAllProperties();
const ss = SpreadsheetApp.getActiveSpreadsheet();
//const sheet = SpreadsheetApp.openById(ssID);
const sheet = ss.getSheetByName("Lista de Participantes");
//Get number of rows to process
rowLen = (rowLen = "auto") ? getRowLen() : rowLen;
const range = sheet.getRange(7,1,rowLen,sheet.getDataRange().getNumColumns());
const matrix = range.getValues();
const fileNameRows = getFileNameRows()
for(let i = 1; i < rowLen; i++){
if (matrix[i][1] == true && matrix[i][27] != "Sim") {
let row = matrix[i];
//Get the title for the file.
let fileName = buildFileName(row)
//Creates a copy of the template file and names it with the current row's details.
let newDoc = DriveApp.getFileById(templateID).makeCopy(fileName);
//Replaces all the text place markers ({{text}}) with current row information.
updateFileData(row, newDoc.getId());
//Save new File ID and email to Properties service.
PropertiesService.getScriptProperties()
.setProperty(newDoc.getId(),row[emailCol]);
// 5. Export the temporal Google Slides as a PDF file.
newDoc = DriveApp.getFileById(newDoc.getId());
DriveApp.getFolderById("folder ID").createFile(newDoc.getBlob());
}
};
Besides the code above, I go this script file within the same container/Spreadsheet, where I map the columns whose data I want to generate a google Slide for. each column of data I refer to as marker.
/*###################################################################
* Maps the relationship between the Google Sheet header and its location
* for each column along with it's corresponding Google Slide Doc template name.
*
* To update change the sheet, col and doc:
* ***
* {
* sheet: << Your sheet header
* col: << The column on the google sheet with the above header
* doc: << the corresonding name in double braces {{name}} in your Slide template
* }
* ***
*###################################################################
*/
const mappedDocToSheet = [
{
sheet:"Nome",
col:2,
doc:"primeiroNome"
},
{
sheet:"Sobrenome",
col:3,
doc:"sobrenome"
},
{
sheet:"COD. CERTIFICADO",
col:9,
doc:"codigo"
},
{
sheet:"Curso",
col:10,
doc:"curso"
},
];
I believe your goal and situation as follows.
You add the values of Google Slides and create it to PDF data
newDoc is the Google Slides
In order to achieve your goal, please use saveAndClose. For your script, please modify as follows.
Modified script:
Please add the following script to your function of mailMerge as follows.
// 5. Export the temporal Google Slides as a PDF file.
SlidesApp.openById(newDoc.getId()).saveAndClose(); // <--- Added
Reference:
saveAndClose()

Saving one sheet as PDF in Google Drive (for all Users)

I made an Excel Sheet in Google Drive to be used by 15 Peoples. The function is that the macro should create a PDF from the Sheet and send it to peoples as Mail. But I want to make a copy as PDF in Google Drive where can I see all of this persons permissions to see all of the sent Mails.
I must say that I am a beginner for this macro thing, I tried 2 codes but I always get the same Error.
function TEST2()
{
var Datum = Utilities.formatDate(new Date(), "GMT+2", "dd.MM.YYYY HH:mm");
var as = SpreadsheetApp.getActive();
var newas = SpreadsheetApp.create("XX");
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("XX");
sheet = as.getSheetByName("XX");
sheet.copyTo(newas);
newas.getSheetByName('XX');
newas.deleteActiveSheet();
var pdf = DriveApp.getFileById(newas.getId()).getAs('application/pdf').getBytes();
var anhang = {fileName:("XX Order" + Datum + ".pdf"),content:pdf,mimeType:'application/pdf'};
var folderID = "TEST FOLDER";
var folder = DriveApp.getFolderById(folderID);
var newFile = DriveApp.createFile(folder);
newFile;
MailApp.sendEmail(
{
to: "Mail Adress",
subject: "XX Order " + Datum,
htmlBody: "XX - Order ",
attachments: anhang
})
SpreadsheetApp.getUi().alert('Mail wurde versendet ' + Datum)
//Delete the temporary sheet
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
}
I always get the same Error message. That the script cannot find a document with this ID.
Ok i found the solution :)
var folderID = "XXX BESTELLUNG";
var folderID2 = "XXX Bestellung";
var folder = DriveApp.getFoldersByName(folderID);
var theblob = newas.getBlob().getAs('application/pdf').setName('XXX Bestellung ' + Datum);
var newFile = folder.next().getFoldersByName(folderID2).next().createFile(theblob);
when i change the code in this case, i get the solution whicht i want :)

How to i can access to one of multi sheets in a spreadsheet

I'm newbie, i developing small project import csv to google sheets,
about part import csv to google sheets and create a sheet in spreadsheets i successed. How i can access to sheet that i created? Under is code to i create a sheet in spreadsheet ID. Thanks!!
$client = getClient();
$service = new Google_Service_Sheets($client);
$valueInputOption = 'USER_ENTERED';
$spreadsheetId = 'xxxxxxxxxxxxSPREADSHEETIDxxxxxxxxxx';
$title = date('m-d');
$body = new Google_Service_Sheets_BatchUpdateSpreadsheetRequest(array( 'requests' => array('addSheet' => array('properties' => array('title' => $title )))));
$result = $service->spreadsheets->batchUpdate($spreadsheetId, $body);
The way of accessing the data of the google spreadsheets is as below:
/*
Assume the data structure of the Google Spreadsheet is:
NAME COLOR
==================
Apple red
Mango yellow
*/
// define sheet url
var dataSheetUrl =
'https://docs.google.com/spreadsheets/d/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/edit';
// open one of the sheet named 'Fruit'
var dataSheet = SpreadsheetApp.openByUrl(dataSheetUrl).getSheetByName('Fruit');
// get sheet data
var data = dataSheet.getDataRange().getValues();
// loop through each row data and then log it
for (var i = 1, j = data.length; i < j; i++) {
Logger.log('NAME: ' + data[i][0]);
Logger.log('AGE: ' + data[i][1]);
}

How to move generated PDF to a specific folder in Google Drive

Here is the jist of what I want this script to do.
User submits a form using Google Forms
Form Records to Google Sheet
Sheet replaces text and generate Google Document from Template
Template is copied
PDF is created from this template
PDF is emailed
PDF is moved to a specific folder in Google Drive.
I have all of those things to work except the last step. Can someone help us out here? We are using this for a school, and nobody in our (IT) department knows anything about scripts. Through Googling and searching I have come this far. The last step is to get the PDF to move to a specific folder.
Here is the current code:
// MacArthur High School
// Generic PLC Agenda Script
// Created 18 Jul 2014
// Author: Josh Patrick
// Decatur Public Schools #61
// Document Creation - replace docTemplate links with each template link on the PLC Drive.
var docTemplate = "1DSFCE6mFZib0ZTVOgVqPbLYaRwjS-XNsnsZn5RZewsE";
var docName = "PLC Agenda";
// Form Functions (labeled identifiers for Form)
function onFormSubmit(e) {
var TimeStamp = e.values [0]
var MeetingDate = e.values [1];
var MeetingTime = e.values [2];
var MeetingLocation = e.values [3];
var PLCFocus = e.values [4];
var PlannedActions = e.values [5];
var ResourcesNeeded = e.values [6];
var AssignedEmail = "jwpatrick#dps61.org";
// Get document template, copy it as a new temp doc, and save the Doc’s id
var copyId = DocsList.getFileById(docTemplate)
.makeCopy(docName+' for '+ MeetingDate)
.getId();
// Open the temporary document
var copyDoc = DocumentApp.openById(copyId);
// Get the document’s body section
var copyBody = copyDoc.getActiveSection();
// Replacing Text with Form Information
copyBody.replaceText('keyMeetingDate', MeetingDate);
copyBody.replaceText('keyMeetingTime', MeetingTime);
copyBody.replaceText('keyMeetingLocation', MeetingLocation);
copyBody.replaceText('keyPLCFocus' , PLCFocus);
copyBody.replaceText('keyPlannedActions' , PlannedActions);
copyBody.replaceText('keyResourcesNeeded' ResourcesNeeded);
// Copy Document and Save
copyDoc.saveAndClose();
// Generate PDF
var pdf = DocsList.getFileById(copyId).getAs("application/pdf");
// Email
var subject = "ELA PLC Agenda for " + MeetingDate ;
var body = "Attached is the PDF copy of the ELA PLC Agenda for " + MeetingDate;
MailApp.sendEmail(AssignedEmail, subject, body, {htmlBody: body, attachments: pdf});
// Delete Temporary Document
DocsList.getFileById(copyId).setTrashed(true);
}
**** Instead of deleting the temporary document, I want to move it to a specific file in Google Drive. I have looked up the scripts help, but I don't think I have done it correctly. I can get it to copydoc but I cannot get it to move to the right folder.
Any assistance is much appreciated.
addToFolder may fit your need.
developers.google.com/apps-script/reference/docs-list/file#addToFolder(Folder)