Search code examples
javascriptgoogle-app-maker

How to send a PDF via email with the contents displayed in table like format?


Here is the code I'm using now:

function emailQuestionnaireAsPDF(questionnaireKey) {
  if (app.getActiveUserRoles().indexOf(app.roles.Admins) === -1) {
    throw new Error('You don\'t have permissions to perform this operation');
  }

  var questionnaire = app.models.Questionnaire.getRecord(questionnaireKey);

  if (!questionnaire) {
    throw new Error('Questionnaire was not found');
  }

  var tmpDoc = DocumentApp.create(FILE_NAME + ' ' + Date.now());
  var body = tmpDoc.getBody();
  var title = questionnaire.FirstName + '\'s Questionnaire';
  var fields = app.metadata.models.Questionnaire.fields;

  body.insertParagraph(0, title)
    .setHeading(DocumentApp.ParagraphHeading.HEADING1)
    .setAlignment(DocumentApp.HorizontalAlignment.CENTER);

  appendField_(body, fields.FirstName.displayName,
               questionnaire.FirstName);
  appendField_(body, fields.LastName.displayName,
               questionnaire.LastName);
  appendField_(body, fields.LikeIceCream.displayName,
               questionnaire.LikeIceCream);
  appendField_(body, fields.FavoriteMovie.displayName,
               questionnaire.FavoriteMovie);
  appendField_(body, fields.FavoriteColor.displayName,
               questionnaire.FavoriteColor);
  appendField_(body, fields.LuckyNumber.displayName,
               questionnaire.LuckyNumber);

  tmpDoc.saveAndClose();

  var blob = tmpDoc.getAs(MimeType.PDF);
  var pdfFile = DriveApp.createFile(blob);

  Drive.Files.remove(tmpDoc.getId());
  pdfFile.setName(FILE_NAME);

  sendEmail_(Session.getActiveUser().getEmail(), FILE_NAME, pdfFile.getUrl());
}

I'm trying to append all fields, from a model related to Questionnaire, to the "pdfFile". How is this done in a way all fields & values associated are pasted to the pdfFile in a table like format?


Solution

  • Based on your description, this is what I've done:

    1. Created a model called questionnaire with the following fields:

      • firstName
      • lastName
      • likeIcecream
      • favoriteMovie
      • favoriteColor
      • luckyNumber

    I added a couple of test records. Then on the server script I added two functions. The first one to send email looks like this:

    function sendEmail(recipient, fileUrl, fileName){
    
      var pdfBlob = UrlFetchApp.fetch(fileUrl).getAs("application/pdf");
    
      MailApp.sendEmail({
        to: recipient,
        subject: "PDF Email Sample",
        htmlBody: "Attached the PDF File",
        attachments: [pdfBlob]
      });  
    
    }
    

    The second function to generate the document looks like this:

    function emailQuestionnaireAsPDF(questionnaireKey){
    
      if (app.getActiveUserRoles().indexOf(app.roles.Admins) === -1) {
        throw new Error('You don\'t have permissions to perform this operation');
      }
    
      var questionnaire = app.models.questionnaire.getRecord(questionnaireKey);
    
      if (!questionnaire) {
        throw new Error('Questionnaire was not found');
      }
    
      //Start generating the HTML template
      var htmlData = "";
      htmlData += "<h1 style='text-align:center'>" + questionnaire.firstName + "'s Questionnaire </h1><br>"; //Title of the document
    
      //Create table start tag
      htmlData += "<table style='border:none;'>";
    
      //Create headers and append to table
      var headers = ["QUESTION", "RESPONSE"];
      var hRowStyle = "background-color:#efefef"; //style for table header row
      var hCellStyle = "font-weight:bold; padding-top:4px; padding-bottom: 3px; border-bottom:1px solid #bebebe;"; //style for table header cells
      htmlData += "<tr style='"+hRowStyle+"'><td style='"+hCellStyle+"'>" + headers.join("</td><td style='"+hCellStyle+"'>") + "</td></tr>";
    
      //Define row cell styles
      var tdSytle = "border-bottom: 1px solid #bebebe; border-left:0px; border-right:0px; padding-top:7px; padding-bottom: 6px;";
    
      //Create table rows
      var rows = [];
      rows.push(["First Name:", questionnaire.firstName]); // Add firstName
      rows.push(["Last Name:", questionnaire.lastName]); // Add lastName
      rows.push(["Likes Icecream:", questionnaire.likeIcecream]); // Add likeIceacream
      rows.push(["Favorite Movie:", questionnaire.favoriteMovie]); // Add favoriteMovie
      rows.push(["Favorite Color:", questionnaire.favoriteColor]); // Add favoriteColor
      rows.push(["Lucky Number:", questionnaire.luckyNumber]); // Add luckyNumber
    
      //Append rows to table
      rows.forEach(function(row){
         htmlData += "<tr><td style='"+tdSytle+"'>" + row.join("</td><td style='"+tdSytle+"'>") + "</td><tr>";
      });
    
      //Create table end tag
      htmlData += "</table>";
    
      //Create gooleDriveDoc
      var fileName = questionnaire.firstName + "'s Questionnaire";
      var data = Utilities.newBlob("").setDataFromString(htmlData).setContentType("text/html");
      var drvFile = Drive.Files.insert({title: fileName}, data, {convert: true});
    
      //Mail PDF File
      var recipient = "email@test.com";
      var fileUrl = "https://docs.google.com/document/d/"+drvFile.id+"/export?format=pdf&access_token="+ScriptApp.getOAuthToken();  
      sendEmail(recipient, fileUrl, fileName);
    
    }
    

    So, in summary, I've created a google document from an HTML template. Then, I used the download url with an access token to fetch the pdf Blob and attach it to the email.

    The result is the following:

    enter image description here enter image description here

    Reading through the code you should be able to catch what it's being done in detail and of course, you can improve it!


    References: