function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Vandana RattanVandana Rattan 

Problem Creating VisualForce QuotePDF

I have created a JavaScript Button to Create quotes automatically. Now I am trying to generate the PDF for the same automatically. My requirement is:-

1) Generate and attach the Quote PDF automatically.
2) Once the PDF is generated, email the Quote PDF automatically to the customer.

For 1: I am writing a visualforce page for generating Quote PDF. The PDF is getting generated but the data related to quote like QuoteNumber is not getting rendered.:-

<apex:page standardController="Quote" showHeader="false" renderAs="pdf" applyhtmltag="false" >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<style type="text/css">
body {
    font-family: sans-serif;
    font-size:12px;
}
table.imagetable {
    width:100%;
    font-family: sans-serif;
    font-size:12px;
    color:#333333;
    border-width: 1px;
    border-color: #999999;
    border-collapse: collapse;
}

table.imagetable th {
    background:#C0D5D8;
    border-width: 1px;
    padding: 8px;
    border-style: solid;
    border-color: #999999;
}

table.imagetable td {
    background:#EFEFEF;
    border-width: 1px;
    padding: 8px;
    border-style: solid;
    border-color: #999999;
}

table.sectionHeadings {
    font-family: sans-serif;
    font-size:16px;
    color:#1E4481;
    border-width: .5px;
    border-color: #999999;
    border-collapse: collapse;
}

table.sectionHeadings th{
    padding: 15px;
    border-top-style:solid;
    border-top-color:#1E4481;
    border-bottom-style:solid;
    border-bottom-color:#1E4481;
    width: 690px;
}

table.headingTopLine th{
    font-family: sans-serif;
    font-size:16px;
    color:#1E4481;
    padding: 15px;
    border-top-style:solid;
    border-top-color:#1E4481;
    width: 690px;
}
table.headingBottomLine td{
    font-family: sans-serif;
    font-size:16px;
    color:#1E4481;
    padding: 15px;
    border-bottom-style:solid;
    border-bottom-color:#1E4481;
    width: 40px;
}

</style>
</head>    
<body> 
     <!--<apex:form >
     <apex:actionFunction name="savePDF" action="{!savePDF}" />
     </apex:form>-->  
     <apex:panelGrid columns="3" width="100%" style="font-size: 12px; font-family: sans-serif">
        <!-- <apex:image url="<a target="_blank" href="https://c.cs14.content.force.com/servlet/servlet.ImageServer?oid=00Dc0000001LPXH&id=015c000000075xm"">https://c.cs14.content.force.com/servlet/servlet.ImageServer?oid=00Dc0000001LPXH&id=015c000000075xm"</a> width="208" height="79" /> -->   
         <apex:panelGroup layout="block" >
             <apex:outputText value="{!$Organization.Name}" /><br></br>
             <apex:outputText value="{!$Organization.Street}"/><br></br>
             <apex:outputText value="{!$Organization.City}, {!$Organization.State} {!$Organization.PostalCode}"/><br></br>
             <apex:outputText value="{!$Organization.Phone}"/>
         </apex:panelGroup>
         <apex:panelGroup layout="block" >             
             <apex:outputText value="Created Date: {!TODAY()} "/><br></br>             
             <!--<apex:outputText value="Offer Expires: {!Quote.ExpirationDate}"/><br></br>-->
             <apex:outputText value="Quote Number: {!Quote.QuoteNumber}"/><br></br>
             <!--<apex:outputText value="Reference: {!Quote.Opportunity}"/>-->
         </apex:panelGroup>
     </apex:panelGrid>
     <br> </br>
     
     <!-- Order Schedule Section Heading  -->
     
     <table Class="sectionHeadings" >
         <tr>
         <th>Order Schedule<br> </br></th>
         </tr>         
     </table>
     <br> </br>
     
     <!-- Prepared for Bill To Section -->
     
     <table  width="100%" >
         <tr >
         <th><apex:outputText value="Prepared for" /></th>         
         <th><apex:outputText value="Bill to" /></th>        
         </tr>       
         <tr>             
         <td><apex:outputText value="Name    : {!Quote.Contact.FirstName} {!Quote.Contact.LastName}" /></td>             
         <td><apex:outputText value="Name  : {!Quote.Opportunity.Name}"></apex:outputText></td>
         <!--<td><apex:outputText value="Name    : {!Quote.BillingName}" /></td>-->
         </tr>
         <!--<tr>             
         <td><apex:outputText value="Company    : {!Quote.Opportunity.Account.Name}" /></td>             
         <td><apex:outputText value="Company    : {!Quote.Opportunity.Account.Name}" /></td>
         </tr>-->
         <tr>             
         <td><apex:outputText value="Address : {!Quote.Contact.MailingStreet}" /></td>             
         <td><apex:outputText value="Address : {!Quote.BillingStreet}" /></td>
         </tr>
         <tr>             
         <td><apex:outputText value="  {!Quote.Contact.MailingCity}, {!Quote.Contact.MailingState} {!Quote.Contact.MailingPostalCode}" style="margin-left:55px" /></td>             
         <td><apex:outputText value="  {!Quote.BillingCity}, {!Quote.BillingState} {!Quote.BillingPostalCode}" style="margin-left:55px" /></td>
         </tr>
         <tr>             
         <td><apex:outputText value="Phone : {!Quote.Contact.Phone}" /></td>             
         <td><apex:outputText value="Phone : {!Quote.Opportunity.Account.Phone}" /></td>
         </tr>
         <tr>             
         <td><apex:outputText value="Email : {!Quote.Contact.Email}" /></td>             
         <td><apex:outputText value="Email : {!Quote.Contact.Email}" /></td>
         </tr>                    
     </table>
     <br> </br>
     
     <!-- Terms Section  -->
     
         <table class="headingTopLine">
         <tr>
         <th > Terms </th>
         </tr>
         <!--<tr>
                      
         <td><apex:outputText value="{!Quote.Billing_Terms__c}" style="font-weight:bold" /></td>                     
         </tr> 
         <tr>         
         <td><apex:outputText value="Payment terms    " style="font-weight:bold" rendered="{!IF((Quote.Billing_Terms__c="Fixed Fee Upfront"),true,false)}" escape="false" /> 
         <apex:outputText value=": Professional fees are due 100% upon the Effective Date.  All invoices are due upon receipt." rendered="{!IF((Quote.Billing_Terms__c="Fixed Fee Upfront"),true,false)}" escape="false" style="margin-left:10px" />          
         </td>
         </tr>
         <tr>
         <td><apex:outputText value="Payment method  " style="font-weight:bold" rendered="{!IF((Quote.Billing_Terms__c="Fixed Fee Upfront"),true,false)}" escape="false" /> 
         <apex:outputText value="   : Standard Invoicing - This option is available only for annual billing. You will be invoiced per the agreed upon payment terms as outlined on this Order Schedule." rendered="{!IF((Quote.Billing_Terms__c="Fixed Fee Upfront"),true,false)}" escape="false"  />          
         </td>         
         </tr>
         <tr>
         <td><apex:outputText value="Payment terms  " style="font-weight:bold" rendered="{!IF((Quote.Billing_Terms__c="Fixed Fee Milestone Project Based"),true,false)}" escape="false"/> 
         <apex:outputText value="   : Professional fees are due …  .All invoices are due upon receipt." rendered="{!IF((Quote.Billing_Terms__c="Fixed Fee Milestone Project Based"),true,false)}" escape="false" style="margin-left:10px"/>          
         </td>
         </tr>
         <tr>
         <td><apex:outputText value="Payment method  " style="font-weight:bold" rendered="{!IF((Quote.Billing_Terms__c="Fixed Fee Milestone Project Based"),true,false)}" escape="false" /> 
         <apex:outputText value="   : To be completed" rendered="{!IF((Quote.Billing_Terms__c="Fixed Fee Milestone Project Based"),true,false)}" escape="false" />          
         </td>         
         </tr>
         <tr>
         <td><apex:outputText value="Payment terms  " style="font-weight:bold" rendered="{!IF((Quote.Billing_Terms__c="Time And Materials"),true,false)}" escape="false" /> 
         <apex:outputText value="   : To be completed" rendered="{!IF((Quote.Billing_Terms__c="Time And Materials"),true,false)}" escape="false"  style="margin-left:10px"/>          
         </td>         
         </tr>
         <tr>
         <td><apex:outputText value="Payment method  " style="font-weight:bold" rendered="{!IF((Quote.Billing_Terms__c="Time And Materials"),true,false)}" escape="false" /> 
         <apex:outputText value="   : To be completed" rendered="{!IF((Quote.Billing_Terms__c="Time And Materials"),true,false)}" escape="false" />          
         </td>         
         </tr>-->
         </table>
         <br> </br>  
         
               
     <!-- Start of Quote Line Items *****
     ****                           *****
     ****                           **-->
     <div style="page-break-after:always;">  
     <table class="headingTopLine">
         <tr>
         <th > Product - Consulting </th>
         </tr>
     </table>
          <table class="imagetable">
         <tr>
         <th><apex:outputText value="{!$ObjectType.Product2.Fields.ProductCode.Label}" /></th>
         <th><apex:outputText value="Product" /></th>
         <th><apex:outputText value="Qty" /></th>
         <th><apex:outputText value="List" /></th>
         <th><apex:outputText value="Discount" /></th>
         <th><apex:outputText value="Sale Price" /></th>
         <th><apex:outputText value="Total Price" /></th>
         </tr>
         <!--<apex:repeat value="{!consultingLineItems}" var="line"  >-->         
         <!--<tr>
             
             <td><apex:outputField value="{!line.Product_CodeF__c}" /></td>
             <td><apex:outputField value="{!line.Product_NameF__c}" /></td>
             <td><apex:outputField value="{!line.Quantity}" /></td>
             <td><apex:outputField value="{!line.ListPrice}" /></td>
             <td><apex:outputField value="{!line.Discount}" /></td>
             <td><apex:outputField value="{!line.UnitPrice}" /></td>
             <td><apex:outputField value="{!line.TotalPrice}" /></td>
              
         </tr>-->
         <!--</apex:repeat>-->             
     </table>
      <apex:outputPanel layout="block" />
          <apex:panelGrid columns="2" columnClasses="right" width="100%">
              <apex:panelGrid columns="2" cellpadding="10" columnClasses="right totalLabel,right total" width="100%">
                  <apex:outputText value="Total"/>
                  <!--<apex:outputText value="{!consultingTotal}"/>-->
              </apex:panelGrid>
          </apex:panelGrid>
          
      <table class="headingTopLine">
      <tr>
      <th >  </th>
      </tr>
      </table>
      </div>
      <apex:outputPanel layout="block" styleClass="line"/>
      
          <table class="headingTopLine">      
         <tr>
         <th >  </th>
         </tr>
         <tr>
         <td>This Order Schedule is submitted pursuant to the Software as a Service Provider Agreement (the “Agreement”) an something else? 
         </td>
         </tr>
         <br></br>
         <tr>
         <td>Prices shown above do not include any taxes that may apply. 
         </td>
         <br></br>
         </tr>
         <tr>
         <td style="font-weight:bold" >IN WITNESS WHEREOF, the parties hereto have caused this Order Schedule and related Agreement to be executed by their duly authorized officers or representatives as of the Effective Date, by signature below.         </td>
         </tr>
         <br> </br>
         <br> </br>
    </table>
    <br> </br>
    <!-- Signatures -->
         <table style="padding:10px" width="100%"  >
         <tr >
         <th><apex:outputText value="{!Quote.Opportunity.Account.Name} " /></th> 
          
               
         <th><apex:outputText value="Kyriba Corporation " /></th> 
         <th></th>                
         </tr>
         <br> </br>
     
         <tr>
         <td >Authorized signature</td>
         <td style="border-bottom-style:solid; border-bottom-color:black;width:150px"></td>
         <td style="border-bottom-style:clear;width:40px"> </td>
         <td >Authorized signature</td>
         <td style="border-bottom-style:solid; border-bottom-color:black;width: 170px"></td>                   
         </tr>
         <br></br>
         <br></br>
         <tr>
         <td >Print Name and Title</td>
         <td style="border-bottom-style:solid; border-bottom-color:black;width:150px"></td>
         <td style="border-bottom-style:clear;width:40px"> </td>
         <td>Print Name and Title</td>
         <td style="border-bottom-style:solid; border-bottom-color:black;width: 170px"></td>                   
         </tr>
         <br></br>
         <br></br>
         <tr>
         <td >Signature date</td>
         <td style="border-bottom-style:clear;width:25px"></td>
         <td style="border-bottom-style:solid; border-bottom-color:black;width:150px"></td>
         <td style="border-bottom-style:clear;width:40px"> </td>
         <td>Signature date</td>         
         <td style="border-bottom-style:clear;width:28px"> </td>
         <td style="border-bottom-style:solid; border-bottom-color:black;width: 170px"></td>                   
         </tr>
         <br></br>
         <br></br>
         </table>
</body>
</html>      
  </apex:page>
For 2: What are the ways for implementing the 2nd requirement?
Vandana RattanVandana Rattan
Thanks Anoop. Can this be implemented using standard Quote object? Also can I send the Quote PDF and additional doc as attachment.
Anoop yadavAnoop yadav
Yeah,

You can use standard Quote object instead of Custom object.


Vandana RattanVandana Rattan
Thanks again. The problem while using standard quote object is that the data is not getting rendered on the PDF. For eg:-

I just tried <apex:outputText value="Quote# {!Quote.QuoteNumber}"/>

But the Quote# is printed blank. Am I missing anything here?
Anoop yadavAnoop yadav
Which profile you are using?
Do you have field level access to that fields?
Are you getting any other field value from Quote?
Vandana RattanVandana Rattan
I am working on my company's sandbox using Admin profile. However, I amunable to get any quote details in the page. I am in a fix... Do I need to override the controller? Can't I do with Standard controller?
Anoop yadavAnoop yadav
You should call the visualforce page with valid Quote Id.
You can override or create a new Button.
Use standardcontroller.
Vandana RattanVandana Rattan
Thanks again Anoop. Below is my generatePDF() that calls the Visualforce page. Am I missing anything here? This method gets called after quote and quote line items are inserted.
WebService static void generatePDF(List<Quote> qts){
        System.debug('Inside generate pdf');
        string TemplateId = '0EH90000000Gdtu';
        List<QuoteDocument> sr = new List<QuoteDocument>();
        for(Quote q:qts){
                     //for (Quote q: qts)
        {
                //PageReference pr = new PageReference('/quote/quoteTemplateDataViewer.apexp?id='+q.id); // link from answer by techtrekker
                PageReference pdfPage = Page.quotePDF;
             //System.debug('Page reference > ' + pr); 
                Blob pdfBlob = pdfPage.getContent();

                 sr.add (new QuoteDocument(
                 QuoteId = q.Id,
                 document = pdfBlob)); 
             System.debug('Quote Id Document > ' + q.Id);
         }
        insert sr;
        }