Refer to Record Type ID in Formula without Hard-coding

I'm building a Custom List Button in a Dev Environment, and I'd like it to work with no changes when deployed to Production even though all IDs will change. The list button (which will be displayed in a related list) allows users to create a new related object, but specifies a specific Record Type, and pre-fills the new object with data from the current record. It looks like this:

The problem is that this RecordType ID will change with deployment. I'll always know it's name, though. Is there any way to use that? Update: Also, won't the custom field ID change also ( CF00NJ0000000QIX7 above) -- what do I do about that?

asked Sep 25, 2012 at 3:11 11.2k 9 9 gold badges 67 67 silver badges 121 121 bronze badges

Benj, 2 things: (1) yes, the custom field ID is different in every org (e.g. Prod, Test Sandbox, Dev Sandbox), and use of this 'Id' is NOT supported, but it should remain constant in a single org, so as long as you figure out what it is in every org you use, you could store it in a custom setting, as @Forceguru suggests. (2) It is always best practice to use RecordType.DeveloperName when possible, not the Id.

Commented Sep 28, 2012 at 17:10 Zach, that's helpful. Can I refer to RecordType.DeveloperName in custom links URLs like the above? Commented Sep 28, 2012 at 17:14

5 Answers 5

You can use custom setting for this. Keep the record type Id in custom setting and use that in your button code, it will look something like this "c.RecordTypeId_c>"

answered Sep 25, 2012 at 3:24 429 3 3 silver badges 7 7 bronze badges

Hm. This would require a configuration change on deployment, but it can be documented easily. Thanks.

Commented Sep 25, 2012 at 4:23

Good solution Forceguru. The $RecordType global variable is not available in Custom button context, but the $Setting. variable is, so this would work great for your solution, and requires no Apex code.

Commented Sep 25, 2012 at 12:24 There are many other options, but this is the shortest and sweetest. Commented Sep 28, 2012 at 22:50

As an aide once you deploy to Production and refresh your sandboxes from Prod, record type ids and for that matter all ids (metadata) will be in sync (I.e. same ) across environments

answered Sep 29, 2012 at 0:16 techtrekker techtrekker 18.4k 1 1 gold badge 44 44 silver badges 50 50 bronze badges

Do you know where SF has that documented (link)? I agree with you, but just wonder where SF has it documented.

Commented Sep 29, 2012 at 0:59 Just know from practical experience. Don't think I've seen it in documentation. Commented Sep 29, 2012 at 1:05

For the sake of anyone who's doing this in Visualforce (which, Benj, I recognize you're not), here's what I would do: get a reference to the record type Id in Apex using a method similar to this: (note that I am returning a Map keyed by RecordType DeveloperName, NOT Name, because Name can always be changed/overridden in Production org, whereas DeveloperName does not change. This is an especially important best practice when developing managed packages.

// Returns a map of active, user-available RecordType IDs for a given SObjectType, // keyed by each RecordType's unique, unchanging DeveloperName global static Map GetRecordTypeIdsByDeveloperName( Schema.SObjectType token ) < // Build a map of RecordTypeIds keyed by DeveloperName MapmapRecordTypes = new Map(); // Get the Describe Result Schema.DescribeSObjectResult obj = token.getDescribe(); // Obtain ALL Active Record Types for the given SObjectType token // (We will filter out the Record Types that are unavailable // to the Running User using Schema information) String soql = 'SELECT Id, Name, DeveloperName ' + 'FROM RecordType ' + 'WHERE SObjectType = \'' + String.escapeSingleQuotes(obj.getName()) + '\' ' + 'AND IsActive = TRUE'; List results; try < results = Database.query(soql); >catch (Exception ex) < results = new List(); > // Obtain the RecordTypeInfos for this SObjectType token Map recordTypeInfos = obj.getRecordTypeInfosByID(); // Loop through all of the Record Types we found, // and weed out those that are unavailable to the Running User for (SObject rt : results) < if (recordTypeInfos.get(rt.Id).isAvailable()) < // This RecordType IS available to the running user, // so add it to our map of RecordTypeIds by DeveloperName mapRecordTypes.put(String.valueOf(rt.get('DeveloperName')),rt.Id); >> return mapRecordTypes; > 

TO use this to accomplish your need, you could do something like the following:

// CONTROLLER public class MyController() < public transient Id myRecordType < public get < if (myRecordType == null) < myRecordType = GetRecordTypeIdsByDeveloperName( DesiredObject__c.SObjectType ).get('Desired_Record_Type_Developer_Name'); >return myRecordType; > private set; > > // Visualforce Page with Link to create a new record of this type '/>