+ Start a Discussion

Metadata api - Picklist Value Sets


Does anybody have working code to retrieve and upsert picklist value sets ?

Can't get it to work, this is my current code :
private GlobalValueSet readGlobalValueSet(String picklist) throws Exception {
		GlobalValueSet values = new GlobalValueSet();

			MetadataConnection metadataConnection = sfmcon.getConnection();
			ReadResult readResult = metadataConnection.readMetadata("GlobalValueSet", new String[] {picklist});
			Metadata[] mdInfo = readResult.getRecords();
			if (mdInfo.length == 1) {
				values = (GlobalValueSet) mdInfo[0];
			else {
				log.info("None or multiple components");		

		return values;

readMetadata returns :

[CustomValue [Metadata  fullName='A02'

The picklist value is active so i would expect :

[CustomValue [Metadata  fullName='A02'

Later when i execute the upsert with :
MetadataConnection metadataConnection = sfmcon.getConnection();
			SaveResult[] results = metadataConnection.updateMetadata(new Metadata[] {repair});

I get the error output :

Error encountered while updating: Application
Error message: CustomField not found.
Varun SinghVarun Singh
Hi Newtec,

You can do this using MetaDataAPI. In MetadataAPI you can add picklist Value.
In following code we add two and three as a picklist value Picklist__c field on Lead.
Use following code in your APEX class:
public static void UpdatePicklistField()
	    MetadataService.MetadataPort service = createService();     
	    MetadataService.CustomField customField = new MetadataService.CustomField();
	    customField.fullName = 'Lead.picklist__c';
	    customField.label = 'picklist';
	    customField.type_x = 'Picklist';
	    metadataservice.Picklist pt = new metadataservice.Picklist();
	    pt.sorted= false;
	    metadataservice.PicklistValue two = new metadataservice.PicklistValue();
	    two.fullName= 'second';
	    two.default_x=false ;
	    metadataservice.PicklistValue three = new metadataservice.PicklistValue();
	    three.fullName= 'third';
	    three.default_x=false ;
	    pt.picklistValues = new list<metadataservice.PicklistValue>{two,three};
	    customField.picklist = pt ;
	    MetadataService.UpdateMetadata ut = new MetadataService.UpdateMetadata();
	    ut.metadata= customField;	
	    MetadataService.AsyncResult[] results = service.updateMetadata(new List<MetadataService.updateMetadata> {ut});
public static MetadataService.MetadataPort createService()
		MetadataService.MetadataPort service = new MetadataService.MetadataPort();
		service.SessionHeader = new MetadataService.SessionHeader_element();
		service.SessionHeader.sessionId = UserInfo.getSessionId();
		return service;		

If this is your solution then please mark as a solution
Hi Varun,

thx for your response.

The code i supplied is java using the metadata api.

Nevertheless :

I tried your code in apex and got the error : 

Invalid type: MetadataService.MetadataPort
Varun SinghVarun Singh
Hi NewTec,
it is  apex code not java.
You can access metadata  directly 

Find MetaData API Wsdl

Go to setup--->API-->Metadata WSDL

Click on the link below to download a Metadata WSDL file.

Generate Metadata WSDL---->

How to geneate Apex from WSDl-->Setup-->apex classes--->Geneate from Wsdl

First  you to generate apex code  for meta data API using wsdl file of metadata

to use MataData is API for  apex first  you have genearte apex code from matadata wsdl file.


you can also use apex metadata class from GitHUB-->Copy code from github and paste into apex classes(New Class)

Jack D PondJack D Pond
This is an old thread, but manually entering picklist values when importing data from other sources is just too cumbersome.  An updated way to do this is through VSCode with the Salesforce CLI addon (SFDX) by directly editing the metadata.  First, get the metadata object for your global name of the metadata object found using:
sfdx force:mdapi:describemetadata -f completeobjectlist.txt
when you look in the file(completeobjeclist.txt), you will see the complete metadata object description for Picklist Value Set as:
      "directoryName": "globalValueSets",
      "inFolder": false,
      "metaFile": false,
      "suffix": "globalValueSet",
      "xmlName": "GlobalValueSet"
Add this to your project manifest (package.xml)
Once you have retreived from source, using View-->Command Pallet (or right click on manifest):
SFDX: Retrieve Source in Manifest from Org
You will now have a list of all your Picklist Value Sets in metadata form in your project under the directory globalValueSets.  The API name (Value) in these sets is <fullName> while the picklist user visible selection is <label>.  You can now update or add your own GlobalValueSet through the xml metadata.  Here is an example:
<?xml version="1.0" encoding="UTF-8"?>
<GlobalValueSet xmlns="http://soap.sforce.com/2006/04/metadata">
        <label>Test 1</label>
        <label>Test 2</label>
        <label>Test 3</label>
    <description>This is an Example Picklist Value Set</description>
    <masterLabel>Example Picklist Value Set</masterLabel>

Further tip.  I created a formula column in my Excel spreadsheet to generate the <customValue> component for each picklist value in an Excel table which I then copied into the xml (after removing the extraneous quotes(").  In Excel, the formula was:
        <fullName>" & [@Value] & "</fullName>
        <label>" & [@Label] & "</label>
You could do the same using the Force IDE too.