+ Start a Discussion
KasriftKasrift 

Apex trigger to update field picklist from another picklist

Hello,

 

I'm not a developer and really new to this.  I had a question and was wondering if someone had a solution or could point me in the right direction.  I have a picklist field on the Case object, that when a value is selected, I would like it to update another picklist field with a value.  The picklist values for the two custom fields are not related by name, but there are equal amounts of picklist values (i.e. field_1 has 32 picklist options & code_1 has 32 options).  I don't want to do a workflow for field updates since I would have to do all 32 options, plus the field needs to be cloned to be 5 similar fields.  This would require too many workflows.  Also, the field_1 picklist options are REALLY long sentences, which I want to update a corresponding field code_1 with the 4 digit code of the field_1 option.  I tried writing a formula field, but ran out of characters before I could list all of the picklist options (other than that, it worked fine).

 

Ideally, I would like to use Apex to make this work.  I have a basic code, but I'd rather not hard code the picklist values in in case they change.  This is what my basic structure looks like:

 

trigger FieldUpdate on Case (before insert, before update, after insert, after update){
// Loop through the incoming records
for (Case c : Trigger.new){
if(c.field_1__c == 'blah blah blah, really long sentence'
&& c.code_1__c == null){c.code_1__c = 'COD1';
}else if (c.AEM_Violation_1__c == 'Equally long descriptive sentence...”'
&& c.AEM__c == null){c.AEM__c = 'COD2';
}else if ....
}
}
}

 

Basically, hard coding the field to update will require me to list all 32 reasons, and then make triggers for each of the 4 other fields that have the same values.  Is there any way to do this in a more efficient manner that doesn't require me to hard code each of the picklist values?

Best Answer chosen by Admin (Salesforce Developers) 
Tim BarsottiTim Barsotti

1) I am not sure about 1 part of your code. The check for Code__c == null. If someone were to update the picklist values, wouldn't you want the code to be updated as well? I removed this from the code below. If you need it add it back. 

 

2) You do not want this to run AFTER update or AFTER insert.  Only before will suffice since you are editing the same record that is being updated.

 

You could use some of the getDescribe features of the case picklist's values and loop through them if your code needs to be numeric based off the picklist order. E.G. first value = COD1, second value = COD2 and so on... 

 

 

trigger FieldUpdate on Case (before insert, before update){
    List <Schema.PicklistEntry> pickListValues = Case.field_1__c.getDescribe().getPicklistValues();     for(Case c: trigger.new) {
    int i = 0;
        for(Schema.PicklistEntry pi: pickListValues){          i++;
            if(field_1__c = pi.getValue()){
                code__c = 'COD' + i;
     }
        }
    }
}

 

If the Code values will be different, you could build a map and reference the map's values. I like this strategy better, because if someone (an admin) re-orders the picklist values, you will not have to worry.

 

trigger FieldUpdate on Case (before insert, before update){
    Map<String, String> myPickListMap = new
Map<String, String> {'blah blah blah, really long sentence'=>'COD1', 'Equally long descriptive sentence...'=> 'COD2', ... };

    for (Case c : Trigger.new){
    if(c.field_1__c != null) {
    c.code__c = myPickListMap.get(c.field_1__c);
     }
    }
}

 

 

Hope this helps! 

All Answers

Tim BarsottiTim Barsotti

1) I am not sure about 1 part of your code. The check for Code__c == null. If someone were to update the picklist values, wouldn't you want the code to be updated as well? I removed this from the code below. If you need it add it back. 

 

2) You do not want this to run AFTER update or AFTER insert.  Only before will suffice since you are editing the same record that is being updated.

 

You could use some of the getDescribe features of the case picklist's values and loop through them if your code needs to be numeric based off the picklist order. E.G. first value = COD1, second value = COD2 and so on... 

 

 

trigger FieldUpdate on Case (before insert, before update){
    List <Schema.PicklistEntry> pickListValues = Case.field_1__c.getDescribe().getPicklistValues();     for(Case c: trigger.new) {
    int i = 0;
        for(Schema.PicklistEntry pi: pickListValues){          i++;
            if(field_1__c = pi.getValue()){
                code__c = 'COD' + i;
     }
        }
    }
}

 

If the Code values will be different, you could build a map and reference the map's values. I like this strategy better, because if someone (an admin) re-orders the picklist values, you will not have to worry.

 

trigger FieldUpdate on Case (before insert, before update){
    Map<String, String> myPickListMap = new
Map<String, String> {'blah blah blah, really long sentence'=>'COD1', 'Equally long descriptive sentence...'=> 'COD2', ... };

    for (Case c : Trigger.new){
    if(c.field_1__c != null) {
    c.code__c = myPickListMap.get(c.field_1__c);
     }
    }
}

 

 

Hope this helps! 

This was selected as the best answer
KasriftKasrift

Hey Tim,  thanks for the reply.  This looks like it will work out.  The reason I had the null value included in the original Apex was because I was using this from a email to case code that I have built out.  The email template our company is using has picklists built into the template so that the wording for the really long picklist values is EXACT.  This will update the long picklist value (which isn't included on the case layout), which in turn will update the other picklist with the appropriate code.  The reason we want to use a short code is for pulling down the data for SAS, long picklist values make the data too hard to work with.  So the second picklist with a code is being updated if it blank.  If the SF user needs to change the code picklist field on the case, they can do so without being affected by the original picklist value & in case there is an odd one off where an email template is sent in to an existing case with the reference number/case number, I don't want it to update the existing code values (this isn't a scenario that should occur, but just wanted to plan for user error).

 

Anyways, thank you very much for your solution.  I am going to build out the code based on you second solution since the picklist values may be re-ordered or expanded upon and since the codes in the second picklist don't always start with "COD".

KasriftKasrift

So I have two follow up questions to the original question that I posted.  I updated the trigger and it works great, the one exception is that I found Apex code does not like "smart quotes".  For example, if I had

 

trigger fieldupdate on Case (before insert, before update){

Map<String, String>myPickListMap = new Map<String,String>{

'....blah blah blah customer's blah blah blah'=>'COD1', 'etc etc etc'=>'COD2'......

for (Case c : Trigger.new)}

if (c.field__c != null){

c.codefield = myPickListMap.get(c.field__c);

}

}

}

 

The apostrope after customer is a smart quote, and it is copied over to the field as a picklist value with a smart quote style (an angled ‘ instead of a straight one ' ).  However, when I string this out from the email body with an Apex inbound email handler, it will always insert the value with a straight apostrophe, thus not updating the field to the right value, and not triggering the field update to change to the appropriate code.  The other values work fine, even straight quotes will update properly, but I can't get apostrophes to load in correctly from an inbound email Apex class.  The Apex class just strings the emailBody and parses out the data correctly, and the fields update from the string properly, I just can't get these specific fields to work right.

 

 

The follow up question is, is it possible to just update the fields after the case is created by the standard Email to Case On Demand functionality?  I have already built out an Apex inbound email handler class, but it occurred to me afterward that it might be easier to just use On Demand Email to Case and use a field update to string the values from the Case Description field (this is where the email body gets pasted to).  As mentioned in the first post, I am just learning to code, so most of this is new to me, but from what I understand, this would be an after insert trigger.  Would the trigger be made one the emailmessage object, or just the case object from the Description field?  And will I run into any issues with the lines from the email that I am trying to get a string from if I use the Description field instead?  For example, I have users submitting an email to case using a template, that when they select a long description from a picklist it will sometimes take up two lines in the email.  Currently, the Apex inbound email handler doesn't seem to mind if the lines are different.  Currently the string code looks like this:

 

String[] emailBody = email.plainTextBody.split('\n', 0);
String test = emailBody[0].substring(17);
String State = emailBody[2].substring(25);
String field1 = emailBody[4].substring(17);
String field2 = emailBody[6].substring(18);
String field3 = emailBody[8].substring(16);

 

The email body lines skip a line because when it is received by Salesforce it addes lines inbetween each line from the email template (not sure why it does this).  Anyways, it seems to me that this will make it difficult to parse data for a field update trigger.  Any assistance or guidance in the right direction for an "after insert" trigger to update fields based on the email body would be appreciated (I'm not using workflows because a workflow rule for a field update for each state, and each value would take too many workflows, and 5 of the fields are named the same except with a number, and have the same picklist values).