How can I map a Google form submission to a template and email to specific individuals as a PDF? - pdf

I am trying to have users submit information through Google forms and have the information inserted into a Google Doc as a template. The completed document would then be converted to a PDF and emailed out to the individual. The issue that I am having is that nothing seems to be produced upon form submission. Help would be appreciated!
Here is the code that I am using:
//Get template from Google Docs and name it
var docTemplate = "1ebZTRMRJTxEkNQl1Y2XTSCmIMhmThSMk3BDEQrJbOBE";
var docName = "Unit Overview Template";
//When Form Gets Submitted
function onFormSubmit(e){
//Get information from form and set as variables
var email_address = "e.values[5]";
var teacher_name = e.values[2];
var unit_name = e.values[6];
var unit_length = e.values[7];
var unit_start = e.values[3];
var course_period = e.values[4];
//Get document template, copy it as a new temp doc, and save the Doc's id
var copyId = DocsList.getFilebyId(docTemplate)
.makeCopy(docName+' for ' +teacher_name)
.getId();
//Open the temporary document
var copyDoc = DocumentApp.openById(copyId);
//Get the document's body section
var copyBody = copyDoc.getActiveSection();
//Replace place holder keys, in our google doc template
copyBody.replaceText('keyFullName', teacher_name);
copyBody.replaceText('keyUnitName', unit_name);
copyBody.replaceText('keyUnitDays', unit_length);
copyBody.replaceText('keyUnitPeriod', course_period);
copyBody.replaceText('keyUnitStart', unit_start);
//Save and close the temporary document
copyDoc.saveAndClose();
//Convert temporary document to PDF
var pdf = DocsList.getFilebyId(copyID).getAs("application/pdf");
//Attach PDF and send the email
var subject = "Unit Lesson Overview";
var body = "Here is your completed Unit Overview for " + unit_name + "";
MailApp.sendEmail(email_address, subject, body, {htmlBody: body, attachments: pdf});
//Delete temp file
DocsList.getFilebyId(copyId).setTrashed(true);
}

Use DriveApp instead of DocsList as the latter is deprecated. Also make sure you have a trigger setup for onFormSubmit under Resources - current project triggers inside the Script Editor.

Related

Extract Text from Multipage Attachment PDF Using Google Apps Script

I have a Gmail attachment PDF with multiple scanned pages. When I use Google Apps Script to save the blob from the attachment to a Drive file, open the PDF manually from Google Drive, then select Open With Google Docs, all of the text from the PDF is displayed as a Google Doc. However, when I save the blob as a Google Doc with OCR, only the text from the image on the first page is saved to a Doc, accessed either manually or by code.
The code to get the blob and process it is:
function getAttachments(desiredLabel, processedLabel, emailQuery){
// Find emails
var threads = GmailApp.search(emailQuery);
if(threads.length > 0){
// Iterate through the emails
for(var i in threads){
var mesgs = threads[i].getMessages();
for(var j in mesgs){
var processingMesg = mesgs[j];
var attachments = processingMesg.getAttachments();
var processedAttachments = 0;
// Iterate through attachments
for(var k in attachments){
var attachment = attachments[k];
var attachmentName = attachment.getName();
var attachmentType = attachment.getContentType();
// Process PDFs
if (attachmentType.includes('pdf')) {
processedAttachments += 1;
var pdfBlob = attachment.copyBlob();
var filename = attachmentName + " " + processedAttachments;
processPDF(pdfBlob, filename);
}
}
}
}
}
}
function processPDF(pdfBlob, filename){
// Saves the blob as a PDF.
// All pages are displayed if I click on it from Google Drive after running this script.
let pdfFile = DriveApp.createFile(pdfBlob);
pdfFile.setName(filename);
// Saves the blob as an OCRed Doc.
let resources = {
title: filename,
mimeType: "application/pdf"
};
let options = {
ocr: true,
ocrLanguage: "en"
};
let file = Drive.Files.insert(resources, pdfBlob, options);
let fileID = file.getId();
// Open the file to get the text.
// Only the text of the image on the first page is available in the Doc.
let doc = DocumentApp.openById(fileID);
let docText = doc.getBody().getText();
}
If I try to use Google Docs to read the PDF without OCR directly, I get Exception: Invalid argument, for example:
DocumentApp.openById(pdfFile.getId());
How do I get the text from all of the pages of the PDF?
DocumentApp.openById is a method that can only be used for Google Docs documents
pdfFile can only be "opened" with the DriveApp - DriveApp.getFileById(pdfFile.getId());
Opening a file with DriveApp allows you to use the following methods on the file
When it comes to OCR conversion, your code works for me correctly to convert all pages of a PDF document to Google Docs, so you error source is likely come from the attachment itself / the way you retrieve the blob
Mind that OCR conversion is not good at preserving formatting, so a two page PDF might be collapsed into a one-page Docs - depneding on the formatting of the PDF

creating a PDF via google apps script but creates the PDF with an additional blank page

I have a apps script bound to a spreadsheet that creates a pdf file from the sheet. this creates one single page pdf and saves it in a folder in drive. Up until recently, this worked perfectly. Now every time I run the code it does what it is supposed to but the file has a second page that is blank. When I create the pdf manually via file/download as/pdf doc, it creates the pdf as it should, with only one page. I have tried this with both the original and copy that the script temporarily creates. Both work when done manually. I am looking for some suggestions on what could have gone wrong and what to change. Here is an example of the code:
function makePDF() {
var sheet1 = SpreadsheetApp.getActive().getSheetByName('eTimesheet');
var sheet2 = SpreadsheetApp.getActive().getSheetByName('Time Sheet');
var sheet3 = SpreadsheetApp.getActive().getSheetByName('Data');
var triggercell3 = sheet1.getRange('M33').getValue();
if (triggercell3 == 'GO'){
var techNumber = sheet3.getRange('B5').getValue();
var date = sheet3.getRange('B3').getValue();
var fileID = sheet3.getRange('B7').getValue();
var pdfName = "TimeSheet- "+ techNumber + " " + date
var ss = SpreadsheetApp.getActive();
var folder = DriveApp.getFolderById(fileID);
sheet2.showSheet();
sheet1.hideSheet();
//Copy whole spreadsheet
var destSpreadsheet = SpreadsheetApp.open(DriveApp.getFileById(ss.getId()).makeCopy("tmp_convert_to_pdf", folder))
//save to pdf
var theBlob = destSpreadsheet.getBlob().getAs('application/pdf').setName(pdfName);
var newFile = folder.createFile(theBlob);
DriveApp.getFileById(destSpreadsheet.getId()).setTrashed(true);
sheet1.showSheet();
sheet2.hideSheet();
sheet1.getRange('M33').clearContent();
}
}
thanks for any assistance...
Without an example, first question I have is... if you delete a few rows from the sheet and run the script, are you back to 1 page?
I am asking in case the issue is just margin settings. If this is the issue, maybe you can adjust rows or use the UrlFetchApp.fetch approach as PDF page formatting can be specified (eg: margin size).

Save a sheet as pdf with onEdit()

i'm trying to save a google spreadsheet as pdf and mail it to myself everytime, when a specific cell in the spreadsheet is edited. I have the script which saves the spreadsheet as pdf and emails it and it works and I also have an onEdit(e) script which does exactly what I want. But when I put them together it doesn't work. Here's the script:
function onEdit(e) {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("booking");
var index = sheet1.getRange('O5').getValue();
if(index == '#N/A') return;
var email = "myemail#gmail.com";
var subject = "Subject";
var sheet3 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Invoice_ENG");
var pdfname = ("PDF.pdf");
var message = ("Hello!");
//Since I can't export only one sheet, I create a new spreadsheet, copy the sheet
//into the new spreadsheet and save the new spreadsheet as pdf
var newSpreadsheet = SpreadsheetApp.create("Spreadsheet to export");
sheet3.copyTo(newSpreadsheet);
//I erase the default Sheet1 from the new Spreadsheet
var ss = newSpreadsheet.getSheetByName('Sheet1');
ss.activate();
newSpreadsheet.deleteActiveSheet();
//Create pdf --- THIS IS WHERE THE SCRIPT SOMEHOW STOPS!
var pdf = DriveApp.getFileById(newSpreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:pdfname,content:pdf, mimeType:'application/pdf'};
//Send mail
GmailApp.sendEmail(email, subject, message, {attachments:[attach]});
//Erase the newly created spreadsheet
DriveApp.getFileById(newSpreadsheet.getId()).setTrashed(true);
}
Is the "export as pdf" task too much to be done with an onEdit function? Because I'm doing the exact same thing in another script which I trigger daily and it works fine.
You should use an installable onEdit trigger as sending email cannot be done with simple trigger.
ScriptApp.newTrigger("onEdit")
.forSpreadsheet(SpreadsheetApp.getActive())
.onEdit()
.create();
//Since I can't export only one sheet, I create a new spreadsheet, copy the sheet
//into the new spreadsheet and save the new spreadsheet as pdf
var newSpreadsheet = SpreadsheetApp.create("Spreadsheet to export");
sheet3.copyTo(newSpreadsheet);
//I erase the default Sheet1 from the new Spreadsheet
var ss = newSpreadsheet.getSheetByName('Sheet1');
ss.activate();
newSpreadsheet.deleteActiveSheet();
I believe that activate is a method for sheets not for spreadsheets. You can open a spreadsheet from SpreadsheetApp.
//Create pdf --- THIS IS WHERE THE SCRIPT SOMEHOW STOPS!
var pdf = DriveApp.getFileById(newSpreadsheet.getId()).getAs('application/pdf').getBytes();
var attach = {fileName:pdfname,content:pdf, mimeType:'application/pdf'};
I believe you need to create the pdf file using DriveApp between these two statements. Possible with DriveApp.createFile

How to send saved pdf which exists within a folder using .net mvc 5

I am using Rotativa. MVC to generate a PDF from a view, so I can send an email with the PDF as an attachment. The following code does so:
var p = ControllerContext;
var h = new ViewAsPdf("Index") { FileName = "TestViewAsPdfHm.pdf" };
var hmm = h.BuildPdf(p);
var memStream2 = new SysIO.MemoryStream(hmm);
MailMessage mm = new MailMessage("From#gmail.com", "To#gmail.com");
mm.IsBodyHtml = true;
mm.Attachments.Add(new Attachment(memStream2, "BuildPdfOption.pdf"));
My question is "How do I obtain a PDF file saved i.e. in my MVC application's Content/Pdf folder, from within in c# code, so I can attach it to an email in the same manner?"
I have tried many times with file,stream readers and with HttpContext.Server.MapPath, but without success. Using the MapPath option just had a textual document in the email that I couldn't open.

Replace attachment when uploading a new attachment

I have a simple form and body field. when user upload an attachment I want to remove any attachment already in the body field of the document. how can I do this in my save button.
I have tried to set the properites on the fileUpload control to always change the filename to tha same name but this does not replace the file, instead it adds a new file and add a new sequential number to it
<xp:fileUpload id="fileUpload1" value="#{userdoc.Body}" filename="profile" seUploadname="false"></xp:fileUpload>
I have also tried to loop all embedded attachments in body field before before save, and all attachments are then removed, but my new attachment is not added.
A little late, but in case anyone gets here just as I did through Google...
There's also another option: a NotesXSPDocument.getAttachmentList("rtitem") returns a list of attachments in the document. Each entry is of type DominoDocument.AttachmentValueHolder which has a getState() property that returns if a file was already in the document or just added. To remove the file that was already in the document you could add this SSJS code to a save button (assuming "files" is the name of the richtext item holding the files):
var attList = docFile.getAttachmentList("files");
for(var i=0; i<attList.size(); i++) {
var att = attList.get(i);
if (att.getState()==0) { //STATE_INDOCUMENT: this is the 'old' file: remove it
docFile.removeAttachment("files", att.getName() );
} else if (att.getState()==1) { //STATE_ADDED: this is the new file
//leave it
}
}
This can be done by removing all attachments first (use the removeAllAttachments function from NotesXSPDocument object) and then attach the uploaded file manually to the richtext item.
This SSJS code has to be added to beforeRenderResponse-event of your XPage / Custom Control:
var con = facesContext.getExternalContext();
var request:com.sun.faces.context.MyHttpServletRequestWrapper = con.getRequest();
var map:java.util.Map = request.getParameterMap();
var fileDataName = getClientId('fileUpload1') ;
var fileData:com.ibm.xsp.http.UploadedFile = map.get( fileDataName );
if( fileData == null ){
return;
}
var tempFile:java.io.File = fileData.getServerFile();
var correctedFile = new java.io.File( tempFile.getParentFile().getAbsolutePath() +
java.io.File.separator + fileData.getClientFileName() );
var success = tempFile.renameTo(correctedFile);
try{
document1.removeAllAttachments("Body");
}catch(e){}
var rtFiles:NotesRichTextItem = null;
if(!(document1.getDocument().hasItem("Body"))){
rtFiles = document1.getDocument().createRichTextItem("Body")
}else{
rtFiles = document1.getDocument().getFirstItem("Body");
}
rtFiles.embedObject(lotus.domino.local.EmbeddedObject.EMBED_ATTACHMENT, "",
correctedFile.getAbsolutePath(), null);
correctedFile.renameTo(tempFile);
document1.save();
The richtext item where the files are stored is "Body", the name of the datasource is "document1". The Fileupload control is "fileUpload1".
There are two limitations:
You cannot use this with a save button, you have to use a normal button / link which makes a full refresh (see what Serdar Basegmez wrote above)
You have to refresh the page after a upload once again, otherwise you will not see the uploaded file in a file download conrol (maybe a partial refresh to this control may work).
EDIT:
Sorry, my fault: You can use this code above in a submit button that saves the document. Then you don't have to refresh the page manually!