Home » All Blogs » Merge and Download Pdf from Salesforce

Merge and Download Pdf from Salesforce

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.

Nishchal vashisht
Nishchal vashisht

Nishchal vashisht
3x certified, Developer at cloud certitude

Articles: 4

One comment

  1. 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?

Leave a Reply