+ Start a Discussion
Sammy7Sammy7 

Attach a visualforce custom quote page to quotePDFs

Hi, 
 I overrode the "Createpdf" button on quote page with a custom VF page (Quotecustom). I would like to create another button on quote page that lets me save that pdf as an attachment to the QuotePDF related list. 
What are the steps to do this? 
I know I need a controller that looks something like this: 
public class attachPDFToquote {
	
	private final quote q; //quote object
	
	//constructor
	public attachPDFToquote(ApexPages.StandardController standardPageController) {
		q = (Quote)standardPageController.getRecord(); //instantiate the quote object for the current record
	}
	
	//method called from the Visualforce's action attribute
	public PageReference attachPDF() {
		//generate and attach the PDF document
		PageReference pdfPage = Page.quotecustom; //create a page reference to quote custom Visualforce page
		Blob pdfBlob = pdfPage.getContent(); //get the output of the page, as displayed to a user in a browser
		Attachment attach = new Attachment(parentId = q.Id, Name = 'pdfAttachmentDemo.pdf', body = pdfBlob); //create the attachment object
		insert attach; //insert the attachment
		//redirect the user
		PageReference pageWhereWeWantToGo = new ApexPages.StandardController(q).view(); //we want to redirect the User back to the quote detail page
		pageWhereWeWantToGo.setRedirect(true); //indicate that the redirect should be performed on the client side
		return pageWhereWeWantToGo; //send the User on their way
	}

}
Im confused about the next step...do I have to create another seperate VF page or add the controller as an "extension" to my Quotecustom VF page. Please excuse my misunderstandings as Im new to this. 

THanks.
 
Best Answer chosen by Sammy7
GarryPGarryP
Step1: you will have to write a VF page that will generate the content for your page- example shown  below. Key think is to add Attribute renderAs="pdf"
<pre>
<apex:page standardController="Account" renderAs="pdf">
Content goes here
</apex:page>
</pre>
Now create another VF page that is the button . inside its controller you will have to access the page create above, something like this.
<pre>
PageReference pdf = Page.NAME_OF_YOUR_PAGE_THAT_HAVE_CONTENT;
// add parent id to the parameters for standardcontroller / or get it from the page URL on button click 
pdf.getParameters().put('id',parentId);
// create the new attachment , this hsould be inserted in realted list with the boy that is created inside try block 
Attachment attach = new Attachment();
// the contents of the attachment from the pdf
Blob body;
try {
// returns the output of the page created in step 1as a PDF
body = pdf.getContent();
} catch (VisualforceException e) {
body = Blob.valueOf('Anything in case of exception!');
}
</pre>
now you have the BODY for the attachment. Insert the attachment wherever required.

All Answers

GarryPGarryP
Step1: you will have to write a VF page that will generate the content for your page- example shown  below. Key think is to add Attribute renderAs="pdf"
<pre>
<apex:page standardController="Account" renderAs="pdf">
Content goes here
</apex:page>
</pre>
Now create another VF page that is the button . inside its controller you will have to access the page create above, something like this.
<pre>
PageReference pdf = Page.NAME_OF_YOUR_PAGE_THAT_HAVE_CONTENT;
// add parent id to the parameters for standardcontroller / or get it from the page URL on button click 
pdf.getParameters().put('id',parentId);
// create the new attachment , this hsould be inserted in realted list with the boy that is created inside try block 
Attachment attach = new Attachment();
// the contents of the attachment from the pdf
Blob body;
try {
// returns the output of the page created in step 1as a PDF
body = pdf.getContent();
} catch (VisualforceException e) {
body = Blob.valueOf('Anything in case of exception!');
}
</pre>
now you have the BODY for the attachment. Insert the attachment wherever required.
This was selected as the best answer
Sammy7Sammy7
Ok I think Im almost there: 
I get this error: SObject row was retrieved via SOQL without querying the requested field: Quote.Name
Error is in expression '{!attachPDF}' in component <apex:page> in page attachpdftoquote: Class.attachPDFtoQuote.attachPDF: line 25, column 1

 
public class attachPDFtoQuote {
private final Quote q; //quote object
    
   
	//constructor
	public attachPDFToQuote(ApexPages.StandardController stdController) {
		this.q = (Quote)stdController.getRecord(); //instantiate the quote object for the current record
        
	}
	
	//method called from the Visualforce's action attribute
	public PageReference attachPDF() {
		//generate and attach the PDF document
		PageReference pdfPage = Page.quotepage2; //create a page reference to our pdfDemo Visualforce page, which was created from the post http://www.interactiveties.com/blog/2015/render-visualforce-pdf.php

       pdfpage.getParameters().put('id',q.id); 
        Blob pdfBlob; //= pdfPage.getContent(); //get the output of the page, as displayed to a user in a browser
		
  if(!test.isRunningTest()){
    pdfblob = pdfPage.getContent();
 }else{
   pdfblob= blob.valueof('TEST');
 }
        
  Attachment attach = new Attachment(ParentId = q.Id, Name = 'Quote-'+q.name+'.pdf', body = pdfBlob); //create the attachment object
		insert attach; //insert the attachment
		//redirect the user
		PageReference pageWhereWeWantToGo = new ApexPages.StandardController(q).view(); //we want to redirect the User back to the Account detail page
		pageWhereWeWantToGo.setRedirect(true); //indicate that the redirect should be performed on the client side
		return pageWhereWeWantToGo; //send the User on their way
	}

}

How do I fix this ? 
Sammy7Sammy7
This is the line:  Attachment attach = new Attachment(ParentId = q.Id, Name = 'Quote-'+q.name+'.pdf', body = pdfBlob);

The problem is with "q.name" but I dont understand why....
Sammy7Sammy7
Ok figured out the workaround. https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/apex_ApexPages_StandardController_getRecord.htm

I added this on my VF page: <apex:outputText value="{!Quote.name}" rendered="false"/>