Warning: This uses undocumented methods. As with any code that relies on anything undocumented it’s not supported and it’s prone to breaking without warning so don’t rely on it working tomorrow!
It’s a known hidden feature of Salesforce that you can pre-populate fields on a standard page layout if you know the name of the fields. There are plenty of blogs on it. For example you can pre-populate the Account Name with the URL:
https://na43.salesforce.com/001/e?acc2=Peace+Without+Walls+Inc&acc5=012345
This gets a bit trickier still on custom page layouts:
https://na43.salesforce.com/a0Q/e?Name=Red%20Widget&00N0G00000DaxKQ=RED
Yeuck! Where did 00N0G00000DaxKQ come from? You have to dig it out using your browser developer tools.
Another blog post on the matter …
So to make this a bit easier, we’re going to write a little VF page and Controller to fathom it all out for us. We’ll only need to remember nice things like Developer Names for stuff.
To do this we need to query two system objects, the EntityDefinition and the FieldDefinition.
The Entity Definition will give us the URL and its Id as contained in the DurableId field.
Select DeveloperName, DurableId, EditUrl, NewUrl From EntityDefinition Where DeveloperName = 'Widget'
DeveloperName: Widget
DurableId: 01I0G000002e6SD
EditUrl: /{ID}/e
NewUrl: /a0Q/e
Using the DurableId from the first Query we can get the Field Definitions:
Select DeveloperName, DurableId, EntityDefinitionId, RunningUserFieldAccessId From FieldDefinition Where EntityDefinitionId = '01I0G000002e6SD' and DeveloperName = 'Colour'
DeveloperName: Colour
DurableId: 01I0G000002e6SD.00N0G00000DaxKQ
EntityDefinitionId: 01I0G000002e6SD
By stripping away everything after and including the . on the DurableId we are left with the Field Id we need to use in our URL.
So lets build something a bit more usable …
Controller:
public without sharing class PreloadPageLayoutController { public String RedirectURL {get; set;} private static final String OBJECT_PARAMETER_KEY = 'o'; /** * Constructor - Builds URL */ public PreloadPageLayoutController() { // Page Parameter Map Map paramMap = ApexPages.currentPage().getParameters(); // Get the Object Parameter String objectName = paramMap.get(OBJECT_PARAMETER_KEY); // Map the Key Pairs Map fieldMappings = new Map(); fieldMappings.putAll(paramMap); fieldMappings.remove(OBJECT_PARAMETER_KEY); try { // Query the Entity Definition for the Object EntityDefinition ed = [Select DeveloperName, DurableId, EditUrl, NewUrl From EntityDefinition Where DeveloperName = :objectName]; Map fieldNameToIdMap = new Map(); Set fieldNames = fieldMappings.keySet(); // Query the Field Definition for the Fields and Map the Developer Names to the Field Ids for (FieldDefinition fd : [Select DeveloperName, DurableId, EntityDefinitionId From FieldDefinition Where EntityDefinitionId = :ed.DurableId and DeveloperName in :fieldNames]) { String[] idParts = fd.DurableId.split('\\.'); fieldNameToIdMap.put(fd.DeveloperName, idParts[1]); } // Build the URL RedirectURL = ed.NewUrl; String prefix = '?'; // Loop through the parameters for (String key : fieldMappings.keySet()) { String value = fieldMappings.get(key); String fieldId = fieldNameToIdMap.get(key); String paramTemplate = '{0}{1}={2}'; String param = String.format(paramTemplate, new String[] { prefix, fieldId == null ? key : fieldId, value }); RedirectURL += param; prefix = '&'; } ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'Redirecting to: ' + RedirectURL)); } catch(Exception e) { ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, e.getMessage() + ' ' + e.getStackTraceString())); RedirectURL = null; } } /** * Action Method to Redirect */ public PageReference redirect() { PageReference ref; if (RedirectURL != null) { ref = new PageReference(RedirectURL); ref.setRedirect(true); } return ref; } }
Quick Unit Test Class:
@isTest private class PreloadPageLayoutControllerTest { @isTest static void testParams() { Map paramMap = ApexPages.currentPage().getParameters(); paramMap.put('o', 'Account'); paramMap.put('Name', 'Test'); paramMap.put('acc2', 'Test2'); PreloadPageLayoutController controller = new PreloadPageLayoutController(); PageReference ref = controller.redirect(); Map newParamMap = ref.getParameters(); System.assert(newParamMap.containsKey('Name')); System.assertEquals('Test', newParamMap.get('Name')); System.assert(newParamMap.containsKey('acc2')); System.assertEquals('Test2', newParamMap.get('acc2')); } }
Visualforce Page: PreloadPageLayout:
If your page does not redirect automatically click here
We can now pass the parameters to our custom page instead but instead of having to inspect the page and work out the yeuky ids we can use the Developer Names instead:
https://na43.salesforce.com/apex/PreloadPageLayout?o=Widget&Name=Red+Widget&Colour=RED
It also works on Standard Objects for Custom fields only. For Standard fields you still need to use acc1, acc2, acc3 etc:
https://na43.salesforce.com/apex/PreloadPageLayout?o=Account&acc2=Peace+Without+Walls+Inc&acc5=012345&My_Rating=Good
You can also use it from your own Apex Code to do a redirect and pre-load the page:
public PageReference redirect() { PageReference ref = Page.PreloadPageLayout; ref.getParameters().put('o', 'Widget'); ref.getParameters().put('Name', 'Red Widget'); ref.getParameters().put('Colour', 'RED'); return ref; }
Another use is a Custom Button to Add Red Widgets:
which you can then add onto the Search Layout.
Totally Awesome post.