Hello friends, today we are going to discuss Generate PDF from Apex class in Salesforce. In this article, we will first generate a pdf in the apex class with the help of the Visualforce page and then send this pdf as an attachment in the email notification.
Many times we face this type of issue that we need to create a pdf order bill and send this to email, we do confuse that how can we get pdf in apex. Because we all know we can generate CSV files easily in apex.
Check out this for generating CSV: create or generate a csv file in Apex Salesforce
Highlights Points :
- Create a pdf by using Visalforce Page (renderas pdf)
- Call this Visalforce page from apex class to get pdf
- Insert this pdf to salesforce object record related list
- Send email with attachment
Step 1: In this step, we create a LWC Component with a button name “Generate PDF And Send Email”. So on clicking this button, we can send an email with an attachment. For records, I create a Picklist of contacts so we can select and send emails.
GeneratePdfAndSendEmail.Html :
<template>
<div class="slds-tabs_card">
<div class="slds-page-header">
<div class="slds-page-header__row">
<div class="slds-page-header__col-title">
<div class="slds-media">
<div class="slds-media__figure">
<span class="slds-icon_container slds-icon-standard-opportunity">
<lightning-icon icon-name="standard:recipe" alternative-text="recipe" title="recipe"></lightning-icon>
</span>
</div>
<div class="slds-media__body">
<div class="slds-page-header__name">
<div class="slds-page-header__name-title">
<h1>
<span>Generate PDF from Apex Salesforce</span>
<span class="slds-page-header__title slds-truncate" title="Recently Viewed">TechDicer</span>
</h1>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div> <br/>
<!-- Start Card for Combobox -->
<lightning-card variant="Narrow" title="Generate PDF from Apex Salesforce" icon-name="standard:account">
<div class="slds-p-horizontal_medium">
<lightning-combobox name="types"
label="Type"
value={value}
options={typeOptions}
onchange={handleTypeChange}>
</lightning-combobox>
<br/>
</div>
<div>
<lightning-button variant="brand" label="Generate PDF And Send Email"
title="Primary action"
onclick={generatePDF}
class="slds-m-left_x-small">
</lightning-button>
</div>
</lightning-card>
<!---------------------->
</template>
GeneratePdfAndSendEmail.JS :
import {LightningElement, track, wire} from 'lwc';
import fetchRecords from "@salesforce/apex/PDFGenerateCtrl.fetchRecords";
import sendPdf from "@salesforce/apex/PDFGenerateCtrl.sendPdf";
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export default class GeneratePdfAndSendEmail extends LightningElement {
@track l_All_Types;
@track typeOptions;
@track selectedOption;
@wire(fetchRecords, {})
wireData({error, data}) {
if (data) {
try {
console.log(data);
this.l_All_Types = data;
let options = [];
for (var key in data) {
// Here key will have index of list of records starting from 0,1,2,....
options.push({label: data[key].Name, value: data[key].Id });
}
this.typeOptions = options;
} catch (error) {
console.error('check error here', error);
}
} else if (error) {
console.error('check error here', error);
}
}
handleTypeChange(event){
this.selectedOption = event.target.value;
}
generatePDF(){
sendPdf({contactId : this.selectedOption})
.then(res=>{
this.ShowToast('Success', res, 'success', 'dismissable');
})
.catch(error=>{
this.ShowToast('Error', 'Error in send email!!', 'error', 'dismissable');
})
}
ShowToast(title, message, variant, mode){
const evt = new ShowToastEvent({
title: title,
message:message,
variant: variant,
mode: mode
});
this.dispatchEvent(evt);
}
}
Step 2: In this step, we create an apex class where we write the logic (pdf.getContent()) for generate a pdf and send emails.
PDFGenerateCtrl.cls :
public class PDFGenerateCtrl {
public Contact con{get;set;}
public String currentRecordId{get;set;}
public PDFGenerateCtrl(){
currentRecordId = ApexPages.CurrentPage().getparameters().get('id');
if(currentRecordId != null && String.isNotBlank(currentRecordId)){
con = [SELECT Id, Name, Email FROM Contact WHERE Id =:currentRecordId];
}
}
@AuraEnabled(cacheable=true)
public static List<Contact> fetchRecords(){
try {
List<Contact> conList = new List<Contact>();
conList = [Select id, Name, Email from Contact];
return conList;
} catch (Exception e) {
System.debug('Exception: '+e.getMessage());
return null;
}
}
@AuraEnabled
public static String sendPdf(String contactId) {
PageReference pdf = new pagereference('/apex/ContactDataPDF?id='+contactId);
pdf.getParameters().put('id', contactId);
Blob body;
try {
// returns page as a PDF
body = pdf.getContent();
} catch (Exception e) {
body = Blob.valueOf('data');
}
//insert content version
ContentVersion CV = new ContentVersion();
CV.Title = 'TechdicerContact.pdf';
CV.PathOnClient = 'TechdicerContact.pdf';
CV.VersionData = body;
CV.FirstPublishLocationId = contactId;
insert CV;
Messaging.EmailFileAttachment attach = new Messaging.EmailFileAttachment();
attach.setContentType('application/pdf');
attach.setFileName('TechdicerContact.pdf');
attach.Body = body;
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(new String[] {'rijwanmohmmed@gmail.com'});
mail.setSubject('Generate PDF from Apex Salesforce');
mail.setHtmlBody('Generate PDF from Apex Salesforce');
mail.setFileAttachments(new Messaging.EmailFileAttachment[] {attach});
// Send the email
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
return 'Email sent Successfully with PDF.';
}
}
Step 3: In this step, we create a Visualforce page that is reneder-as pdf and put some info in this.
ContactDataPDF.vfp:
<apex:page Controller="PDFGenerateCtrl" renderAs="pdf">
<h1>Contact Data</h1>
<p><b>Name :</b> {!con.Name}</p>
<p><b>Email :</b> {!con.Email}</p>
</apex:page>
Output :
4 comments
Everyone shows how to do this, no one shows a passing test class lol.
it’s really simple.
Is this code really works??
Yes