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
DManelskiDManelski 

Problem rendering a VF page as a PDF and attaching to a record

Hello,

 

I'm running into a problem rendering a VF page as a PDF and attaching it to an opportunity record and Single Email Message. The code executes correctly but I get 4 email messages and 4 PDF attachments, none of which actually open in a PDF reader.  I'll be glad to post my code but I wanted to find out if anyone else has run into this issue.

 

Dave 

Best Answer chosen by Admin (Salesforce Developers) 
TehNrdTehNrd
Try this:

//change opp to a property

public Opportunity opp {get; set;}

 

//Second page

<apex:page standardcontroller="Opportunity" extensions="ONEN_EXT_AcknowledgeGift" renderAs="PDF">

<apex:panelGrid columns="2" id="theGrid">
<apex:outputText value="Name: " styleClass="labelCol"/>
<apex:outputText value="{!opp.Name}" styleClass="dataCol" />
<apex:outputText value="Amount: " styleClass="labelCol" />
<apex:outputText value="{!opp.Amount}" styleClass="dataCol" />
<apex:outputText value="Stage: " styleClass="labelCol" />
<apex:outputText value="{!opp.StageName}" styleClass="dataCol" />
</apex:panelGrid>

</apex:page>

 

Message Edited by TehNrd on 02-09-2009 09:27 PM

All Answers

TehNrdTehNrd

Should be fixed:

 

http://community.salesforce.com/sforce/board/message?board.id=Visualforce&message.id=9687#M9687

DManelskiDManelski

Do you know if context is retained if I call another VF page for the PDF attachment from my original VF page?  I know this was a problem before and I don't want to start coding only to find out this isn't working yet.  

 

The alternative is to make the original VF page modal (conditional rendering) by passing parameters into the page from my method, correct?  

TehNrdTehNrd
Controller state between two pages when rendering a pdf is maintainted in Spring 09.
DManelskiDManelski
I couldn't seem to maintain controller state. My PDF, which is a separate VF page called from the first, displayed this text: SObject row was retrieved via SOQL without querying the requested field: Opportunity.Amount
TehNrdTehNrd

Post your code.

DManelskiDManelski

Controller:

 

 

public class ONEN_EXT_AcknowledgeGift {

Opportunity opp;

OpportunityContactRole[] conRoles;

Contact primaryContact; Id primaryId;

 

public Boolean taxDeductible { get {return taxDeductible;} set {taxDeductible = value;} }

 

public ONEN_EXT_AcknowledgeGift(ApexPages.StandardController controller) {

this.opp = (Opportunity)controller.getRecord();

opp = [select id, Name, Amount, StageName, Tax_Receipt_Id__c from Opportunity where id = :opp.id];

conRoles = [select ContactId From OpportunityContactRole WHERE Opportunity.Id = :opp.id AND IsPrimary = true limit 1];

if (conRoles.size()>0) {

primaryID = conRoles[0].ContactId;

}

primaryContact = [select FirstName, LastName, Primary_Street__c, Primary_City__c, Primary_State_Province__c, Primary_Postal_Code__c from Contact where Id = :primaryID];

if ( opp.Tax_Receipt_Id__c == null ) {

taxDeductible = false;

} else {

taxDeductible = true;

}

}

public List<SelectOption> getOptions() {

List<SelectOption> options = new List<SelectOption>();

options.add(new SelectOption('thanks_only','Send a thank you note only'));

if ( taxDeductible ) {

options.add(new SelectOption('thanks_plus_receipt','Send a thank you note with attached tax receipt'));

options.add(new SelectOption('receipt_only','Attach a PDF of the tax receipt to the opportunity (for download)'));

}

return options;

}

public String attachments { get {return attachments;} set {attachments = value;} }

 

public pageReference acknowledgeGift() {

//create the PDF and attach it to the Opp

PageReference pdf = Page.taxReceipt;

pdf.setRedirect(true);

Blob pdfContent = pdf.getContent();

 

if ( opportunity.Tax_Receipt_Id__c != null ) {

Attachment doc = new Attachment(

Body = pdfContent,

Name = primaryContact.FirstName + ' ' + primaryContact.LastName + ' Tax Receipt #:' + opp.Tax_Receipt_Id__c,

ContentType = 'application/pdf',

ParentId = opp.id

);

insert doc;

}

... 

 

 First VF Page:

 

<apex:page standardController="Opportunity" extensions="ONEN_EXT_AcknowledgeGift" >

<apex:sectionHeader title="Acknowledge Gift">

<description>

<apex:outputText value="Use this page to acknowledge a gift and issue a tax receipt via email or attach a PDF of the tax receipt to the opportunity record."/>

</description>

</apex:sectionHeader>

<apex:form >

<apex:pageBlock title="Choose format:" >

<apex:selectRadio value="{!attachments}" id="attachments" layout="pageDirection">

<apex:selectOptions value="{!options}"/>

</apex:selectRadio>

<apex:outputtext rendered="{!!taxDeductible}">

<p><strong>There is not an option to send a tax receipt for this opportunity because this opportunity is not listed as Tax Deductible. If this is incorrect, return to the <a href="/{!opportunity.id}">{!opportunity.name}</a> record and mark the Tax Deductible checkbox to assign a Tax Receipt Id.</strong></p>

</apex:outputtext>

<apex:pageBlockButtons >

<apex:commandButton action="{!acknowledgeGift}" value="Send/Process"/>

</apex:pageBlockButtons>

</apex:pageBlock>

</apex:form>

</apex:page>

 

Second VF Page, called from the first:

 

<apex:page standardcontroller="Opportunity" extensions="ONEN_EXT_AcknowledgeGift" renderAs="PDF">

<apex:panelGrid columns="2" id="theGrid">

<apex:outputText value="Name: " styleClass="labelCol"/>

<apex:outputText value="{!Opportunity.Name}" styleClass="dataCol" />

<apex:outputText value="Amount: " styleClass="labelCol" />

<apex:outputText value="{!Opportunity.Amount}" styleClass="dataCol" />

<apex:outputText value="Stage: " styleClass="labelCol" />

<apex:outputText value="{!Opportunity.StageName}" styleClass="dataCol" />

</apex:panelGrid>

</apex:page>

 

Message Edited by DManelski on 02-09-2009 12:27 PM
TehNrdTehNrd
Is there anyway you could format the code to make it a little more readable?
DManelskiDManelski
Yes, reformatted, cut ande paste from Eclipse to Chrome is apprently a problem.
TehNrdTehNrd
Try this:

//change opp to a property

public Opportunity opp {get; set;}

 

//Second page

<apex:page standardcontroller="Opportunity" extensions="ONEN_EXT_AcknowledgeGift" renderAs="PDF">

<apex:panelGrid columns="2" id="theGrid">
<apex:outputText value="Name: " styleClass="labelCol"/>
<apex:outputText value="{!opp.Name}" styleClass="dataCol" />
<apex:outputText value="Amount: " styleClass="labelCol" />
<apex:outputText value="{!opp.Amount}" styleClass="dataCol" />
<apex:outputText value="Stage: " styleClass="labelCol" />
<apex:outputText value="{!opp.StageName}" styleClass="dataCol" />
</apex:panelGrid>

</apex:page>

 

Message Edited by TehNrd on 02-09-2009 09:27 PM
This was selected as the best answer
DManelskiDManelski
That was ridiculously easier than I thought it would be, thanks so much.  I did have to make the variable public but it worked like a charm.
TehNrdTehNrd

Cool. I've updated the code to make the Opportunity public.

 

In case anyone reads this and needs more details. When using the standard controller the only fields that are queried are the fields that are on the layout. Since on the first page Opportunity Amount was never displayed, referring to it with the {!Opportunity.Amount} syntax was refering the the "standard" Opportunity object. Using {!opp.Amount} refers to the object that was populated with the query in the extension. Another solution would have been to have the Opportunity.Amount field on the first page but hide it with css, <apex: outputField value="{!Opportunity.Amount}" style="visibility:hidden"/>. The standard controller will still query this field even if it is not visible.

dchasmandchasman

FYI - You do not even need to actually send the value to the browser in order to allow the standard conroller to "see" your field reference and cause it to put it in the select list of the auto generated SOQL. Try this slightly cheaper approach:

 

 

<apex:outputText value="{!Opportunity.Amount}" rendered="false"/>