Emailing Visualforce Pages Rendered as PDFs

I blogged the other day about how to dynamically choose whether a Visualforce page is rendered as a PDF or not-useful when creating invoices and so on.  Now I’m going to email that page using a little Apex code.

First, let’s define the page:

<apex:page renderAs="{!if($CurrentPage.parameters.p == null, null, 'pdf')}"
           controller="MyController">
     <apex:pageBlock title="My Dual-Rendering Invoice">
        <apex:pageBlockSection title="Section 1"> Text </apex:pageBlockSection>
        <apex:pageBlockSection title="Section 2"> Text </apex:pageBlockSection>
    </apex:pageBlock>
             <apex:form >
                <apex:commandLink rendered="{!$CurrentPage.parameters.p == null}"  value="PDF"
             action="{!deliverAsPDF}" ></apex:commandLink>
             </apex:form>
</apex:page>

This is a refinement of the one I blogged last time, using some tips from Doug Chasman.  Note that the outputlink won’t render in the final PDF – cool!  The only key thing here is that the page will render as a PDF if a parameter “p” is passed in. Otherwise it renders as HTML.

The question is how to write our getDeliverAsPDF() method to create the PDF and mail it off in an email.  Here’s how I coded the controller to do this:

public class MyController { public PageReference getDeliverAsPDF() {
     // Reference the page, pass in a parameter to force PDF
     PageReference pdf =  Page.foo;
     pdf.getParameters().put('p','p');
     pdf.setRedirect(true);
     // Grab it!
      Blob b = pdf.getContent();
     // Create an email
     Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
      email.setSubject('From getDeliverAsPDF!');
     String [] toAddresses = new String[] {'foobar@youremailaddressz.com'};
     email.setToAddresses(toAddresses);
     email.setPlainTextBody('Here is the body of the email');
     // Create an email attachment
     Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
     efa.setFileName('MyPDF.pdf'); // neat - set name of PDF
     efa.setBody(b); //attach the PDF
     email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});
     // send it, ignoring any errors (bad!)
     Messaging.SendEmailResult [] r =
             Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});
        return null;
 }}

The only tricky bit here is the pdf.GetContent() method, which grabs the rendered PDF content.  I then stuff it into an email attachment and send it off!

 


Technorati Tags:
,

 

tagged Bookmark the permalink. Trackbacks are closed, but you can post a comment.
  • http://www.leancrm.com/ Andreas Schaefer

    very cool! this should also allow me to save the rendered pdf as an attachment to e.g. an opportunity instead of e-mailing it.

  • http://developer.force.com/ Jon Mountjoy

    Hi Andreas
    Because it’s simply Apex, you can do a lot of things with the PDF, including adding an attachment like you suggest. To do this, instead of emailing the blob (b) above, I could wrap it in an attachment and insert the new attachment object like so:

    Attachment a = new Attachment(parentId =idOfContactOrOppToWhichToAttach, name=’JONSATTACHMENT.pdf’,body=b);
    insert a;

  • http://asdf.org foo

    Very neat <<< """ " <

  • Nick

    This looks great.
    Does anyone know if you can use this method to set the From address in the email?

  • http://developer.force.com/ Jon Mountjoy

    Hi Nick
    A quick search of our forums yields the answer: no.
    See here for an explanation.
    http://tinyurl.com/5csrwk
    Regards,
    Jon

  • Mark

    Is there a way to record sending this email into and objects activity history?

  • sreedhar

    Great stuff…
    One question: Assuming we have a free text box in the VF page, How do we capture the content typed in the same in the emailed PDF?
    Thanks in advance?

  • http://developer.force.com/ Jon Mountjoy

    No idea sreedhar. It’s easy to imagine your controller displaying information that’s it’s grabbed from the database. Perhaps you can display that field in the page? ie. put it in an outputfield somewhere, which is only shown when you are generating a PDF?