You can create a method in Apex which will return the data required in your document template. To use that type of data source, an Admin should create a class with TemplateApexDataProvider interface implementation. Interface includes two methods:

  • getAvailableTokensWithLabels – method defines Aveneer Token names and labels that are to be displayed as picklist values under the Configuration section of a Template Configuration record when Method mapping is selected.
  • getDataSource(TemplateApexDataProviderContext context) – method retrieves data from the database and assigns them to appropriate Aveneer Tokens.

After the correct class is created, it is available for selection when the “Method” data source is selected on the Template Configuration record page under the Configuration section.

Sample code can be found below. Remember to change the variables to ones that will suit your needs. To implement the code go to Setup -> Custom Code -> Apex Classes and create a new Apex Class.

global class SampleDataProvider implements ave.TemplateApexDataProvider {

     global Map<String, ave.ApexDataProviderTokenLabelInfo> getAvailableTokensWithLabels() {
         Map<String, ave.ApexDataProviderTokenLabelInfo> example = new Map<String, ave.ApexDataProviderTokenLabelInfo>();

        // standard tokens, string which we put in key should match key in getDataSource method
        example.put('phone', new ave.ApexDataProviderTokenLabelInfo('Phone'));
        example.put('fax', new ave.ApexDataProviderTokenLabelInfo('Fax'));
        example.put('name', new ave.ApexDataProviderTokenLabelInfo('Name'));

        // table token, mostly used in case, when we need to display some child records for example some data from Contacts related to Account
        ave.ApexDataProviderTokenLabelInfo table = new ave.ApexDataProviderTokenLabelInfo('Account Contacts');
        table.addChild('first_name', 'First Name');
        table.addChild('last_name', 'Last Name');
        table.addChild('phone', 'Phone');
        example.put('contacts', table);

        return example;
    }

    // ave.TemplateApexDataProviderContext context - generation context with two useful methods:
    // - List<String> getRecordIds() - return list of recordIDs to generate
    global ave.DataSourceWrapper getDataSource(ave.TemplateApexDataProviderContext context){
        ave.DataSourceWrapper dataSource = new ave.DataSourceWrapper();

        for(String recordId : context.getRecordIds()){
            dataSource.addForRecord(recordId)
                    .addValue('phone', '123123')
                    .addValue('fax', '321321')
                    .addValue('name', 'Test Account');
            for(Integer i = 1; i <= 3; i++) {
                dataSource.addForRecord(recordId)
                        .addTableRecord('contacts',
                            new ave.DataSourceRecordWrapper()
                            .addValue('first_name', 'First Name ' + i)
                            .addValue('last_name', 'Last Name ' + i)
                            .addValue('phone', String.valueOf(i))
                );
            }
        }
       return dataSource;
    }
}

Example – formatting dates with full month name to different languages

Salesforce every time returns full and short month name from MMMM and MMM date time format in English language. To adjust returned formatted date, we need to localize it manually. For this case we can use data provider, which will replace english month name to any other language. Below example is for German language, Account object and CreatedDate field, but can be easily adjusted to any language, object and field.

global with sharing class AveneerDateFormatProvider implements ave.TemplateApexDataProvider {

    Map<String, String> MONTH_TO_FULL_NAME_EN_MAP = new Map<String, String> {
            '01' => 'January',
            '02' => 'February',
            '03' => 'March',
            '04' => 'April',
            '05' => 'May',
            '06' => 'June',
            '07' => 'July',
            '08' => 'August',
            '09' => 'September',
            '10' => 'October',
            '11' => 'November',
            '12' => 'December'
    };

    Map<String, String> MONTH_TO_FULL_NAME_DE_MAP = new Map<String, String> {
            '01' => 'Januar',
            '02' => 'Februar',
            '03' => 'März',
            '04' => 'April',
            '05' => 'Mai',
            '06' => 'Juni',
            '07' => 'Juli',
            '08' => 'August',
            '09' => 'September',
            '10' => 'Oktober',
            '11' => 'November',
            '12' => 'Dezember'
    };

    Map<String, String> MONTH_TO_SHORT_NAME_EN_MAP = new Map<String, String> {
            '01' => 'Jan',
            '02' => 'Feb',
            '03' => 'Mar',
            '04' => 'Apr',
            '05' => 'May',
            '06' => 'Jun',
            '07' => 'Jul',
            '08' => 'Aug',
            '09' => 'Sep',
            '10' => 'Oct',
            '11' => 'Nov',
            '12' => 'Dec'
    };

    Map<String, String> MONTH_TO_SHORT_NAME_DE_MAP = new Map<String, String> {
            '01' => 'Jan',
            '02' => 'Feb',
            '03' => 'Mär',
            '04' => 'Apr',
            '05' => 'Mai',
            '06' => 'Jun',
            '07' => 'Jul',
            '08' => 'Aug',
            '09' => 'Sep',
            '10' => 'Okt',
            '11' => 'Nov',
            '12' => 'Dez'
    };

    global Map<String, ave.ApexDataProviderTokenLabelInfo> getAvailableTokensWithLabels() {
        Map<String, ave.ApexDataProviderTokenLabelInfo> labels = new Map<String, ave.ApexDataProviderTokenLabelInfo>();

        // labels for Today and CreatedDate with full month name
        labels.put('today_ddMMMMyyyy_de', new ave.ApexDataProviderTokenLabelInfo('Today dd MMMM yyyy (de)'));
        labels.put('createdDate_ddMMMMyyyy_de', new ave.ApexDataProviderTokenLabelInfo('CreatedDate dd MMMM yyyy (de)'));

        // labels for Today and CreatedDate with short month name (abbreviated)
        labels.put('today_ddMMMyyyy_de', new ave.ApexDataProviderTokenLabelInfo('Today dd MMM yyyy (de)'));
        labels.put('createdDate_ddMMMyyyy_de', new ave.ApexDataProviderTokenLabelInfo('CreatedDate dd MMM yyyy (de)'));

        return labels;
    }

    global ave.DataSourceWrapper getDataSource(ave.TemplateApexDataProviderContext context) {
        ave.DataSourceWrapper dataSource = new ave.DataSourceWrapper();
        List<String> recordIds = context.getRecordIds();

        // this example assume that recordId is from Account object, but it can be any object
        Map<Id, Account> accountsMap = new Map<Id, Account>([SELECT Id, CreatedDate FROM Account WHERE Id IN :recordIds]);

        for (String recordId : recordIds) {
            if (accountsMap.containsKey(recordId)) {
                Datetime createdDate = accountsMap.get(recordId).CreatedDate;

                dataSource.addForRecord(recordId)
                        // format today date to "dd MMMM yyyy" date format, and replace full month name from english to german based on map with full month names
                        .addValue('today_ddMMMMyyyy_de', DateTime.now().format('dd MMMM yyyy').replace(MONTH_TO_FULL_NAME_EN_MAP.get(DateTime.now().format('MM')), MONTH_TO_FULL_NAME_DE_MAP.get(DateTime.now().format('MM'))))
                        // format createdDate (it can be any date time field) to "dd MMMM yyyy" date format, and replace full month name from english to german based on map with full month names
                        .addValue('createdDate_ddMMMMyyyy_de', createdDate.format('dd MMMM yyyy').replace(MONTH_TO_FULL_NAME_EN_MAP.get(createdDate.format('MM')), MONTH_TO_FULL_NAME_DE_MAP.get(createdDate.format('MM'))))
                        // format today date to "dd MMM yyyy" date format, and replace short month name from english to german based on map with short month names
                        .addValue('today_ddMMMyyyy_de', DateTime.now().format('dd MMM yyyy').replace(MONTH_TO_SHORT_NAME_EN_MAP.get(DateTime.now().format('MM')), MONTH_TO_SHORT_NAME_DE_MAP.get(DateTime.now().format('MM'))))
                        // format createdDate (it can be any date time field) to "dd MMM yyyy" date format, and replace short month name from english to german based on map with short month names
                        .addValue('createdDate_ddMMMyyyy_de', createdDate.format('dd MMM yyyy').replace(MONTH_TO_SHORT_NAME_EN_MAP.get(createdDate.format('MM')), MONTH_TO_SHORT_NAME_DE_MAP.get(createdDate.format('MM'))));
            }
        }

        return dataSource;
    }
}