1

I'm implementing custom functionality of merge fields on visualforce page. For that I'm adding templates in select option, after selecting particular template I'm rendering text-area with actual data from that particular record.

Functionality is working fine if their are non-relational fields in template (e.g. {!Contact.Name} , {!Contact.Email} etc) but it fails if their are any relational fields (e.g. {!Case.Account.Name})

Method to get merge field data

public static Map<String,String> mergeText(String messageBody, Id recId){
    pattern p = Pattern.compile('\\{[!a-zA-Z0-9_\\s\\.]*\\}');
    String objectName = '';
    Matcher m = p.matcher(messageBody);
    String fieldName = '';
    Map<String,Set<String>> fieldMap = new Map<String,Set<String>>();
    Map<String,String> templateBodyMap = new Map<String,String>();
    if(recId != null){
        objectName = recId.getSObjectType().getDescribe().getName();
        fieldMap.put(objectName,new Set<String>{'Id'});
    }

    Set<String> fieldApiSet = new Set<String>();

    //find merge fieds and create map of objectApi and fieldApi for dynamic soql
    while(m.find()){
        fieldName = messageBody.substring(m.start()+2,m.end()-1);

        //Spliting Object API and field API
        String[] apiArry = fieldName.split('\\.');
        if(apiArry[0] == objectName){
            if(fieldMap.containsKey(apiArry[0])){
                fieldMap.get(apiArry[0]).add(apiArry[1]);
            }
            else{
                fieldMap.put(apiArry[0],new Set<String>{apiArry[1]});
            }  
        }else{
            System.debug('objectName>>'+objectName);
            System.debug('fieldName>>'+fieldName);
            System.debug('fieldMap>>'+fieldMap);
            fieldMap.get(objectName).add(fieldName);
        }
    }

    //iterate throught map and create soql query String
    List<String> fieldList = new List<String>();        

    for(Set<String> fields : fieldMap.values()){
        for(String f: fields){
            fieldList.add(f);
        }
    }

    String queryString = ' SELECT ' + String.join( fieldList, ',' )+' FROM '+ objectName +' WHERE Id =:recId';
    System.debug('query>>'+queryString);

    Database.QueryLocator q = Database.getQueryLocator(queryString);
    Database.QueryLocatorIterator it =  q.iterator();

    while (it.hasNext()) {
        SObject obj = (SObject )it.next();
        System.debug('obj>>'+obj);
        for(String field : fieldList){
            if(obj.get(field) != null && obj.get(field) != ''){
                messageBody = messageBody.replace('{!' + objectName + '.' + field + '}', String.valueOf(obj.get(field))).trim();
            }else{
                messageBody = messageBody.replace('{!' + objectName + '.' + field + '}','').trim();
            }

            if(obj.get('id') != null){
                templateBodyMap.put(String.valueOf(obj.get('id')),messageBody);
            }
        }
    }

    return templateBodyMap;
}

I'm getting following error if relational fields are included in template

enter image description here

If relational fields are not included in template data is populated in text-area as per standard functionality of salesforce

2 Answers 2

1

The line number of the error doesn't correlate to your code, but it looks like your issue is probably with

if(obj.get(field) != null && obj.get(field) != ''){

You're calling sObject.get() with a relationship field path, and that's not supported. You can illustrate that with an Anonymous Apex experiment:

Contact c = [SELECT Id, Account.Name FROM Contact WHERE AccountId != null LIMIT 1];

c.get('Account.Name');

Here you get the same error.

Unfortunately, it looks like to implement this requirement (merging relationship fields) you'd need to split the field name by '.' and then iteratively call obj.getSobject() on each intermediate path component before calling finalObj.get() on the last sObject result you obtain.

2
  • Thanks @David.. resolved issue by using getSobject() method. Is their any way to get data directly for standard objects like Company Information, cause Salesforce allows to use these fields while creating templates. can we get data for these standard object without SOQL? May 24, 2018 at 12:27
  • I'm less familiar with the suite of standard objects that are usable in templates, I'm afraid.
    – David Reed
    May 24, 2018 at 13:33
0

Can you please provide me your updated code in which you are getting the relational field.I am getting error when I am trying to merge the relational field

1
  • 1
    If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context. - From Review
    – Derek F
    Dec 15, 2021 at 11:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .