function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Swagat.TusharSwagat.Tushar 

Update picklist values and their dependencies using Metadata API

Hi All,

Requirement: To update four picklist field values with dependencies on any object. As the numbers of picklist values are high it’s difficult to manage the Field Dependencies manually.

 

Product Family

Product Line

Product Module

Product Version

 

Design Approach: So we planned to go for customization. We used four custom settings to store the picklist values. Then update the picklist fields values using Metadata API.

Below are the design of four custom settings.

Product Family

Family1

Family2

Family3

 

Product Line

Family1 - Line1

Family2 - Line2

Family3 - Line3

 

Product Module

Line1 - Module1

Line1 - Module2

Line2 - Module2

 

Product Version

Line1 - Version1

Line1 - Version1

Line2 - Version2

 

Problem: Though the above design works for less volume of data, when i am trying to update 1000 picklist values the system is not updating the values. I tried to debug my code but there is also an inconsistency in Debug Log or Debug Log is not showing completely.

 

I have posted about this inconsistency here:

http://boards.developerforce.com/t5/Apex-Code-Development/Inconsistent-Debug-Log-Debug-Log-not-showing/td-p/695633

 

Here is the code for the VF/Controller from where I am trying to invoke the Metadata update methods.

<apex:page controller="UpdatePicklist">
<apex:pageMessages ></apex:pageMessages>
    <apex:form >
        Add picklist values with field dependencies
        <apex:commandButton value="Product Family" id="theButtonFamily" Action="{!updatePicklistField_Product_Family}"/>
        <apex:commandButton value="Product Line" id="theButtonLine" Action="{!updatePicklistField_Product_Line}"/>
        <apex:commandButton value="Product Module" id="theButtonModule" Action="{!updatePicklistField_Product_Module}"/>
        <apex:commandButton value="Product Version" id="theButtonVersion" Action="{!updatePicklistField_Product_Version}"/>
    </apex:form>   
</apex:page>

 

Apex class/Controller

public class UpdatePicklist{
    public static MetadataService.MetadataPort createService(){
        MetadataService.MetadataPort service = new MetadataService.MetadataPort();
        service.SessionHeader = new MetadataService.SessionHeader_element();
        service.SessionHeader.sessionId = UserInfo.getSessionId();
        return service;
    }
    
    //Update Product Family
    public PageReference updatePicklistField_Product_Family() {
        List<Product_Family__c> lstProduct_Family = Product_Family__c.getall().values();
        MetadataService.MetadataPort service = createService();
        MetadataService.CustomField customField = new MetadataService.CustomField();
        customField.fullName = 'Case.Primary_Product_Family__c';
        customField.label = 'Primary Product Family';
        customField.type_x = 'Picklist';
    
        metadataservice.Picklist pt = new metadataservice.Picklist();
        pt.sorted= true;
        pt.picklistValues = new list<metadataservice.PicklistValue>();
            
        for(Product_Family__c objPicklistValues : lstProduct_Family){
            metadataservice.PicklistValue plValue = new metadataservice.PicklistValue();
            plValue.fullName=objPicklistValues.Family__c;
            plValue.default_x=false ;
            pt.picklistValues.add(plValue);       
        }
        customField.picklist = pt ;

        MetadataService.UpdateMetadata ut = new MetadataService.UpdateMetadata();
        ut.currentName='Case.Primary_Product_Family__c';
        ut.metadata= customField;
        MetadataService.AsyncResult[] results = service.updateMetadata(new List<MetadataService.updateMetadata> {ut});
        system.debug('xxxxxx'+results);
        system.debug('xxxxxx'+results[0].State);
        //check if async call completed
        /*if (results[0].State == 'Completed'){
            updatePicklistField_Product_Line();
        }*/
        return null;
    }
    
    //Update Product Line
    public PageReference updatePicklistField_Product_Line() {
        List<Product_Line__c> lstProduct_Line = Product_Line__c.getall().values();
        MetadataService.MetadataPort service = createService();
        MetadataService.CustomField customField = new MetadataService.CustomField(); 
        customField.fullName = 'Case.Primary_Product_Line__c';
        customField.label = 'Primary Product Line';
        customField.type_x = 'Picklist'; 
        
        metadataservice.Picklist pt = new metadataservice.Picklist();
        pt.sorted= true;
        pt.picklistValues = new list<metadataservice.PicklistValue>();
        pt.controllingField='Primary_Product_Family__c'; //***** name of controlling field . if picklist has contrlloing field , this must be asssigned . else field dependency will be deleted
        //************************
        
        Map<String, List<String>> mapDepValContVal = new Map<String, List<String>>();
        for(Product_Line__c prdLine : lstProduct_Line){
            List<String> lstControllingValues = mapDepValContVal.get(prdLine.Line__c);
            if(lstControllingValues == null)
                lstControllingValues = new list<String>();
            lstControllingValues.add(prdLine.Family__c);
            mapDepValContVal.put(prdLine.Line__c, lstControllingValues);
        }
        system.debug('xxxxxmapDepValContVal'+mapDepValContVal);
        
        for(String strDepVal : mapDepValContVal.keySet()){
            metadataservice.PicklistValue plValue = new metadataservice.PicklistValue();
            plValue.fullName=strDepVal;
            plValue.default_x=false ;
            plValue.controllingFieldValues = mapDepValContVal.get(strDepVal);
            pt.picklistValues.add(plValue);       
        } 
        customField.picklist = pt ;       
        
        MetadataService.UpdateMetadata ut = new MetadataService.UpdateMetadata();
        ut.currentName='Case.Primary_Product_Line__c';
        ut.metadata=customField;
        MetadataService.AsyncResult[] results = service.updateMetadata(new List<MetadataService.updateMetadata> {ut});
        
        //check if async call completed
        /*if (results[0].State == 'Completed'){
            updatePicklistField_Product_Module();
            updatePicklistField_Product_Version();    
        }*/
        return null;
    }
    
    //Update Product Module
    public PageReference updatePicklistField_Product_Module() {
        system.debug('cccccupdatePicklistField_Product_Module');
        //List<Product_Module__c> lstProduct_Module = Product_Module__c.getall().values();
        List<Product_Module__c> lstProduct_Module = [Select Name, Module__c, Line__c from Product_Module__c limit 200];
        system.debug('ccccclstProduct_Module'+lstProduct_Module);
        MetadataService.MetadataPort service;
        try{
            service = createService();
            system.debug('ccccc-1');
        }
        Catch(Exception ex){
         system.debug('ccccc0'+ex);
        }
        system.debug('ccccc1');
        MetadataService.CustomField customField = new MetadataService.CustomField(); 
        customField.fullName = 'Case.Primary_Product_Module__c';
        customField.label = 'Primary Product Module';
        customField.type_x = 'Picklist'; 
        system.debug('ccccc2');
        
        metadataservice.Picklist pt = new metadataservice.Picklist();
        pt.sorted= true;
        pt.picklistValues = new list<metadataservice.PicklistValue>();
        pt.controllingField='Primary_Product_Line__c'; //***** name of controlling field . if picklist has contrlloing field , this must be asssigned . else field dependency will be deleted
        //************************
        
        system.debug('ccccclstProduct_Module'+lstProduct_Module.size());
        Map<String, List<String>> mapDepValContVal = new Map<String, List<String>>();
        for(Product_Module__c prdModule : lstProduct_Module){
            system.debug('cccccprdModule'+prdModule);
            List<String> lstControllingValues = mapDepValContVal.get(prdModule.Module__c);
            if(lstControllingValues == null)
                lstControllingValues = new list<String>();
            lstControllingValues.add(prdModule.Line__c);
            system.debug('ccccclstControllingValues'+lstControllingValues);
            mapDepValContVal.put(prdModule.Module__c, lstControllingValues);
        }
        system.debug('cccccmapDepValContVal'+mapDepValContVal.size());
        
        for(String strDepVal : mapDepValContVal.keySet()){
            system.debug('cccccstrDepVal'+strDepVal);
            metadataservice.PicklistValue plValue = new metadataservice.PicklistValue();
            plValue.fullName=strDepVal;
            plValue.default_x=false ;
            plValue.controllingFieldValues = mapDepValContVal.get(strDepVal);
            pt.picklistValues.add(plValue);       
        } 
        system.debug('ccccc3');
        customField.picklist = pt ;  
        system.debug('ccccc4');     
        
        MetadataService.UpdateMetadata ut = new MetadataService.UpdateMetadata();
        ut.currentName='Case.Primary_Product_Module__c';
        ut.metadata=customField;
        MetadataService.AsyncResult[] results = service.updateMetadata(new List<MetadataService.updateMetadata> {ut});
        return null;
    }
    
    //Update Product Version
    public PageReference updatePicklistField_Product_Version() {
        system.debug('dddddupdatePicklistField_Product_Version');
        //List<Product_Version__c> lstProduct_Version = Product_Version__c.getall().values();
        List<Product_Version__c> lstProduct_Version = [Select Name, Version__c, Line__c from Product_Version__c limit 100];
        system.debug('dddddlstProduct_Version'+lstProduct_Version);
        MetadataService.MetadataPort service;
        try{
            service = createService();
            system.debug('ddddd-1');
        }
        Catch(Exception ex){
         system.debug('ddddd0'+ex);
        }
        system.debug('ddddd1');
        MetadataService.CustomField customField = new MetadataService.CustomField(); 
        customField.fullName = 'Case.Primary_Product_Version__c';
        customField.label = 'Primary Product Version';
        customField.type_x = 'Picklist'; 
        system.debug('ddddd2');
        
        metadataservice.Picklist pt = new metadataservice.Picklist();
        pt.sorted= true;
        pt.picklistValues = new list<metadataservice.PicklistValue>();
        pt.controllingField='Primary_Product_Line__c'; //***** name of controlling field . if picklist has contrlloing field , this must be asssigned . else field dependency will be deleted
        //************************
        
        system.debug('dddddlstProduct_Version'+lstProduct_Version.size());
        Map<String, List<String>> mapDepValContVal = new Map<String, List<String>>();
        for(Product_Version__c prdVersion : lstProduct_Version){
            List<String> lstControllingValues = mapDepValContVal.get(prdVersion.Version__c);
            if(lstControllingValues == null)
                lstControllingValues = new list<String>();
            lstControllingValues.add(prdVersion.Line__c);
            system.debug('dddddlstControllingValues'+lstControllingValues);
            mapDepValContVal.put(prdVersion.Version__c, lstControllingValues);
        }
        system.debug('dddddmapDepValContVal'+mapDepValContVal.size());
        
        for(String strDepVal : mapDepValContVal.keySet()){
            metadataservice.PicklistValue plValue = new metadataservice.PicklistValue();
            plValue.fullName=strDepVal;
            plValue.default_x=false ;
            plValue.controllingFieldValues = mapDepValContVal.get(strDepVal);
            pt.picklistValues.add(plValue);       
        } 
        system.debug('ddddd3');
        customField.picklist = pt ;  
        system.debug('ddddd4');     
        
        MetadataService.UpdateMetadata ut = new MetadataService.UpdateMetadata();
        ut.currentName='Case.Primary_Product_Version__c';
        ut.metadata=customField;
        MetadataService.AsyncResult[] results = service.updateMetadata(new List<MetadataService.updateMetadata> {ut});
        return null;
    }
}

 

Any words of advice or any other approach/solution?

 

Regards

Swagat

 

 

 
Best Answer chosen by Admin (Salesforce Developers) 
Swagat.TusharSwagat.Tushar
This is resolved now. . The issue was with the data provided to upload.
The controlling field values provided are not actually present in the controlling field.
So the async call was not succeeding and the result was “Error” with the message “FIELD_INTEGRITY_EXCEPTION”.

All Answers

Swagat.TusharSwagat.Tushar
This is resolved now. . The issue was with the data provided to upload.
The controlling field values provided are not actually present in the controlling field.
So the async call was not succeeding and the result was “Error” with the message “FIELD_INTEGRITY_EXCEPTION”.
This was selected as the best answer
ezdhanhussainezdhanhussain

Hi swagat i think your post can help me. My post is this

http://boards.developerforce.com/t5/Apex-Code-Development/Add-delete-values-in-pick-list-through-apex-and-visualforce/td-p/707015

you are using depandencies but i have only one picklist and need to retrieve and add/delete values inside picklist through visualforce and apex. can you help me ? 

Swagat.TusharSwagat.Tushar
public PageReference AddPicklistValue() {
	//Get the picklist values. I am getting here from a custom setting
	//Name of custom setting - "PicklistValues__c"
	//One field in custom setting with name "Services__c"
	List<PicklistValues__c> lstPicklistValues = Product_Family__c.getall().values();
	MetadataClass.MetadataPort objMetadataClass = new MetadataClass.MetadataPort();
	objMetadataClass.SessionHeader = new MetadataClass.SessionHeader_element();
	objMetadataClass.SessionHeader.sessionId = UserInfo.getSessionId();
	MetadataClass.CustomField customField = new MetadataClass.CustomField();
	customField.fullName = 'Client__c.Services__c';
	customField.label = 'Services';
	customField.type_x = 'Picklist';

	MetadataClass.Picklist pt = new MetadataClass.Picklist();
	pt.sorted= true;
	pt.picklistValues = new list<MetadataClass.PicklistValue>();
		
	for(PicklistValues__c objPicklistValues : lstPicklistValues){
		MetadataClass.PicklistValue plValue = new MetadataClass.PicklistValue();
		plValue.fullName=objPicklistValues.Services__c;
		plValue.default_x=false ;
		pt.picklistValues.add(plValue);       
	}
	customField.picklist = pt ;

	MetadataClass.UpdateMetadata ut = new MetadataClass.UpdateMetadata();
	ut.currentName='Client__c.Services__c';
	ut.metadata= customField;
	MetadataClass.AsyncResult[] results = objMetadataClass.updateMetadata(new List<MetadataClass.updateMetadata> {ut});
	return null;
}

 

Please check the above code. This might work. I am getting the values from a custom setting. You can get the values from VF input.

 

Please download the Metadata API and generate an apex class with name "MetadataClass" and use the same.