Search code examples
apexvisualforcesalesforce-lightning

How can I get a Visualforce page to save into files on the opportunity page using an extension controller?


I am new to Salesforce and this is the first time I've ever had to open the developer console, so bear with me, the code may be rough and I appreciate any help. I have a controller and visualforce page that work to compile products from the products list on the opportunity page, create a new (non-repeating) quote number, and compile all this on to a PDF with the company logo and in the desired format; this is all called from the click of a button on the opportunity page. I want a button on the visualforce page to then, after the PDF is made and shown, save the PDF into files.

Visualforce page works as desired in creating my PDF

<apex:page controller="QuoteOppProductCtrl" extensions="QuotePDFSaveExt" applyHtmlTag="false" showHeader="false" renderAs="PDF" action="{!generateAndStoreQuoteNumber}">  
----------------the body of the content of the PDF is here ------------
</apex:page>

Main custom controller works as desired

public with sharing class QuoteOppProductCtrl {
    public Date Today { get { return Date.today(); } }
    public Opportunity opportunity { get; set; }
    public String shipToAccountName { get; set; }
    public String prosthetistName { get; set; }
    public String fittingProsthetistId { get; set; }
    public String prosthetistEmail { get; set; }
    public Decimal subtotal { get; set; }
    public Decimal quoteTotal { get; set; }
    public String quoteNumber { get; set; } // To store the generated quote number
--------- body of controller ---------   

Controller Extension: UPDATED Error is stating that there is a null reference for QuotePDFSaveExt(ApexPages.StandardController ctrl)

public with sharing class QuotePDFSaveExt{
    String oppId{get;set;}
    public QuotePDFSaveExt(ApexPages.StandardController ctrl) {
        oppId = ctrl.getId();
    }
        
    public PageReference savePDF() {
      // Generate the PDF here
       PageReference pdfPage = Page.QuoteOppProductVfp;
      // recordId = opp.Id;
       pdfPage.getParameters().put('Id', oppId);
       pdfPage.setRedirect(true);
        
       PageReference ret;

        try {
      Blob pdfBlob = Test.isRunningTest()
        ? Blob.valueOf('Test PDF Content')
        : pdfPage.getContentAsPDF();

      ContentVersion cv = new ContentVersion(
        Title = 'Quote ' + oppId,
        PathOnClient = 'Quote ' + oppId + '.pdf',
        VersionData = pdfBlob,
        FirstPublishLocationId = oppId
      );
      insert cv;
      ret = new ApexPages.StandardController([SELECT Id FROM ContentDocument WHERE LatestPublishedVersionId = :cv.Id]).view();
        } 
        catch (exception e) {
      ApexPages.addMessages(e);
        }
    return ret;

    }
}

Added VFP to save PDF

<apex:page standardController="Opportunity" extensions="QuotePDFSaveExt">
    <apex:pageMessages />
    <apex:form >
        <apex:pageBlock title="preview and save">
            <apex:pageBlockButtons >
                <apex:commandButton value="Save" action="{!savePDF}" />
            </apex:pageBlockButtons>
            <apex:iframe src="{!URLFOR($Page.QuoteOppProductVfp, null, [id=Opportunity.Id])}" scrolling="true" />
        </apex:pageBlock>
    </apex:form>
</apex:page>

Solution

  • As the VFP and the controller worked in creating the PDF I needed as an output, these remained unchanged from my question. I took the advice of creating a separate controller to create a "save pdf" method, and a separate Visualforce page to have a "Save" button. The button from the opportunity page calls the new Visualforce page.

    The additional controller

    public class QuotePDFSaveExt {
    public ID oppId { get; set; }
    public Opportunity opportunity {get;set;}
    
    public QuotePDFSaveExt() {
        oppId = ApexPages.currentPage().getParameters().get('id');
        System.debug('opportunity Id: ' + oppId);
        opportunity = [SELECT Id, Name
                      FROM Opportunity
                      WHERE Id = :oppId];
    }
    
    public PageReference savePDF() {
        PageReference pdfPage = Page.QuoteOppProductVfp;
        pdfPage.getParameters().put('Id', oppId);
        pdfPage.setRedirect(true);
        PageReference ret = null;
    
        try {
            Blob pdfBlob = Test.isRunningTest()
                    ? Blob.valueOf('Test PDF Content')
                    : pdfPage.getContentAsPDF();
    
            ContentVersion cv = new ContentVersion(
                    Title = 'Quote ' + oppId,
                    PathOnClient = 'Quote ' + oppId + '.pdf',
                    VersionData = pdfBlob,
                    FirstPublishLocationId = oppId
            );
            insert cv;
            System.debug('ContentVersion inserted: ' + cv);
            
            ret = new ApexPages.StandardController([SELECT Id FROM ContentDocument WHERE LatestPublishedVersionId = :cv.Id]).view();
        } catch (Exception e) {
            ApexPages.addMessages(e);
            System.debug('An exception occurred: ' + e.getMessage());
        }
        System.debug('Returning PageReference: ' + ret);
        return ret;
        }
    }
    

    The additional Visualforce page

    <apex:page controller="QuotePDFSaveExt" >
    <apex:pageMessages />
    <apex:form >
        <apex:pageBlock title="preview and save">
            <apex:pageBlockButtons >
                <apex:commandButton value="Save" action="{!savePDF}"/>
            </apex:pageBlockButtons>
            <apex:include pageName="QuoteOppProductVfp">
            </apex:include>
        </apex:pageBlock>
    </apex:form>
    </apex:page>