1

BACKGROUND

I have a VF page with one field on it:

Page 1

<apex:page standardController="Opportunity" showHeader="false" sidebar="false" renderAs="pdf" >
    <apex:outputText value="{!Opportunity.Quote_Header_Information__c}" escape="false"/>
<apex:page/>

The Quote_Header_Information__c is a custom formula field that returns text.

When I open the page in the preview mode it shows as expected and the field contains a proper value. It also shows up in an iframe in another VF page:

Page 2

<apex:page standardController="Opportunity" extensions="QuoteCreatePdfController" showHeader="false" sidebar="false">
   <apex:form >

    <apex:pageBlock >
        <apex:outputPanel >
            <apex:iframe src="{!quotePage}" height="550px"/>
        </apex:outputPanel>
    </apex:pageBlock>

    <center>
        <apex:pageBlock >
            <apex:commandLink value="Save to Attachments" action="{!saveToAttachments}" />&nbsp;

        </apex:pageBlock>
    </center>

  </apex:form>

Page 2 Contrloller "QuoteCreatePdfController"

public class QuoteCreatePdfController
{

    // Public declarations
    public final PageReference quotePage {get; set;}

    // Private declarations
    private final Opportunity opp;
    private final Id oppId;

    private static final Boolean DEBUG_ON = true;   
     // Constructor
    public QuoteCreatePdfController(ApexPages.StandardController controller)
    {
        // Get the sObject in controller
        this.oppId = (Id)controller.getId();
        this.opp = (Opportunity)controller.getRecord();

        // Assigng a page to display in the iframe
        this.quotePage = Page.CustomQuote;
        this.quotePage.getParameters().put('id', (String)this.oppId);
    }

    public void saveToAttachments()
    {
        // Retrieve all the attachments in the current sObject
        List<Attachment> attachments = [SELECT Id FROM Attachment WHERE ParentId = :this.oppId];
        if (DEBUG_ON) System.debug('>>> [saveAttachment] => [attachments]: ' + attachments);

        // Create a name for attachment
        Integer attNumber = attachments.size() + 1;
        String attName = this.opp.Name + '_Quote_' + String.valueOf(attNumber) + '_' + String.valueOf(Date.today()) + '.pdf';
        if (DEBUG_ON) System.debug('>>> [saveAttachment] => [attName]: ' + attName);

        // Get the content of the quote page as blob
        Blob content;
        if (Test.IsRunningTest())
        { 
            content = Blob.valueOf('UNIT.TEST'); 
        }   
        else
        { 
            try
            {
                if (DEBUG_ON) System.debug('>>> [saveAttachment] => [this.quotePage.getUrl()]: ' + this.quotePage.getUrl());
                content = this.quotePage.getContentAsPDF();
                //content = Blob.valueOf('UNIT.TEST');
            }
            catch (System.Exception e)
            {
                System.debug('An unexpected error has occurred: ' + e.getMessage());
                throw new AttacmentsException('An unexpected error has occurred while saving the attachment. Contact your administraton for more details.');
            }
        }

        // Create an attachment
        if (DEBUG_ON) System.debug('>>> [saveAttachment] Creating attachment...');
        Attachment att = new Attachment();
        att.Name = attName;
        att.Body = content;
        att.ParentId = this.oppId;
        // Save into the database
        try
        {
            insert att;
        } 
        catch (System.DmlException e)
        {
            System.debug('An unexpected error has occurred: ' + e.getMessage());
            throw new AttacmentsException('An unexpected error has occurred while saving the attachment. Contact your administraton for more details.');
        }
    }
}

PROBLEM

Everything works fine until I click the "Save to Attachments" button on Page 2. I am getting the following error:

SObject row was retrieved via SOQL without querying the requested field: Opportunity.Quote_Header_Information__c

The problem is in this line of code

content = this.quotePage.getContentAsPDF();

I found this doc link with a similar example and it works just fine. It's very annoying that Page 1 can be rendered as PDF, but it cannot provide its content with the getContentAsPDF() function if object's fields are provided by standard controller only.

QUESTION

Are there any ways to use only standard controller for Page 1? Or the only option I have is using a custom controller for Page 1 that will provide all that fields as instance members?

  • Try adding a rerender attribute to apex:commandLink – Raul Aug 18 '17 at 11:05
  • What do I need to provide in the reRender attribute? Id of the Opportunity object? – Eduard Aug 18 '17 at 11:23
  • Have an empty outputPanel and giving its id. And give the id of that element to command link. It will do a partial page refresh. I guess you would want to also display a success or failure message based on the save. – Raul Aug 18 '17 at 11:25
0

I ended up creating a custom controller for Page 1 and retrieving necessary fields via SOQL.

Page 1

<apex:page standardController="Opportunity" extensions="CustomController" showHeader="false" sidebar="false" renderAs="pdf" >
    <apex:outputText value="{!Opportunity.Quote_Header_Information__c}" escape="false"/>
<apex:page/>

CustomController

public class CustomController
{
    public Opportunity opp { get; set; }
    // Constructor
    public QuoteCustomController(ApexPages.StandardController controller)
    {
        // Get the sObject in controller
        Id oppId = (Id)controller.getId();
        this.opp = [SELECT Id, Quote_Header_Information__c,
                    FROM Opportunity 
                    WHERE Id = :oppId LIMIT 1];
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.