+ Start a Discussion
paddingtonpaddington 

Querying and setting multi-select picklist values

Note the code pasted in normal text format in blue for those who see garbled code.

 

Hi all,

 

The key problem here is how to take a multi-select picklist on two separate instances of an object related to the account and populate a multi-select picklist on the account with a merged set of their values. Sounds simple, but I'm stumped.

 

Here are the details:

 

An account is being assessed by two independent users via a related custom object called Assessment. In their assessments they give feedback via a multi-select picklist called Decline/Refer Feedback and then make a recommendation by choosing a value in a picklist called Recommendation.

 

When they save an assessment record and Recommendation has switched from null to not null, an after update trigger on the assessment calls a decision method with a list of the affected accounts. This method creates nested maps of account to assessment to recommendation and account to assessment to decline/refer feedback:

 

        //Create nested map of account ID to map of IEF assessment IDs to recommendations
        Map<ID,Map<ID,String>> recMap = new Map<ID,Map<ID,String>> ();
        Map<ID,String> recNestMap = new Map<ID,String> ();
       
        //Create nested map of account ID to map of IEF assessment IDs to decline/refer feedback
        Map<ID,Map<ID,String>> feedMap = new Map<ID,Map<ID,String>> ();
        Map<ID,String> feedNestMap = new Map<ID,String> ();

 

After populating these maps, I iterate through the accounts and count the instances of a certain recommendation occurring, which allows me to decide on the appropriate action. This is relatively easy as we're dealing with a picklist with four values: Decline, Refer to Level 1, Refer to Level 2 and Approve:

 

//Iterate through accounts
        for(Account a:accs){
                      
            //Declare counting variables
            Integer approvecount=0;
            Integer declinecount=0;
            Integer refertwocount=0;
            Integer earlycount=0;
            Integer grantcount=0;

            //Count approvals, declinations and referrals for each account
            for(ID rec :recMap.get(a.Id).keySet()){
                if(recMap.get(a.Id).get(rec) == 'Approve'){
                    approvecount++;
                }
                if(recMap.get(a.Id).get(rec) == 'Decline'){
                    declinecount++;
                }
                if(recMap.get(a.Id).get(rec) == 'Refer to Level 2'){
                    refertwocount++;
                }
            }               

            //Decide on appropriate action
            if(approvecount>=2){
                a.SAQ_Sub_stage__c='SAQ to be sent';
                a.Initial_Enquiry_Sub_stage__c='Assessment complete (No conflict)';
                a.Advantage_Stage__c='SAQ';             
            }
            else if(approvecount==1){  
                a.SAQ_Sub_stage__c='SAQ to be sent';
                a.Initial_Enquiry_Sub_stage__c='Assessment complete (Conflict)';
                a.Advantage_Stage__c='SAQ';             
            }
            else if(declinecount>=2){  
                a.Initial_Enquiry_Sub_stage__c='Assessment complete (No conflict)';             
                a.Advantage_Status__c='To be declined';
            }
            else if(refertwocount>=2){  
                a.Initial_Enquiry_Sub_stage__c='Assessment complete (No conflict)';             
                a.Advantage_Status__c='To be referred to Level 2';
            }
            else if(refertwocount==1){  
                a.Initial_Enquiry_Sub_stage__c='Assessment complete (Conflict)';             
                a.Advantage_Status__c='To be referred to Level 2';
            }
            else if(declinecount==1){ 
                a.Initial_Enquiry_Sub_stage__c='Assessment complete (Conflict)';            
                a.Advantage_Status__c='To be referred to Level 1';
            }
            else{          
                a.Initial_Enquiry_Sub_stage__c='Assessment complete (No conflict)';             
                a.Advantage_Status__c='To be referred to Level 1';
            }

 

 The problem comes with the multi-picklists, as combinations increase exponentially with increase in the number of values. I started with two feedback values: Too early and Requests grant. With only two values it's quite easy to count the occurrence of each value across the assessment objects:

 

//Count feedback given
            for(ID feed :feedMap.get(a.Id).keySet()){
                if(feedMap.get(a.Id).get(feed) == 'Too Early'){
                    earlycount++;
                }
                if(feedMap.get(a.Id).get(feed) == 'Requests Grant'){               
                    grantcount++;
                }
                if(feedMap.get(a.Id).get(feed) == 'Too Early;Requests Grant'
                  || feedMap.get(a.Id).get(feed) == 'Requests Grant;Too Early'){                               
                    earlycount++;
                    grantcount++;
                }
            }
           
            //Decide on appropriate action based on feedback counts
            if(earlycount>0 && grantcount>0){
                a.Assessment_Feedback__c='It is too early stage;You require grant finance';
            }
            else if(earlycount>0){
                a.Assessment_Feedback__c='It is too early stage';
            }
            else if(grantcount>0){
                a.Assessment_Feedback__c='You require grant finance';
            }
            else{
                a.Assessment_Feedback__c=null;
            }
        }

 

 The problem comes when the users want to have six values in the feedback multi-select picklist. Counting occurrences of a value now becomes a bit of a nightmare. I've tried using the contains String method, but when I try it with the case of only two multi-select options, it fails my test class.

 

  //Count feedback given
            for(ID feed :feedMap.get(a.Id).keySet()){               
                if(feedMap.get(a.Id).get(feed).contains('Too Early')){
                    earlycount++;
                }
                if(feedMap.get(a.Id).get(feed).contains('Requests Grant')){               
                    grantcount++;
                }               
            }
           
            //Decide on appropriate action based on feedback counts
            if(earlycount>0 && grantcount>0){
                a.Assessment_Feedback__c='It is too early stage;You require grant finance';
            }
            else if(earlycount>0){
                a.Assessment_Feedback__c='It is too early stage';
            }
            else if(grantcount>0){
                a.Assessment_Feedback__c='You require grant finance';
            }
            else{
                a.Assessment_Feedback__c=null;
            }

 

 The error is "Attempt to de-reference a null object" and is pinned to this line at "get(feed)":

 

if(feedMap.get(a.Id).get(feed).contains('Too Early'))

 

Now this is weird, as it passes my tests when I use:

 

 if(feedMap.get(a.Id).get(feed) == 'Too Early')

 

 

Looking in the string method documentation, it seems that 'contains' is an instance method, which might be what is screwing things up.

 

Regardless, there has to be a better way of querying multi-select picklists than looking for equivalency for 63 different combinations (6_C_6 + 6_C_5 + 6_C_4 + 6_C_3 + 6_C_2 + 6_C_1 = 63 [link]). The second problem is then how do I populate the multi-select picklist on the Account, based upon the occurrence of different multi-select values. At the moment, I'm writing a string to the account field, which is fine for two values, as there are only three combinations. With six, however, we're dealing with 63 different strings again. I can't find any documentation on selecting a multi-select value without overwriting what is in the field already, which is what I would do in an ideal world.

 

Any advice on how to deal with these two problems would be very gratefully received.

 

Thanks in advance,

 

Paddington

Message Edited by paddington on 11-20-2009 11:23 AM
Message Edited by paddington on 11-20-2009 11:24 AM
Cool_DevloperCool_Devloper

Hey Pads, 

Seems there is some issue with the threads.

The codes pasted are like completely unreadable! Are you able to see your code pasted here in a readable format?

Cool_D 

paddingtonpaddington
Code segments seem fine to me. I'm in FF on a Mac - wouldn't have thought it'd make a difference. What do you see? Have re-pasted without using code pasting tool.
Message Edited by paddington on 11-20-2009 11:25 AM