Skip to main content

Creating Super Awesome PDF's with Salesforce


Brief intro Salesforce PDF


Salesforce under the hood uses "Flying-Saucer" rendering engine to render the pdf of the fly.
Check out more about Flying-Saucer here :
It basically supports CSS2.1 and minimal features of CSS3.

I would recommend you to go through @Page css properties
and this link for a better understanding
http://www.antennahouse.com/CSSInfo/CSS-Page-Tutorial-en.pdf

Lets get started:

Case1 :
Repeating Header / Footer

In this example we will have our Logo as header and Page number as the footer
 which will repeated in all the pages of the document.


Demo

The Code:
<apex:page renderAs="pdf" standardStylesheets="false" showHeader="false" applyHtmlTag="false" >
   <head>
       
            <style>
            
            @page
            {
                margin-top:70px;
                margin-left:0px;
                margin-right:0px;
               
                size:portrait;              
                background-color:#EDEDED;
                
              
                @top-left
                {
                    content : element(top-left-div);
                    
                }
                @top-center
                {
                    content : element(top-center-div);
                }
                @top-right
                {
                  
                    content : element(top-right-div) ;
                }
                
                
                @bottom-left
                {
                    content : element(bottom-left-div);
                }
                
                @bottom-center
                {
                    content : element(bottom-center-div);
                }
                
                @bottom-right
                {
                    content : element(bottom-right-div);
                }
                
            }
           
            .top-left-div
            {
                position: running(top-left-div);
               
                background-color:#01a3d6;
                
                color:white;
                text-align:left;
               
                border-bottom: 2px solid black;
                padding:17.5px;
              
            }
             .top-center-div
            {
                position: running(top-center-div);
               
                background-color:#01a3d6;
                color:white;
                text-align:center;
                
                
                border-bottom: 2px solid black;
                padding:25px;
                
            }
             .top-right-div
            {
                position: running(top-right-div);
               
                background-color:#01a3d6;
                text-align:right;
                color:white;
                
                
                border-bottom: 2px solid black;
                padding:25px;
            }
            
            .bottom-left-div
            {
                position: running(bottom-left-div);                  
                
                color:#666666;
                
                text-align:left;                
                margin:5px;
               
                        
            }
             .bottom-center-div
            {
                position: running(bottom-center-div);             
               
                color:#666666;
               
                text-align:center;
                margin:5px;
                
                
            }
             .bottom-right-div
            {
                position: running(bottom-right-div);
                
                color:#666666;
                
                text-align:right;
                margin:5px;
               
                              
            }
            
            
            .pagenumber:before 
            {
                 content: counter(page);
            }

            .pagecount:before 
            {
                content: counter(pages);
            }
            
            
            .content
            {
                margin:10px;
                
                
            }
            .pageFont
            {
                font-family: Arial, Helvetica, sans-serif;
            }
            </style>
    </head>
    
    <body>
        <!-- HEADER INFO BEGIN-->
           
            <div class="top-left-div pageFont">
            
                <!-- THE LOGO -->
                <img src="{!URLFOR($Resource.cloudLogo)}" height="30px"  />
                
            </div>
             <div class="top-center-div pageFont">
                TOP - CENTER
            </div>
             <div class="top-right-div pageFont">
                
                   <div>
                     TOP - RIGHT  
                         
                     </div>
            </div>
       <!-- HEADER INFO END-->

        <!-- FOOTER INFO BEGIN-->
             <div class="bottom-left-div pageFont">
                BOTTOM - LEFT
            </div>
             <div class="bottom-center-div pageFont">
                BOTTOM - CENTER
            </div>
             <div class="bottom-right-div pageFont">
                 <span class="pagenumber"/> 
                           |
                 <span class="pagecount"/>
            </div>
       
       
       <!-- FOOTER INFO END--> 

       <!-- CONTENT -->
       <div class="content pageFont"> 
          THE CONTENT IN PAGE 1
         </div>  
        
        
       <!-- NEW PAGE -->
       <div style="page-break-after:always;"/>
   
            <div class="content pageFont"> 
               THE CONTENT IN PAGE 2
            </div>  
         
    </body>
</apex:page>

Case 2 :
Repeating Header / Footer
First Page is LandScape and rest all are in Portrait

Demo

Just add the following CSS to previous code and you are all set !
   @page:first
            {
                size:landscape;
            }


Case 3 :
Repeating Header / Footer
First n Pages is Portrait and rest n in LandScapemode

For this we make use named page selectors.
First 2 pages are in portrait mode and the next 2 are in landscape mode.
The base code remains the same ,the additions are highlighted in blue.

Demo

Code:
   <apex:page renderAs="pdf" standardStylesheets="false" showHeader="false" applyHtmlTag="false" >
   <head>
       
            <style>
            
            @page landscapeMode
            {
                size : landscape;
            }
                       
            
            
            @page
            {
                margin-top:70px;
                margin-left:0px;
                margin-right:0px;
                
                size : portrait;
                
                background-color:#EDEDED;
                
              
                @top-left
                {
                    content : element(top-left-div);
                    
                }
                @top-center
                {
                    content : element(top-center-div);
                }
                @top-right
                {
                  
                    content : element(top-right-div) ;
                }
                
                
                @bottom-left
                {
                    content : element(bottom-left-div);
                }
                
                @bottom-center
                {
                    content : element(bottom-center-div);
                }
                
                @bottom-right
                {
                    content : element(bottom-right-div);
                }
                
            }
           
            .top-left-div
            {
                position: running(top-left-div);
               
                background-color:#01a3d6;
                
                color:white;
                text-align:left;
               
                border-bottom: 2px solid black;
                padding:17.5px;
              
            }
             .top-center-div
            {
                position: running(top-center-div);
               
                background-color:#01a3d6;
                color:white;
                text-align:center;
                
                margin-left:-1px;
                border-bottom: 2px solid black;
                padding:25px;
                
            }
             .top-right-div
            {
                position: running(top-right-div);
               
                background-color:#01a3d6;
                text-align:right;
                color:white;
                
                margin-left:-1px;
                border-bottom: 2px solid black;
                padding:25px;
            }
            
            .bottom-left-div
            {
                position: running(bottom-left-div);                  
                
                color:#666666;
                
                text-align:left;                
                margin:5px;
               
                        
            }
             .bottom-center-div
            {
                position: running(bottom-center-div);             
               
                color:#666666;
               
                text-align:center;
                margin:5px;
                
                
            }
             .bottom-right-div
            {
                position: running(bottom-right-div);
                
                color:#666666;
                
                text-align:right;
                margin:5px;
               
                              
            }
            
            
            .pagenumber:before 
            {
                 content: counter(page);
            }

            .pagecount:before 
            {
                content: counter(pages);
            }
            
            
            .landscapePages
            {
                page : landscapeMode;
            }
               
            
            .content
            {
                margin:10px;
                
                
            }
            .pageFont
            {
                font-family: Arial, Helvetica, sans-serif;
            }
            </style>
    </head>
    
    <body>
        <!-- HEADER INFO BEGIN-->
           
            <div class="top-left-div pageFont">
            
                <!-- THE LOGO -->
                <img src="{!URLFOR($Resource.cloudLogo)}" height="30px"  />
                
            </div>
             <div class="top-center-div pageFont">
                TOP - CENTER
            </div>
             <div class="top-right-div pageFont">
                
                   <div>
                     TOP - RIGHT  
                         
                     </div>
            </div>
       <!-- HEADER INFO END-->
        <!-- FOOTER INFO BEGIN-->
             <div class="bottom-left-div pageFont">
                BOTTOM - LEFT
            </div>
             <div class="bottom-center-div pageFont">
                BOTTOM - CENTER
            </div>
             <div class="bottom-right-div pageFont">
                 <span class="pagenumber"/> 
                           |
                 <span class="pagecount"/>
            </div>
       
       
       <!-- FOOTER INFO END--> 
       
        <!-- POTRAIT PAGES BEGIN -->
            <div class="content pageFont"> 
                  THE CONTENT IN PORTRAIT PAGE 1
                 </div>  
         
           <!-- NEW PAGE -->
            <div style="page-break-after:always;"/>
         
           <div class="content pageFont"> 
                      THE CONTENT IN PORTRAIT  PAGE 2
               </div> 
         
       <!-- POTRAIT PAGES END-->
      <!-- LANDSCAPE PAGES BEGIN -->

       <div class="landscapePages">
           <div class="content pageFont"> 
                  THE CONTENT IN LANDSCAPE PAGE 1
                 </div>  
                
                
               <!-- NEW PAGE -->
               <div style="page-break-after:always;"/>
           
               <div class="content pageFont"> 
                      THE CONTENT IN LANDSCAPE PAGE 2
               </div>                                      
      </div> 
              <!-- LANDSCAPE PAGES END -->
     </body>
</apex:page>

Happy Coding !!!!!

Comments

  1. Hey Pavan, I need to display a tag(DIV) content (Payment adivce of the invoice which users can tear it off) in the bottom of the last page of the PDF(i.e. Above the footer).
    Could you please help me in doing that I've been struggling to fix that thing from past week

    ReplyDelete

Post a Comment

Popular posts from this blog

Restricting the file types upload in salesforce chatter

Restricting the file types upload in salesforce chatter To restrict the file types one option is to write a trigger on "Feeditem". Developing the Trigger: Open developer console ,go to "File"---> "New" --->"Apex Trigger". From the pop-up give the name of the trigger and choose the sObject as "FeedItem" from the dropdown and hit "Submit" Start Coding !! //TRIGGER TO RESTRICT FILE TYPES ON CHATTER trigger restrictFileType on FeedItem (after insert) {                   for(FeedItem fi : Trigger.new)                    {                                  if(fi.ContentType == 'text')                                            fi.addError('You are not allowed to upload this kin...

Solving the Logout back button problem through javascript.

In this blog we will see how to solve the logout back button problem, this is a simple solution to handle but its not robust but still works well less number of pages. Here is the JS for <pre> function preventBack(){          window.history.forward();                   }                   setTimeout("preventBack()", 0);          window.onunload=function(){null}; </pre> Here is the Demo Another way of overcoming this would be adding recaptcha to the login form , even though the form gets resubmitted it will fail at captcha as it would be different for every page load.