As a Salesforce Admin you sometimes wish you could create a custom button on an object that does one thing depending on a certain condition or does something else if the condition is not met.
This is possible but mostly requires some javascript knowledge. A lot of new admins, including myself at one time, depend on an external consulting firm because it means you’ll have to use some sort of code.
My company depended on external consultancy for such requirements and after letting then create some, analysing their code, I actually can create them myself now.
Once you get how they are written and how it works, they are not that difficult to create or modify. So, I thought I’d share some examples of custom button code that every admin could use in different scenarios.
General settings for the custom button if you are going to use conditions:
1. Alert if condition is not met otherwise do your thing
In the following example the opportunity probability has to be greater than 90% to generate a Contract document with drawloop. If the probability is lower an alert will be displayed.
The button code:
{!REQUIRESCRIPT("/soap/ajax/25.0/connection.js")} var check1 = {!Opportunity.Probability >= 0.9}; var error1string = "Error:\n"; var error1found = false; if(!check1) { error1string += "First change the probability to 90% or higher perform THIS ACTION \n"; error1found = true; } if(error1found) { alert(error1string); window.location = "{!URLFOR($Action.Opportunity.View,Opportunity.Id)}"; } else { window.location = "/apex/loop__looplus?eid={!Opportunity.Id}&accountId={!Opportunity.AccountId}&sessionId={!$Api.Session_ID}&filter= {!$User.Landcode__c}"; }
This results in the following alert message:
2. Alert in case of multiple conditions otherwise do your thing
The following checks two conditions with their own custom alert message before it lets you perform the action.
The button code:
{!REQUIRESCRIPT("/soap/ajax/25.0/connection.js")} var check1 = {!Opportunity.Probability >= 0.9}; var error1string = "Error:\n"; var error1found = false; if(!check1) { error1string += "Probability is not equal or greater than 90%! \n"; error1found = true; } var check2 = {!NOT(ISBLANK(Opportunity.StartDate__c))}; var error2string = "Error:\n"; var error2found = false; if(!check2) { error2string += "StartDate is blank! \n"; error2found = true; } if(error2found) { alert(error2string); window.location = "{!URLFOR($Action.Opportunity.View,Opportunity.Id)}"; } else if(error1found) { alert(error1string); window.location = "{!URLFOR($Action.Opportunity.View,Opportunity.Id)}"; } else { window.location = "/apex/loop__looplus?eid={!Opportunity.Id}&accountId={!Opportunity.AccountId}&sessionId={!$Api.Session_ID}&filter= {!$User.Landcode__c}"; }
Resulting in:
and/or:
3. Redirect to different URLs depending on several user fields like division or language or…
The following is somewhat more complex. This button is a custom button to a custom “add products” selection page on an opportunity. It’s just to show how parameters can change the redirection to specific url’s. In this case it will redirect to a custom visualforce page depending on the users language (custom field on user) and division (standard field on user) and includes a fallback to the default product selection page in all other cases.
You can also see that only the page name changes and that opportunity.id will be appended to the chosen url in all cases.
var loc; if( "{!$User.Language__c}" == "fr" && "{!$User.Division}" == "France" ){ loc = "/apex/opportunityProductEntryFR_FR?"; } else if( "{!$User.Language__c}" == "en_US" && "{!$User.Division}" == "Group" ){ loc = "/apex/opportunityProductEntryEN?"; } else if( "{!$User.Language__c}" == "fr" && "{!$User.Division}" != "Belgium" ){ loc = "/apex/opportunityProductEntryBE_FR?"; } else if( "{!$User.Language__c}" == "nl_NL" && "{!$User.Division}" == "Belgium" ){ loc = "/apex/opportunityProductEntryBE_NL?"; } else{ loc = "/p/opp/SelectSearch?"; } loc += "addTo={!Opportunity.Id}&" + "retURL={!Opportunity.Id}&" + "sfdc.override=1&" + "id={!Opportunity.Id}"; window.top.location.href = loc;
4. Create a related record or update the record if it already exists
This is very advanced but shows that you can use SOQL queries within a button.
The following button is placed on opportunity and creates a case (specific recordtype) to the correct queue depending on assignmentrules. But because we only allow one such case per opportunity it also has to look if such a case does not exist yet and redirect the user to that case if it does. If not such case exists yet it has to go to the create case with several fields and lookups prefilled to make it easier on the user. (comments in the code explain what is happening)
{!REQUIRESCRIPT("/soap/ajax/25.0/connection.js")} // Button on Opportunity pagelayout. Creates a case of recordtype "Order". // This case has to go to the correct back office queue through assignment rules depending on the region // of the owner of the opportunity. // Only Closed Opportunities var isClosed = "{!Opportunity.IsClosed}"; if (isClosed == true) { // Find the correct Recordtype var recordtypeResult = sforce.connection.query("Select Id FROM RecordType WHERE Name='Order'"); if (recordtypeResult.size != 1) { alert("Recordtype Order not found!"); } else { var recordType = recordtypeResult.getArray("records"); var opportunityId = "{!Opportunity.Id}"; var caseResults = sforce.connection.query("Select Id FROM CASE WHERE Opportunity__c='" + opportunityId + "'"); if (caseResults.size == 0) { //Create the case and prefill some fields var newCase = new sforce.SObject("Case"); newCase.RecordTypeId = recordType[0].Id; //lookup the contactid to fill the lookup contact field of the case var recordtypeResult2 = sforce.connection.query("Select ContactId From OpportunityContactRole Where OpportunityId = '" + opportunityId + "'"); if (recordtypeResult2.size == 1) { var recordType2 = recordtypeResult2.getArray("records"); newCase.ContactId = recordType2[0].ContactId; } newCase.AccountId = "{!Opportunity.AccountId}"; newCase.Opportunity__c = opportunityId; newCase.Subject = "Opportunity " + "{!Opportunity.Name}"; newCase.Origin = "Colleague"; try { var createCaseresult = sforce.connection.create([newCase]); } catch (error) { alert("Error while creating the case.\n" + error); } var caseId = createCaseresult[0].id; if (caseId != null) { window.parent.frames.location.replace("/" + caseId + "/e?retURL=" + opportunityId + "&cas21=0"); // parameter cas21 will check the checkbox Assign using active assignment rules. } else { alert("Error: " + createCaseresult[0].errors); } } else { alert("There already exists a Case for this opportunity, we will redirect to that case"); var caseArray = caseResults.getArray("records"); window.parent.frames.location.replace("/" + caseArray[0].Id + "/e?retURL=" + opportunityId + "&cas21=0"); } } }
5. Update a record before performing an action
I wrote a previous post that uses this called Skip the pricebook selection page and go directly to productsearch depending on fieldvalues
Do not try to just copy/paste the examples because they all contain custom fields and won’t work for you as they are. My intention is to show you that there are several use cases where a custom button can help and if you read through the examples I’m sure you could use the code and tweak it a little bit to also work for you.
If you want to know more about using custom buttons, I found the following resources and code samples:
- Displaying Alerts
- Getting RecordId’s
- Mass Delete
- Passing RecordId’s to an external URL
- Reopening cases
- Open a Google map passing Record values
- Call an apex class from a button
- Update the status of a record sample
I would appreciate it if you’d share your custom button use case and code, if you have any. Getting to know lots of scenarios opens up new ideas for everyone.
Hope this helps anybody ????