Converting a Google doc to PDF, then moving to another folder - javascript

I am working on script that will fill a Google doc template with cell values from a spreadsheet. A copy of the edited doc is created and converted into a PDF. I would then like for both the doc and the pdf to be moved to the specified folder. I am stuck on getting the pdf moved over to the folder. I created a function to move the docs, and it seems to work fine with the Google doc copy, but an error is being returned when the function runs for the pdf. The error seems to be coming from the moveFile function. I have also tried moving moveFile pdf call to fillLetter, but still get the same error. This is my first attempt at coding with Google script, so any advice would be greatly appreciated. Thank you!
function fillLetter() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];//Form Responses tab
var templateId = '1d-CKr_Xi27FrWsH6eWdUCWKyzrLjy3ivTjLkk_WyJ4s';//Test doc
//get candidates row number from user input
var ui = SpreadsheetApp.getUi();
var rowNum = ui.prompt("Please enter candidate row number");
//activates first column in selected row
var col = sheet.getRange("A"+ rowNum.getResponseText());
sheet.setActiveRange(col);
var candName = sheet.getActiveCell().getValue();
col = sheet.getRange("B"+ rowNum.getResponseText());
sheet.setActiveRange(col);
var location = sheet.getActiveCell().getValue();
//creates copy of template doc and renames
var lastName = candName.split(" ");
var filename = candName.substring(0,1) + lastName[lastName.length - 1] + ' - Offer Letter';
var newOffer = DriveApp.getFileById(templateId).makeCopy();
var offerId = newOffer.getId();
DriveApp.getFileById(offerId).setName(filename);
//gets body of template doc and replaces text
var doc = DocumentApp.openById(offerId);
var body = doc.getBody();
var todaysDate = Utilities.formatDate(new Date(), 'PST', 'MMMM dd, yyyy');
body.replaceText('{{Todays date}}', todaysDate);
body.replaceText('{{Candidate name}}', candName);
body.replaceText('{{Location}}', location);
doc.saveAndClose();
//Creates folder and moves newly created files
var folderName = DriveApp.createFolder(candName).getId();
convertPDF(offerId, folderName); // Line 52
moveFile(offerId, folderName);
}
function convertPDF(fileToCopy, folder) {
var docFolder = DriveApp.getFolderById(folder);
var copy = DriveApp.getFileById(fileToCopy);
//Add the PDF extension
var docblob = copy.getAs('application/pdf');
docblob.setName(copy.getName() + ".pdf");
var pdfFile = DriveApp.createFile(docblob);
var fileId = pdfFile.getId();
Logger.log("Offer PDF id - " + fileId);//for debug
moveFile(fileId, docFolder); // Line 66
}
function moveFile(fileId, folderId) {
var file = DriveApp.getFileById(fileId);
DriveApp.getFolderById(folderId).addFile(file); // Line 72: wh/ error is most likely occurring
}
Below is the error message from the Logger:
Error
Exception: Unexpected error while getting the method or property getFolderById on object DriveApp.
moveFile # testCode.gs:72
convertPDF # testCode.gs:66
fillLetter # testCode.gs:52

In the current stage, you can use moveTo method for moving the file on Google Drive. This has added on July 27, 2020. Ref In your script, when moveFile is modified, it becomes as follows.
Modified script:
function moveFile(fileId, folderId) {
var file = DriveApp.getFileById(fileId);
file.moveTo(DriveApp.getFolderById(folderId));
}
Reference:
moveTo(destination)
The methods of addFile, addFolder, removeFile and removeFolder have already been deprecated. Ref

Related

How to partially change a file name in google apps script?

function autoFillGoogleDocFromForm(e) {
var timestamp = e.values[0];
var auditorFirmName = e.values[1];
var auditorAddressLine1 = e.values [2];
var auditorAddressLine2 = e.values[3];
var auditorAddressLine3 = e.values[4];
var auditorAddressLine4 = e.values [5];
var dateOfLetterIssue = e.values[6];
const template = "template";
var templateFile = DriveApp.getFileById("");
var templateFolder = DriveApp.getFolderById("");
var copy = templateFile.makeCopy(auditorFirmName + ${template}, templateFolder);
var doc = DocumentApp.openById(copy.getId());
var body = doc.getBody();
body.replaceText("{{Insert Auditor Firm name}}", auditorFirmName);
body.replaceText("{{Address Line 1}}", auditorAddressLine1);
body.replaceText("{{Address Line 2}}", auditorAddressLine2);
body.replaceText("{{Address Line 3}}", auditorAddressLine3);
body.replaceText("{{Address Line 4}}",auditorAddressLine4);
body.replaceText("{{Date}}",dateOfLetterIssue);
doc.saveAndClose();
}
Currently the line var copy = templateFile.makeCopy(auditorFirmName, templateFolder); is creating a copy of the original doc with the file name of the auditor firm as I have requested. But what I would like to do is create a file name with the auditor firm name and the wording template for example. Or a fixed piece of text that is not a variable. E.g currently the file will save as John Smith Auditors where I want it to save as John Smith Auditors Template. Where John Smith stays as a variable but the word Template would always remain fixed. Is this possible?
How about changing this line var copy = templateFile.makeCopy(auditorFirmName, templateFolder); to this var copy = templateFile.makeCopy(auditorFirmName + template, templateFolder); and add a const template="whatever words you want to add"; earlier in the file near the top. You could just add + "Template" if you like but typically your needs tend to change so the use of a variable may be useful but it's up to you. If I'm not understanding you question I apologize.

Exception error relating to method signature

I'm super new to JavaScript, am an editor by trade, but need to create a Google Calendar view from a Google Sheet for story assignments for my writers. I've gone through a tutorial on how to make this work and have fixed a number of problems with the code. I'm stuck on what I think is the final issue. It relates to the method signature. The error message is:
Exception: The parameters (String,String,String,String,String,String)
don't match the method signature for
CalendarApp.Calendar.createAllDayEvent. (line 20, file "Code")
Here's the code. Can anyone help???
function myFunction() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var calendarId = spreadsheet.getRange ("N8").getValue();
var eventCal = CalendarApp.getCalendarById(calendarId);
var signups = spreadsheet.getRange("G8:L124").getValues();
for (x=6; x<signups.length; x++) {
var shift = signups[x];
var author = shift[0];
var newsletterdate = shift[1];
var livedate = shift[2];
var duetoproductiondate = shift[3];
var duetocopyeditdate = shift[4];
var duetocontenteditdate = shift[5];
eventCal.createAllDayEvent(author, newsletterdate, livedate, duetoproductiondate, duetocopyeditdate, duetocontenteditdate);
}
}
It seems there is no signature for this method that has 6 parameters. The maximum I noted was 5 on this documentation: https://developers.google.com/apps-script/reference/calendar/calendar-app
You must review the arguments you are passing when calling the function and choose the most suitable method signature.

Line Break Causing Error Importing CSV from Google Drive to Google Sheets

I'm working to automate the flow of data that we use to power some of our analytics/reporting. To summarize, I have a CSV in Google Drive that needs to be imported into a Google Sheet. The CSV contains line breaks in some of the "cells" that is causing the import to be completely askew / out of line. To be clear, I can get the data, but it is misaligned due to the line breaks in the CSV.
I started with code from Ctrl:
function importCSVFromGoogleDrive() {
var file = DriveApp.getFilesByName("tweet_activity.csv").next();
var csvData = Utilities.parseCsv(file.getBlob().getDataAsString());
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
I quickly discovered that, while the code did import the file, the line breaks ruined the alignment of the data. Upon inspection, it's clear that the line breaks are the genesis of the issue.
I scoured the forums and found some possible fixes ([here](Saving as CSV through google script handling newline characters
) and [here](Apps Script Utilities.parseCsv assumes new row on line breaks within double quotes
) for instance)
I've tried:
function importCSVFromGoogleDrive_v2() {
var file = DriveApp.getFilesByName("tweet_activity.csv").next();
var NewFile = file.replace("\n", " ").replace("\r", " ");
var csvData = Utilities.parseCsv(NewFile.getBlob().getDataAsString());
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
This resulted in "TypeError: Cannot find function replace in object tweet_activity.csv. (line 42, file "Code")"
I also tried replacing the line breaks after the parse.
function importCSVFromGoogleDrive_v3() {
var file = DriveApp.getFilesByName("tweet_activity_metrics_downtownstlouis_20190303_20190331_en.csv").next();
var csvData = Utilities.parseCsv(file.getBlob().getDataAsString());
var csvDataRev = csvData.replace("\n", " ").replace("\r", " ");
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
This resulted in "TypeError: Cannot find function replace in object"
Finally, I tried different replace code (I modified for my purposes, but this was the pertinent part):
var dataString = myBlob().getDataAsString();
var escapedString = dataString.replace(/(?=["'])(?:"[^"\](?:\[\s\S][^"\])"|'[^'\]\r\n(?:\[\s\S][^'\]\r\n)')/g, function(match) { return match.replace(/\r\n/g,"\r\n")} );
var csvData = Utilities.parseCsv(escapedString);
No dice.
Any suggestions on how to deal with the line breaks in this scenario?

Convert path string from unc to uri, replacing slashes with backslashes in Google Apps Script

I need to convert a path this UNC. I have searched and search and cannot piece anything together.
"\\NAS_01\GlobalShare\Docs\Customers\2017\S\Smith, John\photo1.jpg"
I need to remove the "\NAS_01\GlobalShare\Docs\Customers\" portion of the path and also "photo1.jpg" and end up with:
2017\S\Smith, John\
so that I can pass it to the following function:
function getDriveFolderNoCreate(path, rootFolder) {
var name, folder, search, fullpath;
// Remove extra slashes and trim the path
fullpath = path.replace(/^\/*|\/*$/g, '').replace(/^\s*|\s*$/g, '').split("/");
// Always start with the main Drive folder
folder = rootFolder;
for (var subfolder in fullpath) {
name = fullpath[subfolder];
search = folder.getFoldersByName(name);
if (search.hasNext()) {
var folder = search.next;
var folderID = folder.getId();
return folderID;
}
}
}
My intention is to return a url to open the Google Drive folder with the same path.
I ended up with a multi-part solution that works very well.
I paste the fill UNC path to cell B2.
This formula is in B3 =Index(split(B2, "\"), 0, 8)
It returns the exact folder name i need.
Then in my gs file:
function findDriveFolder() {
var pFId = "XYZ1233333333333";
var input = SpreadsheetApp.getActive().getRange("B3").getValue();
var folders = DriveApp.getFoldersByName(input);
Logger.log("folders: " + folders[0]);
while (folders.hasNext()) {
var folder = folders.next();
var url = folder.getUrl();
showAnchor("View Folder", url);
}
}
function showAnchor(name,url) {
var html = '<html><body>'+name+'</body></html>';
var ui = HtmlService.createHtmlOutput(html)
SpreadsheetApp.getUi().showModelessDialog(ui,"Files Folder");
}
I have not implemented the searchFolders part yet that I hope will speed it up. At least it's working for now.
Apps Script needs your input backslashes to be escaped if you are writing the string yourself (i.e. testing input).
wrong:
input = "\\NAS_01\GlobalShare\Docs\Customers\2017\S\Smith, John\photo1.jpg"
right:
input = "\\\\NAS_01\\GlobalShare\\Docs\\Customers\\2017\\S\\Smith, John\\photos1.jpg"
In Apps Script then, I am able to get the matching portion with the following regex:
/\d{4}\\[A-Z]\\.+\\/
i.e:
function unc2uri(input) {
const forwardSlash = String.fromCharCode(47);
const backSlash = String.fromCharCode(92);
if(!input)
input = '\\\\NAS_01\\GlobalShare\\Docs\\Customers\\2017\\S\\Smith, John\\photo1.jpg';
// Should show \\NAS_01\GlobalShare\Docs\Customers\2017\S\Smith, John\photo1.jpg
Logger.log(input);
const matcher = /\d{4}\\[A-Z]\\.+\\/;
const arrayOfMatches = input.match(matcher);
// Should show [2017\S\Smith, John\].
Logger.log(arrayOfMatches);
}
To verify, ask for the input string from someplace else (example, Browser.inputBox) and pass that to the above as input:
function readInput() {
unc2uri(Browser.inputBox("What's the path?"));
}
In the inputBox, you would enter the string you expect to be sent, as we view it, i.e. \\NAS_01\GlobalShare\Docs\Customers\2017\S\Smith, John\photo1.jpg

Updated doc not attaching as PDF in Gmail

I'm using Google Apps Script to create a copy of a doc file and save data from spreadsheet to the new file, then send it to email as a PDF attachment. Everything is working as it should except the pdf file is showing the default values which was from the source file instead of updated values.
Here are my codes,
var lr = dataSheet.getLastRow();
var dataRange = dataSheet.getRange(lr, 1, 1, 3).getValues();
var firstName = dataRange[0][1];
var lastName = dataRange[0][2];
var email = dataRange[0][3];
var emailText = "Hi "+firstName+",\n\nThank you for signing up.";
var emailSubject = "Test PDF";
var fileTemplate = DriveApp.getFileById("FILE_ID"); // Get Template File Id
var fileCopied = fileTemplate.makeCopy("Doc Copy-"+new Date()).getId(); // Make a copy of the template and get the id of the new file.
var doc = DocumentApp.openById(fileCopied); // Get destination doc
var dbody = doc.getBody(); // get destination doc's body
// Replace the fields with values from sheet.
dbody.replaceText("First Name", firstName);
dbody.replaceText("Last Name", lastName);
dbody.replaceText("EmailAddress", email);
Utilities.sleep(1000);
// Send Email with PDF attachment
MailApp.sendEmail(email, emailSubject, emailText, {
attachments: [doc.getAs(MimeType.PDF)]
});
How can I get the updated doc in the mail as a PDF attachment?
I think, it can be done if we consider the 'files' as 'blobs', that is how Google treats the Google Docs files. Please see this example which converts and sends Google Spreadsheets as PDF files.
/* Send Spreadsheet in an email as PDF, automatically */
function emailSpreadsheetAsPDF() {
// Send the PDF of the spreadsheet to this email address
var email = "amit#labnol.org";
// Subject of email message
// The date time string can be formatted in your timezone using Utilities.formatDate method
var subject = "PDF Reports - " + (new Date()).toString();
// Get the currently active spreadsheet URL (link)
// Or use SpreadsheetApp.openByUrl("<<SPREADSHEET URL>>");
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Email Body can be HTML too with your logo image - see ctrlq.org/html-mail
var body = "PDF generated using code at ctrlq.org from sheet " + ss.getName();
var url = ss.getUrl();
url = url.replace(/edit$/,'');
/* Specify PDF export parameters
// From: https://code.google.com/p/google-apps-script-issues/issues/detail?id=3579
exportFormat = pdf / csv / xls / xlsx
gridlines = true / false
printtitle = true (1) / false (0)
size = legal / letter/ A4
fzr (repeat frozen rows) = true / false
portrait = true (1) / false (0)
fitw (fit to page width) = true (1) / false (0)
add gid if to export a particular sheet - 0, 1, 2,..
*/
var url_ext = 'export?exportFormat=pdf&format=pdf' // export as pdf
+ '&size=letter' // paper size
+ '&portrait=false' // orientation, false for landscape
+ '&fitw=true&source=labnol' // fit to width, false for 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='; // the sheet's Id
var token = ScriptApp.getOAuthToken();
var sheets = ss.getSheets();
//make an empty array to hold your fetched blobs
var blobs = [];
for (var i=0; i<sheets.length; i++) {
// Convert individual worksheets to PDF
var response = UrlFetchApp.fetch(url + url_ext + sheets[i].getSheetId(), {
headers: {
'Authorization': 'Bearer ' + token
}
});
//convert the response to a blob and store in our array
blobs[i] = response.getBlob().setName(sheets[i].getName() + '.pdf');
}
//create new blob that is a zip file containing our blob array
var zipBlob = Utilities.zip(blobs).setName(ss.getName() + '.zip');
//optional: save the file to the root folder of Google Drive
DriveApp.createFile(zipBlob);
// Define the scope
Logger.log("Storage Space used: " + DriveApp.getStorageUsed());
// If allowed to send emails, send the email with the PDF attachment
if (MailApp.getRemainingDailyQuota() > 0)
GmailApp.sendEmail(email, subject, body, {attachments:[zipBlob]});
}
More in here: Convert and Email Google Spreadsheets as PDF Files

Categories