A colleague recently came to me with a ‘problem’ that he was scratching his head about.

His requirement was to generate multiple documents (PDFs in this case) from data stored in varying objects in salesforce, which he needed to be zipped and attached to an object or otherwise able to be downloaded.

My initial answer to him was simple, just install Conga and be done with it. Unfortunately, as this particular organisation is unable to use anything that was hosted on AWS (I know… ) Conga was out.

So after thinking a little bit more, I remembered that, thanks to the PageReference class, you can ‘access’ visualforce pages programmatically (amongst other things), and store the resulting output in a Blob.

For example, lets say you have a simple visualforce page that displays some information from an account record.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<apex:page standardController="Account" standardStylesheets="false" showHeader="false" sidebar="false" renderAs="PDF">
    <html>
        <head>
        </head>
        <body>
 
            <h1>Account Summary for {! Account.Name }</h1>
 
            <table>
                <tr><th>Phone</th>  <td><apex:outputText value="{! Account.Phone }"/></td></tr>
                <tr><th>Fax</th>    <td><apex:outputText value="{! Account.Fax }"/></td></tr>
                <tr><th>Website</th><td><apex:outputText value="{! Account.Website }"/></td></tr>
            </table>
 
            <p><apex:outputText value="{! Account.Description }"/></p>
        </body>
    </html>
 
</apex:page>

In this example, we will generate some of these ‘Account Summary’ PDFs for a given list of accounts. Its very simple really;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//some accounts for this example
List acts = [ SELECT Id, Phone, Fax, Website, Description, Name FROM Account LIMIT 10];
//the resulting list of blobs containing the generated pdfs
List generatedPdfs = new List();
 
  for(Account a :acts) {        
    //PageReference for the visualforce page we wish to use
    PageReference pdf = Page.Account;
    //provide it with the require parameters
    pdf.getParameters().put('Id', a.Id);
    //access it and store it as a blob
    Blob b = pdf.getContent();
    generatedPdfs.add(b);
}

Now we have a blob of each page, and bear in mind that they don’t all have to be the same page, I am simply using a loop to generate multiple PDFs without having to write a bunch of visualforce pages for this example.

With those blobs, we can do a few things. We could post them to chatter, attach them to a record, or post them to a content library.

We could also, using a very cool ‘library’ I found called ‘Zippex‘ we could zip them all up, then post to the resulting zip to chatter, content, attachments, etc.

This isn’t just for PDFs. Using the contentType attribute of visualforce, you could output a bunch of CSVs, or other document types (see here for some more on this) and zip/attach them as well.

Some things to bear in mind;

  • If your visualforce pages perform SOQL, looping through them may cause you to hit query limits
  • Generating lots of documents will cause you to hit the heap size limit
  • Zipping lots of documents may cause you to hit the CPU limit
  • There is a reason that apps like conga handle this off platform.

    However, if you’ve got some existing visualforce pages, can accept these limitations and need a way to generate and attach documents without a tool like Conga, this is an option for you.

    Here is a link to some more example code on my github

    Leave a Reply

    Your email address will not be published. Required fields are marked *