Search code examples
google-apps-scriptgoogle-sheetsgoogle-docsgoogle-forms

Generate & send a png or jpg from a Google Form Submission (script attached to Google Sheet that references a Google Doc template)


I have a google form survey that I send to my app members. I want to include a way for them to create a custom Instagram story post that I'd auto-generate based on their input and email to them to post. The template I use to auto-generate it is a google doc with a placeholder where I plug in their custom input.

My script currently is able to send them the post as a PDF, but that's really frustrating to post on an Instagram story (if not impossible - I spent 20 mins trying to do it).

Is it possible to have the file send as a jpg or png? Or to add a step converting the PDF to a jpg or png?

function onSubmit(e) {
  const rg = e.range;
  const sh = rg.getSheet();
  
  //Get all the form submitted data
  //Note: This data is dependent on the headers. If headers, are changed update these as well.
  const Email = e.namedValues["What's your email address?"][0];
  const Name = e.namedValues["What's your name?"][0];
  const Text = e.namedValues["If you want to make a custom Instagram story sharing what your experience was like, feel free to drop your text here!"][0];
  
  //Build a new story from the template
  //Folder ID (save destination) and file IDs (template ID + new doc ID)
  const StoryFolderID = '1ghiNSWwkUS7WJ5wwnEON5g0-zRueYlfd';
  const StoryFolder = DriveApp.getFolderById(StoryFolderID);
  
  const TemplateFileID = '1IJ-i8VeazzmWlxyjyXXKHCLrA3pT1fgu4Zy_m74OgHc';
  const newFilename = 'Story -' + TemplateFileID;
  
  //Make a copy of the template file
  const newTemplateFileID = DriveApp.getFileById(TemplateFileID).makeCopy(newFilename, StoryFolder).getId();;
  
  //Get the body into a variable
  var document = DocumentApp.openById(newTemplateFileID);
  var body = document.getBody();
  
  //Replace all the {{ }} text in the story body
  body.replaceText('{{text}}', Text);

  document.saveAndClose();

// define email variables
var subject = 'Instagram Story';
var img = DriveApp.getFileById("1d2jofSzEsxuUUEw5g-B684AKMALqyy-b").getBlob();



var msgHtml = 
"Hi " + Name + "!" + "<br/>" + "<br/>" +
"Please find your custom story image attached."  ;
var attachment = DriveApp.getFileById(newTemplateFileID);

//send email with the file
GmailApp.sendEmail(Email, subject, msgHtml, {htmlBody: msgHtml, inlineImages: {sampleImage: img}, attachments: [attachment.getAs(MimeType.PDF)]});
  }


Solution

  • About Is it possible to have the file send as a jpg or png? Or to add a step converting the PDF to a jpg or png?, in this case, I thought that my this blog might be useful. In this blog, a PDF data is converted to PNG images for every page. When this is reflected in your script, how about the following modification?

    Modified script:

    In this sample, Drive API is used. So, please enable Drive API at Advanced Google services.

    /**
     * This is a method for converting all pages in a PDF file to PNG images.
     * PNG images are returned as BlobSource[].
     * IMPORTANT: This method uses Drive API. Please enable Drive API at Advanced Google services.
     *
     * @param {Blob} blob Blob of PDF file.
     * @return {BlobSource[]} PNG blobs.
     */
    async function convertPDFToPNG_(blob) {
      // Convert PDF to PNG images.
      const cdnjs = "https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js";
      eval(UrlFetchApp.fetch(cdnjs).getContentText()); // Load pdf-lib
      const setTimeout = function (f, t) {
        // Overwrite setTimeout with Google Apps Script.
        Utilities.sleep(t);
        return f();
      };
      const data = new Uint8Array(blob.getBytes());
      const pdfData = await PDFLib.PDFDocument.load(data);
      const pageLength = pdfData.getPageCount();
      console.log(`Total pages: ${pageLength}`);
      const obj = { imageBlobs: [], fileIds: [] };
      for (let i = 0; i < pageLength; i++) {
        console.log(`Processing page: ${i + 1}`);
        const pdfDoc = await PDFLib.PDFDocument.create();
        const [page] = await pdfDoc.copyPages(pdfData, [i]);
        pdfDoc.addPage(page);
        const bytes = await pdfDoc.save();
        const blob = Utilities.newBlob(
          [...new Int8Array(bytes)],
          MimeType.PDF,
          `sample${i + 1}.pdf`
        );
        const id = DriveApp.createFile(blob).getId();
        Utilities.sleep(3000); // This is used for preparing the thumbnail of the created file.
        const link = Drive.Files.get(id, { fields: "thumbnailLink" }).thumbnailLink;
        if (!link) {
          throw new Error(
            "In this case, please increase the value of 3000 in Utilities.sleep(3000), and test it again."
          );
        }
        const imageBlob = UrlFetchApp.fetch(link.replace(/\=s\d*/, "=s1000"))
          .getBlob()
          .setName(`page${i + 1}.png`);
        obj.imageBlobs.push(imageBlob);
        obj.fileIds.push(id);
      }
      obj.fileIds.forEach((id) => DriveApp.getFileById(id).setTrashed(true));
      return obj.imageBlobs;
    }
    
    async function onSubmit(e) {
      const rg = e.range;
      const sh = rg.getSheet();
    
      //Get all the form submitted data
      //Note: This data is dependent on the headers. If headers, are changed update these as well.
      const Email = e.namedValues["What's your email address?"][0];
      const Name = e.namedValues["What's your name?"][0];
      const Text = e.namedValues["If you want to make a custom Instagram story sharing what your experience was like, feel free to drop your text here!"][0];
    
      //Build a new story from the template
      //Folder ID (save destination) and file IDs (template ID + new doc ID)
      const StoryFolderID = '1ghiNSWwkUS7WJ5wwnEON5g0-zRueYlfd';
      const StoryFolder = DriveApp.getFolderById(StoryFolderID);
    
      const TemplateFileID = '1IJ-i8VeazzmWlxyjyXXKHCLrA3pT1fgu4Zy_m74OgHc';
      const newFilename = 'Story -' + TemplateFileID;
    
      //Make a copy of the template file
      const newTemplateFileID = DriveApp.getFileById(TemplateFileID).makeCopy(newFilename, StoryFolder).getId();;
    
      //Get the body into a variable
      var document = DocumentApp.openById(newTemplateFileID);
      var body = document.getBody();
    
      //Replace all the {{ }} text in the story body
      body.replaceText('{{text}}', Text);
    
      document.saveAndClose();
    
      // define email variables
      var subject = 'Instagram Story';
      var img = DriveApp.getFileById("1d2jofSzEsxuUUEw5g-B684AKMALqyy-b").getBlob();
    
      var msgHtml =
        "Hi " + Name + "!" + "<br/>" + "<br/>" +
        "Please find your custom story image attached.";
    
      var attachment = DriveApp.getFileById(newTemplateFileID);
      const imageBlobs = await convertPDFToPNG_(attachment.getBlob());
    
      //send email with the file
      GmailApp.sendEmail(Email, subject, msgHtml, { htmlBody: msgHtml, inlineImages: { sampleImage: img }, attachments: imageBlobs });
    }
    
    • When onSubmit is run, the PDF data of attachment.getBlob() is converted to PNG images and the PNG images are used with attachments: imageBlobs.

    Reference: