You need to sign in to do that
Don't have an account?

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
//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>
All Answers
Should be fixed:
http://community.salesforce.com/sforce/board/message?board.id=Visualforce&message.id=9687#M9687
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?
Post your code.
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>
//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>
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.
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"/>