function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
bathybathy 

Save a custom object record as a PDF Document and attach to the same record

Hi Guys,

I am trying to develop a trigger(not sure if it is possible through Apex Triggers) to save a custom object record as a pdf document and then attach the same document to that record. we have a custom object called Research, what we want to achieve is when a certain date field is entered and saved then the data in that research record must be saved as a PDF document and get attached to the same record. 

I am not sure if this is achievable through triggers only. can anyone give any suggestions for how this can be achieved?

Thanks,
SlashApex (Luis Luciani)SlashApex (Luis Luciani)
Hi bathy!

Check this out. Seems like this would work for you. What you are trying to achieve is possible using triggers.

http://corycowgill.blogspot.com/2012/02/generating-pdf-in-apex-trigger.html

Good luck!
bathybathy
Hi Luis,
Thanks for your quick reply. I will try this out and let you know if I still have any issues.

Thanks,
bathybathy
Hi Luis,

I tried this solution. Its working very well. but this is grabbing all the fields on to the PDF File. Is there any way to just grab a few fields? I am new to coding can you please help me?
//Dynamically grab all the fields to store in the PDF
            Map<String, Schema.SObjectType> sobjectSchemaMap = Schema.getGlobalDescribe();
            Schema.DescribeSObjectResult objDescribe = sobjectSchemaMap.get('Administration_and_Compliance__c').getDescribe();
            Map<String, Schema.SObjectField> fieldMap = objDescribe.fields.getMap();
The above part of the class grabs all the fields from the record. Any way restrict just the required fields?

also can you please help me in writing test class for this class?

Thanks,
 
bathybathy
Hi Luis,

I was able to add only a few required fields to the PDF File by using a if statement. I am now looking to change the order of the fields on the PDF File and display 'Yes/No' instead of 'True/False' on the PDF File. I have opened another discussion for this requirement and I also shared my modified code. Can you please look into it suggest how can this be achieved?

Thanks,
Bathy.
SlashApex (Luis Luciani)SlashApex (Luis Luciani)
Hi bathy,

I did not find your new discussion. You can change the fields that you want to display and the order. Using the If statements is a bit limiting, since you are hardcoding the variables that you want to show. There are 2 routes to follow:
  1. The wrong way, but the easy one. If you are certain that you will not be changing the order of the fields in the future, or removing fields from the "Administration_and_Compliance__c" object in the future, do this:
public with sharing class AccountPDFGenerator
{
    
    public static final String FORM_HTML_START = '<HTML><BODY>';
    public static final String FORM_HTML_END = '</BODY></HTML>';

    //ENTER FIELDS HERE IN THE ORDER YOU WANT TO SHOW
    List<string> fieldsToInclude = new List<string> {

    	id,
    	Name,
    	Field1__c,
    	Field3__c,
    	Field2__c
    };

    public static void generateAccountPDF(Administration_and_Compliance__c adminCompliance)
    {
        String pdfContent = '' + FORM_HTML_START;
        try
        {
            pdfContent = '' + FORM_HTML_START;
            pdfContent = pdfContent + '<H2>Account Information in PDF</H2>';
            
            //Dynamically grab all the fields to store in the PDF
            Map<String, Schema.SObjectType> sobjectSchemaMap = Schema.getGlobalDescribe();
            Schema.DescribeSObjectResult objDescribe = sobjectSchemaMap.get('Administration_and_Compliance__c').getDescribe();
            Map<String, Schema.SObjectField> fieldMap = objDescribe.fields.getMap();
            
            //Append each Field to the PDF
            for(string field : fieldsToInclude)
            {
            	if(!fieldMap.containsKey(field))
            		continue;

            	Schema.SObjectField fieldDef = fieldMap.get(field);
                Schema.Describefieldresult fieldDescResult = fieldDef.getDescribe();
                String name = fieldDescResult.getName();
                string value = adminCompliance.get(name);
                
            	//TRANSLATE TRUE/FALSE TO YES/NO
                if(fieldDescResult.getType() == 'Boolean')
                	value = (value == 'true')?'Yes':'No';

                pdfContent = pdfContent + '<P>' + name + ': ' + adminCompliance.get(name) + '</P>';
            }
            pdfContent = pdfContent + FORM_HTML_END;
        }
        catch(Exception e)
        {
            pdfContent = '' + FORM_HTML_START;
            pdfContent = pdfContent + '<P>THERE WAS AN ERROR GENERATING PDF: ' + e.getMessage() + '</P>';
            pdfContent = pdfContent + FORM_HTML_END;
        }
        attachPDF(adminCompliance,pdfContent);
    }
    
    public static void attachPDF(Administration_and_Compliance__c adminCompliance, String pdfContent)
    {
        try
        {
            Attachment attachmentPDF = new Attachment();
            attachmentPDF.parentId = adminCompliance.Id;
            attachmentPDF.Name = adminCompliance.Name + '.pdf';
            attachmentPDF.body = Blob.toPDF(pdfContent); //This creates the PDF content
            insert attachmentPDF;
        }catch(Exception e)
        {
            adminCompliance.addError(e.getMessage());
        }
    }
    
}
2. The slightly harder way, but correct.
- Create a Custom Setting. Make it a List custom setting. Give it a name of "Account Admin and Compliance Settings". Add a text area field with 255 characters and name it "Fields to include". Create another text area field with 255 characters and name it "Fields to include 2". Then click manage and set a value for both. Add all the fields you want to display on the PDF in the order that you want them to display, separated by commas.
- Use this code:
 
public with sharing class AccountPDFGenerator
{
    
    public static final String FORM_HTML_START = '<HTML><BODY>';
    public static final String FORM_HTML_END = '</BODY></HTML>';

    //ENTER FIELDS HERE IN THE ORDER YOU WANT TO SHOW
    Administration_and_Compliance_Settings__c adminNComplSettings = Administration_and_Compliance_Settings__c.getOrgDefaults();

    public static void generateAccountPDF(Administration_and_Compliance__c adminCompliance)
    {
        String pdfContent = '' + FORM_HTML_START;
        try
        {
            pdfContent = '' + FORM_HTML_START;
            pdfContent = pdfContent + '<H2>Account Information in PDF</H2>';
            
            //Dynamically grab all the fields to store in the PDF
            Map<String, Schema.SObjectType> sobjectSchemaMap = Schema.getGlobalDescribe();
            Schema.DescribeSObjectResult objDescribe = sobjectSchemaMap.get('Administration_and_Compliance__c').getDescribe();
            Map<String, Schema.SObjectField> fieldMap = objDescribe.fields.getMap();
            
            List<string> fieldsToInclude = new List<string>();
            if(!String.IsBlank(adminNComplSettings.Fields_To_Include__c))
            	fieldsToInclude.addAll(adminNComplSettings.Fields_To_Include__c.split(','));

            if(!String.IsBlank(adminNComplSettings.Fields_To_Include_2__c))
            	fieldsToInclude.addAll(adminNComplSettings.Fields_To_Include_2__c.split(','));
            
            //Append each Field to the PDF
            for(string field : fieldsToInclude)
            {
            	if(!fieldMap.containsKey(field))
            		continue;

            	Schema.SObjectField fieldDef = fieldMap.get(field);
                Schema.Describefieldresult fieldDescResult = fieldDef.getDescribe();
                String name = fieldDescResult.getName();
                string value = adminCompliance.get(name);
                
            	//TRANSLATE TRUE/FALSE TO YES/NO
                if(fieldDescResult.getType() == 'Boolean')
                	value = (value == 'true')?'Yes':'No';

                pdfContent = pdfContent + '<P>' + name + ': ' + adminCompliance.get(name) + '</P>';
            }
            pdfContent = pdfContent + FORM_HTML_END;
        }
        catch(Exception e)
        {
            pdfContent = '' + FORM_HTML_START;
            pdfContent = pdfContent + '<P>THERE WAS AN ERROR GENERATING PDF: ' + e.getMessage() + '</P>';
            pdfContent = pdfContent + FORM_HTML_END;
        }
        attachPDF(adminCompliance,pdfContent);
    }
    
    public static void attachPDF(Administration_and_Compliance__c adminCompliance, String pdfContent)
    {
        try
        {
            Attachment attachmentPDF = new Attachment();
            attachmentPDF.parentId = adminCompliance.Id;
            attachmentPDF.Name = adminCompliance.Name + '.pdf';
            attachmentPDF.body = Blob.toPDF(pdfContent); //This creates the PDF content
            insert attachmentPDF;
        }catch(Exception e)
        {
            adminCompliance.addError(e.getMessage());
        }
    }
    
}

Please note that contrary to the original code. I have not tested any of these solutions, so there might be compiling errors that you must iron out.

Hope this helps! Good Luck!

Luis
 
gupta 100gupta 100
Hi Luis,

This solution really worked for me.Thanks a lot.But I have one concern.Can we format the pdf such that it displays sections and fields as we have in page layouts.

Any help is appreciated.

Savina
Mayank_SharmaMayank_Sharma

this class helps for a sinle insert or update.

how to do it for List of records.