You need to sign in to do that
Don't have an account?

How to pull a Dependent Picklist Value Mapping in Apex
I was frustrated with the various answers I had found as to how to get a complete mapping of dependent picklist values, so I combined a few different posts into a solution that works, is efficient, and does not require a web service call. This only works for single level dependencies,
I created a class called Utilities that holds the method GetDependentOptions for getting dependent picklist values. There is also a method called GetPickListValues to retrieve values for a simple picklist. The method FirstControllingValueFor is used to do a reverse lookup given a child value to find the first controlling value that the child is valid for.
public class Utilities {
public static List<String> GetPickListValues(String object_name, String field_name, String first_val) {
SObjectType objectType = Schema.getGlobalDescribe().get(object_name);
List<String> options = new List<String>(); //new list for holding all of the picklist options
if (first_val != null) { //if there is a first value being provided
options.add(first_val); //add the first option
}
List<String> classes = new List<String>();
classes.add(object_name);
List<Schema.DescribeSObjectResult> results = Schema.describeSObjects(classes);
Schema.DescribeSObjectResult sobject_describe = results[0];
Map<String, Schema.SObjectField> field_map = sobject_describe.fields.getMap(); //get a map of fields for the passed sobject
if (null != field_map) {
Schema.SObjectField fs = field_map.get(field_name);
Schema.DescribeFieldResult dsr = fs.getDescribe();
if (null != dsr) {
List<Schema.PicklistEntry> pick_list_values = dsr.getPickListValues(); //grab the list of picklist values for the passed field on the sobject
if (null != pick_list_values) {
for (Schema.PicklistEntry a : pick_list_values) { //for all values in the picklist list
options.add(a.getValue());
}
}
}
}
return options; //return the List
}
private static Map<String, Integer> base64Vals = null;
private static List<Integer> ConvertB64ToInts(string b64Str) {
if (base64Vals == null) {
base64Vals = new Map<String, Integer> {
'A'=>00,'B'=>01,'C'=>02,'D'=>03,'E'=>04,'F'=>05,'G'=>06,'H'=>07,'I'=>08,'J'=>09,
'K'=>10,'L'=>11,'M'=>12,'N'=>13,'O'=>14,'P'=>15,'Q'=>16,'R'=>17,'S'=>18,'T'=>19,
'U'=>20,'V'=>21,'W'=>22,'X'=>23,'Y'=>24,'Z'=>25,'a'=>26,'b'=>27,'c'=>28,'d'=>29,
'e'=>30,'f'=>31,'g'=>32,'h'=>33,'i'=>34,'j'=>35,'k'=>36,'l'=>37,'m'=>38,'n'=>39,
'o'=>40,'p'=>41,'q'=>42,'r'=>43,'s'=>44,'t'=>45,'u'=>46,'v'=>47,'w'=>48,'x'=>49,
'y'=>50,'z'=>51,'0'=>52,'1'=>53,'2'=>54,'3'=>55,'4'=>56,'5'=>57,'6'=>58,'7'=>59,
'8'=>60,'9'=>61,'+'=>62,'/'=>63
};
}
List<Integer> ints = new List<Integer>();
for (Integer idx = 0; idx< b64Str.length(); ++idx) {
String c = String.fromCharArray(new List<Integer> { b64Str.charAt(idx)});
ints.add(base64Vals.get(c));
}
return ints;
}
private class TPicklistEntry{
public string active {get;set;}
public string defaultValue {get;set;}
public string label {get;set;}
public string value {get;set;}
public string validFor {get;set;}
public TPicklistEntry(){}
}
public static Map<String,List<String>> GetDependentOptions(String pObjName, String pControllingFieldName, String pDependentFieldName) {
Map<String,List<String>> mapResults = new Map<String,List<String>>();
//verify/get object schema
Schema.SObjectType pType = Schema.getGlobalDescribe().get(pObjName);
if ( pType == null ) return mapResults;
Map<String, Schema.SObjectField> objFieldMap = pType.getDescribe().fields.getMap();
//verify field names
if (!objFieldMap.containsKey(pControllingFieldName) || !objFieldMap.containsKey(pDependentFieldName)) return mapResults;
//get the control & dependent values
List<Schema.PicklistEntry> ctrl_ple = objFieldMap.get(pControllingFieldName).getDescribe().getPicklistValues();
List<Schema.PicklistEntry> dep_ple = objFieldMap.get(pDependentFieldName).getDescribe().getPicklistValues();
//initialize results mapping
for(Integer pControllingIndex=0; pControllingIndex < ctrl_ple.size(); pControllingIndex++) {
mapResults.put( ctrl_ple[pControllingIndex].getLabel(), new List<String>());
}
//serialize dep entries
List<TPicklistEntry> objDS_Entries = new List<TPicklistEntry>();
objDS_Entries = (List<TPicklistEntry>)JSON.deserialize(JSON.serialize(dep_ple), List<TPicklistEntry>.class);
for (TPicklistEntry objDepPLE : objDS_Entries){
List<Integer> bitValues = ConvertB64ToInts(objDepPLE.validFor);
Integer bitMask = 32; // Ignore highest 2 bits
Integer intIndex = 0;
Integer bitIdx = 0;
for (Integer numBits = bitValues.size() * 6; numBits > 0; --numBits) {
Integer bits = bitValues[intIndex];
if ((bits & bitMask) == bitMask) {
mapResults.get( ctrl_ple[bitIdx].getLabel() ).add( objDepPLE.label );
}
bitMask = bitMask >>> 1;
++bitIdx;
if (bitMask == 0) {
bitMask = 32;
intIndex = intIndex + 1;
}
}
}
return mapResults;
}//GetDependentOptions
public static String FirstControllingValueFor(String pObjName, String pControllingFieldName, String pDependentFieldName, String childValue) {
Map<String,List<String>> mappedItems = GetDependentOptions(pObjName, pControllingFieldName, pDependentFieldName);
for (String key : mappedItems.keySet()) {
List<String> items = mappedItems.get(key);
Set<String> itemSet = new Set<String>(items);
if (itemSet.contains(childValue)) {
return key;
}
}
return null;
}
}
I created a class called Utilities that holds the method GetDependentOptions for getting dependent picklist values. There is also a method called GetPickListValues to retrieve values for a simple picklist. The method FirstControllingValueFor is used to do a reverse lookup given a child value to find the first controlling value that the child is valid for.
public class Utilities {
public static List<String> GetPickListValues(String object_name, String field_name, String first_val) {
SObjectType objectType = Schema.getGlobalDescribe().get(object_name);
List<String> options = new List<String>(); //new list for holding all of the picklist options
if (first_val != null) { //if there is a first value being provided
options.add(first_val); //add the first option
}
List<String> classes = new List<String>();
classes.add(object_name);
List<Schema.DescribeSObjectResult> results = Schema.describeSObjects(classes);
Schema.DescribeSObjectResult sobject_describe = results[0];
Map<String, Schema.SObjectField> field_map = sobject_describe.fields.getMap(); //get a map of fields for the passed sobject
if (null != field_map) {
Schema.SObjectField fs = field_map.get(field_name);
Schema.DescribeFieldResult dsr = fs.getDescribe();
if (null != dsr) {
List<Schema.PicklistEntry> pick_list_values = dsr.getPickListValues(); //grab the list of picklist values for the passed field on the sobject
if (null != pick_list_values) {
for (Schema.PicklistEntry a : pick_list_values) { //for all values in the picklist list
options.add(a.getValue());
}
}
}
}
return options; //return the List
}
private static Map<String, Integer> base64Vals = null;
private static List<Integer> ConvertB64ToInts(string b64Str) {
if (base64Vals == null) {
base64Vals = new Map<String, Integer> {
'A'=>00,'B'=>01,'C'=>02,'D'=>03,'E'=>04,'F'=>05,'G'=>06,'H'=>07,'I'=>08,'J'=>09,
'K'=>10,'L'=>11,'M'=>12,'N'=>13,'O'=>14,'P'=>15,'Q'=>16,'R'=>17,'S'=>18,'T'=>19,
'U'=>20,'V'=>21,'W'=>22,'X'=>23,'Y'=>24,'Z'=>25,'a'=>26,'b'=>27,'c'=>28,'d'=>29,
'e'=>30,'f'=>31,'g'=>32,'h'=>33,'i'=>34,'j'=>35,'k'=>36,'l'=>37,'m'=>38,'n'=>39,
'o'=>40,'p'=>41,'q'=>42,'r'=>43,'s'=>44,'t'=>45,'u'=>46,'v'=>47,'w'=>48,'x'=>49,
'y'=>50,'z'=>51,'0'=>52,'1'=>53,'2'=>54,'3'=>55,'4'=>56,'5'=>57,'6'=>58,'7'=>59,
'8'=>60,'9'=>61,'+'=>62,'/'=>63
};
}
List<Integer> ints = new List<Integer>();
for (Integer idx = 0; idx< b64Str.length(); ++idx) {
String c = String.fromCharArray(new List<Integer> { b64Str.charAt(idx)});
ints.add(base64Vals.get(c));
}
return ints;
}
private class TPicklistEntry{
public string active {get;set;}
public string defaultValue {get;set;}
public string label {get;set;}
public string value {get;set;}
public string validFor {get;set;}
public TPicklistEntry(){}
}
public static Map<String,List<String>> GetDependentOptions(String pObjName, String pControllingFieldName, String pDependentFieldName) {
Map<String,List<String>> mapResults = new Map<String,List<String>>();
//verify/get object schema
Schema.SObjectType pType = Schema.getGlobalDescribe().get(pObjName);
if ( pType == null ) return mapResults;
Map<String, Schema.SObjectField> objFieldMap = pType.getDescribe().fields.getMap();
//verify field names
if (!objFieldMap.containsKey(pControllingFieldName) || !objFieldMap.containsKey(pDependentFieldName)) return mapResults;
//get the control & dependent values
List<Schema.PicklistEntry> ctrl_ple = objFieldMap.get(pControllingFieldName).getDescribe().getPicklistValues();
List<Schema.PicklistEntry> dep_ple = objFieldMap.get(pDependentFieldName).getDescribe().getPicklistValues();
//initialize results mapping
for(Integer pControllingIndex=0; pControllingIndex < ctrl_ple.size(); pControllingIndex++) {
mapResults.put( ctrl_ple[pControllingIndex].getLabel(), new List<String>());
}
//serialize dep entries
List<TPicklistEntry> objDS_Entries = new List<TPicklistEntry>();
objDS_Entries = (List<TPicklistEntry>)JSON.deserialize(JSON.serialize(dep_ple), List<TPicklistEntry>.class);
for (TPicklistEntry objDepPLE : objDS_Entries){
List<Integer> bitValues = ConvertB64ToInts(objDepPLE.validFor);
Integer bitMask = 32; // Ignore highest 2 bits
Integer intIndex = 0;
Integer bitIdx = 0;
for (Integer numBits = bitValues.size() * 6; numBits > 0; --numBits) {
Integer bits = bitValues[intIndex];
if ((bits & bitMask) == bitMask) {
mapResults.get( ctrl_ple[bitIdx].getLabel() ).add( objDepPLE.label );
}
bitMask = bitMask >>> 1;
++bitIdx;
if (bitMask == 0) {
bitMask = 32;
intIndex = intIndex + 1;
}
}
}
return mapResults;
}//GetDependentOptions
public static String FirstControllingValueFor(String pObjName, String pControllingFieldName, String pDependentFieldName, String childValue) {
Map<String,List<String>> mappedItems = GetDependentOptions(pObjName, pControllingFieldName, pDependentFieldName);
for (String key : mappedItems.keySet()) {
List<String> items = mappedItems.get(key);
Set<String> itemSet = new Set<String>(items);
if (itemSet.contains(childValue)) {
return key;
}
}
return null;
}
}
https://developer.salesforce.com/blogs/developer-relations/2008/12/using-the-metadata-api-to-retrieve-picklist-values.html
I only included GetPickListValues function to make the class a little more complete in respect to picklists.
I hope this can help you or others who might navigate to this forum question.