Hello folks, In this blog I will show how you can Merge and Download Pdf from Salesforce into a single pdf file. You may encounter this issue when your client wants to download all of its attachments and files into a single pdf. You may find some Apps available on the Salesforce AppExchange but lets try it in our own way.
Key Requirements
- Must Know basics of admin and development in salesforce.
- Must know how to work over LWC in Salesforce. You can read more about LWC here.
- Must Know some third party integration process.
For fulfilling our requirement we are using a third-party library named PDF-LIB. You can use any other library if you want.
Merge and Download Pdf from Salesforce
1. Download PDF-LIB library from here and Upload the file in Static Resources of your org.
2. Get all file data in base64 format from Apex Controller. For Ex
@AuraEnabled
public static List<String> getData(String accountId){
System.debug('ID is '+accountId);
Map<String,String> mapOfData = new Map<String,String>();
List<ContentDocumentLink> lsOfCDL = [SELECT Id, LinkedEntityId, ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId=:accountId];
List<Id> tempsId =new List<Id>();
for(ContentDocumentLink tempLoop:lsOfCDL){
tempsId.add(tempLoop.ContentDocumentId);
}
List<ContentVersion> lsOfCV = [SELECT Id,VersionData,FileExtension FROM ContentVersion WHERE ContentDocumentId=:tempsId];
List<String> lsOfFiles = new List<String>();
for(ContentVersion tempLoopCv :lsOfCV){
lsOfFiles.add(EncodingUtil.base64Encode(tempLoopCv.VersionData));
System.debug('File Extension is '+tempLoopCv.FileExtension);
if((''+tempLoopCv.FileExtension).toLowerCase() == 'pdf'){
mapOfData.put(''+tempLoopCv.Id+','+'PDF',EncodingUtil.base64Encode(tempLoopCv.VersionData));
}else{
mapOfData.put(''+tempLoopCv.Id+','+'PDF',EncodingUtil.base64Encode(tempLoopCv.VersionData));
}
}
return lsOfFiles;
}
3. Now load your PDF-LIB into your lightning component environment by calling loadscript method and later calling your base64 file data from your Apex controller. For ex:
renderedCallback() {
loadScript(this, pdflib).then(() => {
});
console.log('recode ud ' + this.recordId)
if (this.recordId) {
getData({ accountId: this.recordId })
.then((result) => {
this.docData = JSON.parse(JSON.stringify(result));
console.log('Size of File are ' + this.docData.length)
this.error = undefined;
// this.createPdf()
})
.catch((error) => {
console.log('error while calling ' + error)
}
)
}
}
Inside the loadscript method pdflib denotes the name you have given to your static resource.
4. Define createPdf where actual work is done of merging .
async createPdf() {
const pdfDoc = await PDFLib.PDFDocument.create();
console.log('pdfDoc is ', pdfDoc)
if (this.docData.length < 1)
return
var tempBytes = Uint8Array.from(atob(this.docData[0]), (c) => c.charCodeAt(0));
console.log('tempBytes', tempBytes)
const [firstPage] = await pdfDoc.embedPdf(tempBytes);
const americanFlagDims = firstPage.scale(0.99);
var page = pdfDoc.addPage();
console.log('page is ', page)
page.drawPage(firstPage, {
...americanFlagDims,
x: page.getWidth() - americanFlagDims.width,
y: page.getHeight() - americanFlagDims.height - 10,
});
if (this.docData.length > 1) {
for (let i = 1; i < this.docData.length; i++) {
tempBytes = Uint8Array.from(atob(this.docData[i]), (c) => c.charCodeAt(0));
console.log('tempBtes>> ', tempBytes)
page = pdfDoc.addPage();
const usConstitutionPdf = await PDFLib.PDFDocument.load(tempBytes);
console.log('After ', usConstitutionPdf, usConstitutionPdf.getPages())
const preamble = await pdfDoc.embedPage(usConstitutionPdf.getPages()[0]);
console.log(' Inside page is ', page)
const preambleDims = preamble.scale(0.95);
page.drawPage(preamble, {
...preambleDims,
x: page.getWidth() - americanFlagDims.width,
y: page.getHeight() - americanFlagDims.height - 10,
});
}
}
const pdfBytes = await pdfDoc.save();
this.saveByteArray("My PDF", pdfBytes);
}
5. Create saveByteArray method to download your merge file.
saveByteArray(pdfName, byte) {
var blob = new Blob([byte], { type: "application/pdf" });
var link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
var fileName = pdfName;
link.download = fileName;
link.click();
}
You can get the full code from here.
Hi, I was trying to implement your code and came across an error such as – Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘create’).
Can you help me in understanding if I am making any mistake in the code?