[SalesForce] Visualforce page doesn’t renderAs pdf (used as attachment it’s blank)

I have a requirement where I need to send an email with attached PDF of Invoice . But I am getting blank PDF. please suggest how can this be rectified.

When I add renderAs = "PDF" , I am getting the Error "PDF generation failed. Check the page markup is valid."

    public PageReference attachCurrentPage() {
            /* At this moment there should be only one attached PDF version,
            so we'll delete all existing before inserting new one.*/
            List<Attachment> existingAttachments = [SELECT Id FROM Attachment WHERE ParentId = :orderId];
           // delete existingAttachments;

            // Insert current page as PDF attachment to the Order.        
            System.PageReference currentPage = ApexPages.currentPage();
            Blob pdfData = currentPage.getContentAsPDF();
            Attachment attach = new Attachment();
            attach.ParentId = orderId;
            attach.Name = 'Invoice_'+System.now()+'.pdf';
            attach.Body = pdfData;
            insert attach;
            return null;        
        }



<apex:page standardController="Order__c" extensions="Cls_Invoice" showHeader="false" sidebar="false" standardStylesheets="true">
<script>
function reload() 
{

   window.top.location='/{!Order__c.id}'; 

}
</script>
<style>
table,th,td
{
padding:5px;
}
</style>

 <table width="100%">
        <tr>
            <th>Customs Invoice</th>
            <!--td rowspan="2"-->
            <th> <apex:image value="{!$Resource.image1}" width="170" height="75"  /> </th> 
        </tr>
        <tr>
            <td>Value for customs purpose only<br/>Tax free export</td> 
            <td>  Date:&nbsp;<apex:outputField value="{Order__c.CreatedDate}"/><br/></td>
<apex:image value="{!$Resource.cancelledimage}"  width="150" height="150"  rendered="{!Order__c.Order_Cancelled__c ==true}"/>
        </tr>     
 </table>


<table width="100%">
<tr>
            <th colspan="2">  Shipping Information</th>
</tr>

</table>
<table width="100%">
<tr>
  <th>Sent to</th>
  <th>Sent from</th>     
</tr>
<tr>
   <td>
      {!Order__c.Shipping_Address__c}
   </td>
   <td>MyAddress   </td>
  <!-- 
  <td rowspan="2">Terms of delivery: DDP
               <br/>Total Gross Weight: {!Order__c.Total_Gross_Weight__c}
                <br/>Total Net Weight: {!Order__c.Total_Net_Weight__c} 
                                <br/>Carrier: DHL
            </td>
   -->
</tr>
 </table >
    <B>  &nbsp; Package Details </B>      
    <apex:form >
        <apex:pageBlock >     
                 <apex:pageBlockTable value="{!OrderProductList}" var="prod">
                    <apex:pageMessages ></apex:pageMessages>                        
                        <apex:column headerValue="Product Description">
                            <apex:outputField value="{!prod.Name}"/>
                        </apex:column>
                        <apex:column headerValue="Quantity">
                            <apex:outputField value="{!prod.Quantity__c}"/>
                        </apex:column>    
                        <apex:column headerValue="Unit Value">
                            <apex:outputField value="{!prod.Price__c}"/>
                        </apex:column>
                        <apex:column headerValue="Sub Total Value">
                                <apex:outputField value="{!prod.Total_Price__c}"/>
                        </apex:column>                      
               </apex:pageBlockTable> 
       </apex:pageBlock>

   <!--  
<table border="1" cellspacing="0">
        <tr>
            <td>Number of items</td>
            <td>{!Order__c.Quantity__c}</td>
        </tr>
        <tr>
           <th>Total</th>
            <th><apex:outputField value="{!Order__c.Total_Price__c}"/></th>
        </tr>
    </table> -->
    <!-- ============================ -->
    <br/>
    <br/>
     <table width="100%">
        <tr>
            <span>
                &nbsp; Reason for Export: Repair/Replacement (goods are delivered free of charge)<br/>
                &nbsp; I declare that the above information is true and correct to the best of my knowledge.<br/>
                <br/>
                 <br/>
                 &nbsp;Signature <br/>
                 &nbsp;{!Order__c.Case__r.Owner.Name}
            </span>
        </tr>
     </table>
     <apex:image value="{!$Resource.ad}" width="150" height="75"  /><br/>
    <center>&nbsp;<apex:commandButton value="Save as attachment" action="{!attachCurrentPage}" status="closer" oncomplete="reload();"   reRender="buttons" />
    &nbsp;<apex:commandButton onclick="window.top.close();" value="Close" />
    &nbsp;<apex:actionStatus startText="(Saving...)" stopText="" onstop=" window.top.close();opener.location.reload(true);"  id="closer"  />   
    &nbsp;<apex:commandButton value="Send Email" action="{!send}"/>  </center>
 </apex:form>
</apex:page>

Best Answer

One thing to watch out is the use of images stored in static resources. PDF rendering engine doesn't like them. Start with deleting / commenting out the image-related tags.

If it fixes it - you can still use images you've uploaded to Documents tab (as long as they're marked as "externally available". In my current org I've uploaded logos to production's Documents folder and all email templates point to production link. Looks off, you'd maybe want to point to current sandbox but in dev sandboxes the Documents will always be empty. So it becomes a bit of preference, do you want templates that work everywhere or are you after clear distinction that email from sandbox is OK to not have images so nobody can do something with it by mistake.


Apart from that - ditch the JavaScript, <apex:form>, <apex:commandButton> and other "interactive" elements. Buttons will render (like <apex:detail> will) but it doesn't mean it's a good idea.

Related Topic