Salesforce coding lessons for the 99%
Finally, Apex tutorials for point-and-click admins! Written by a self-taught Google engineer.
  • Beginner Tutorials
    • Apex
    • Certifications
    • Career Info
    • Technical Architect
    • Visualforce
    • Videos
  • Apex Academy
  • Success Stories
  • About Me
  • Misc
    • Mailbag
    • Challenges
    • Links
    • Login to my Org
Follow @dvdkliuor SUBSCRIBE!

Change your trigger on the fly using Custom Settings

March 2, 2014

Preface: this post is part of the Advanced Apex Concepts series.

Custom Settings are a hidden gem in Apex that always impresses people, especially bosses!

Custom Settings are variables that you use in your code but set and modify outside of your code.

Here’s an example:
You’re writing a trigger that sets a “Customer Service Rep” field on an Account every time there’s a high value Opportunity associated with it. Two things are certain: (1) The CSR on duty changes every week and (2) the threshold for a “high value” opp changes often since your company is expanding.

A perfect use case to use Custom Settings to set the CSR on duty and the “high value” opp threshold!

Benefits of using Custom Settings:

  • Change your variables through Salesforce.com without deploying code!
  • Any non-coder admin can now modify your variables and change how your code works!
  • Show your boss that you’re thinking ahead and not just concerned with doing the bare minimum!

Step 1: Create a Custom Setting “object” for your trigger:
Setup >> Develop >> Custom Settings >> New

Step 2: In your Custom Setting object, create Custom Fields for each needed variable:

Step 3: Create a Custom Setting record and edit its variables
Navigate to your Custom Setting >> Manage >> New

Step 4: Use your Custom Setting in your code!

trigger AddCSR on Opportunity (before insert) {
// Grab your Custom Setting values CSR_Settings__c settings = CSR_Settings__c.getInstance('csr'); String CSR_USER_ID = settings.CSR_User_ID__c; Decimal OPP_MIN_VALUE = settings.Opp_Minimum_Value__c;
// Create a master list of accounts to bulk update List<Account> accounts = new List<Account>(); for (Opportunity opp : Trigger.new) { // Make sure we meet the minimum threshold
if (opp.Amount >= OPP_MIN_VALUE) {
// This is a trick to get the related account! Account acc = new Account(); acc.Id = opp.AccountId; // Update the CSR and add to master list
acc.CSR__c = CSR_USER_ID;
accounts.add(acc); } } // Update the master list of accounts update accounts; }

Now if you need to edit the CSR on duty or the minimum Opportunity amount threshold, simply edit the record in Step 3 – no rewriting or deploying code necessary!

One important note – custom Settings aren’t automatically transferred between sandboxes and production, so make sure you include them in both places or your code will break!

Next post: How to simplify the most complex triggers!

57 Comments
Ganesh Gavhane
April 13, 2022 @ 12:12 pm

In this trigger i think event should be After insert because we are trying to
perrform Dml operation on Other object i.e Account.

in this you are using before insert but in before event the value of system field
is null(i.e id,lastModifiedBy etc)

I dont understand why before insert and update dml operation.

Thanks& Regards
Ganesh Gavhane

Reply
PARAG BHOR
November 29, 2020 @ 3:30 am

Can someone please tell how to create a custom field , which is required in this topic. Because if its going to be a look up field on account object, then what will be the parent object.

Reply
    PARAG BHOR
    November 29, 2020 @ 3:31 am

    Sorry not custom field, I mean Lookup field on account object

    Reply
parag
November 29, 2020 @ 3:27 am

Can please someone tell, how to create lookup field in this chapter.
There’s no look up field option in custom settings and if it gonna be a lookup on account object , then with whom.

Reply
sagar
January 21, 2020 @ 10:12 pm

Create a Hierarchical custom setting “TriggerSetting“. Create fields for all triggers developed in your system. This custom setting should be used to enable/disable any trigger from your org.

Reply
sagarrr
January 21, 2020 @ 10:11 pm

Create a Hierarchical custom setting “TriggerSetting“. Create fields for all triggers developed
in your system.This custom setting should be used to enable/disable any trigger from your
org.

Reply
Priyanka Nimar
November 21, 2016 @ 12:33 am

Hi David,

I want to replace the custom object with custom setting.
But the object is being queried with Order By on different fields in different classes.

Could you please help me in this.

select id,name from obj1 where *** order by field1

select id,name…. from obj1 where ** order by field2.

And all the fields are getting used in the code.

Regards,
Priyanka Nimkar

Reply
balireddy
August 28, 2016 @ 3:10 am

how do u create account without enter the required field account name in u r code……..

Reply
    David Liu
    August 29, 2016 @ 8:15 pm

    The account already exists =)

    Reply
balireddy
August 28, 2016 @ 2:37 am

hi david …u used update DML ….but i think it should be insert there

Reply
    David Liu
    August 29, 2016 @ 8:15 pm

    All accounts already exist!

    Reply
Meagan Diegelman
November 13, 2015 @ 8:14 am

Hi David– I have a trigger that automates chatter notifications on a record based on field changes. I’m planing to use custom settings to determine the notification text so that my customer can make changes to the notification once I leave. Right now I’m able to include field values in the notification text in my trigger (ie: Account.Name + ‘ was just updated to ‘ + Account.Status__c). Is that possible using custom settings? I know I can default the text but how would I reference fields on the record since there is no formula field option in custom settings.

PS–I feel like we might become best friends as I’m learning to code, hope that’s okay with you! :)

Reply
Kumar
August 9, 2015 @ 6:06 pm

Hi All,

Kindly let me know is there any way to modify the custom seetings values in visualforce page. please share the code .

Thanks in Advance,
Kumar

Reply
    David Liu
    August 9, 2015 @ 8:51 pm

    It’s possible! Don’t have the code but you can do it! Or just link to the actual custom setting page.

    Reply
      NB
      May 31, 2016 @ 12:12 am

      Hey David,

      I am in such a situation that I need to update record in After Trigger. Is it possible.??
      My scenario is that I want to fire a trigger only once even for multiple transactions after meeting my conditions.

      Reply
        David Liu
        June 1, 2016 @ 7:09 pm

        Totally possible, need to use static variables. Good luck!

        Reply
Cooler
March 21, 2015 @ 2:17 pm

David, am i right, settings ‘type’ uses singleton pattern?

Reply
Reshmi
February 12, 2015 @ 10:36 pm

Hi David,

Have got a question in the above custom settings trigger.

// This is a trick to get the related account!
Account acc = new Account();
acc.Id = opp.AccountId;

In the above code, we are creating a new account. and the current Oppty’s Account Id is passing to the new account. so would it be a duplicate?.. I didn’t get the the exact intention of the code. Pls help me. Thanks a lot for your time .

Reply
    David Liu
    February 12, 2015 @ 10:50 pm

    Not really actually!

    We’re not creating a new Account, we’re creating a new reference to the same account using the opp’s ID. The alternative would be to query the account outright, but that would take one of our SOQL queries.

    Hope this makes sense!
    David

    Reply
    Reshmi
    February 13, 2015 @ 2:40 am

    Hello David,

    I have got clear.. :) Thanks :)

    Reply
Sunil Nandipati
October 29, 2014 @ 6:11 am

Good Article. I have a Apex Scheduled job that needs to cleanup some data every now and then. I started using CSRs to record my previous data points like last_sync_dates here so that my Apex code can start looking from that point.

Reply
Swapnil
October 16, 2014 @ 12:33 am

Hi david, I don’t understand why we should take lookUp filed on Account, I am taking text field CSR__c on Account. Trigger is working fine with insert and update opportunity. and most important thing is , if we tried to take lookup field on Account , which object we should select for “Related to”. Custom setting object is not appearing in list.
Swapnil

Reply
ajay
September 20, 2014 @ 4:16 am

thnks

Reply
chitral
August 18, 2014 @ 1:04 pm

hey david,
where do we get this CSR user id from ?? like in the snapshot u hav put CSR user id …..

Reply
    chitral
    August 18, 2014 @ 1:33 pm

    if CSR ID is related to a particular account Id for whose opportunity we want to check …
    like i tried puting CSR id (in custom settings) that of a particular account id(which i created new)

    next when i create an opportunity for that particular account .
    on save i gt this error.

    Error: Invalid Data.
    Review all error messages below to correct your data.
    Apex trigger AddCSR caused an unexpected exception, contact your administrator: AddCSR: execution of BeforeInsert caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.AddCSR: line 4, column 1

    Reply
      David Liu
      August 18, 2014 @ 7:49 pm

      Make sure the name of the custom setting is “csr”

      Reply
    David Liu
    August 18, 2014 @ 7:50 pm

    The URL of any User record =)

    Reply
SD
July 22, 2014 @ 2:55 am

Hi David, in the example above, i could not understand one thing : that Trigger is written on before insert and within the code its doing a update account… wouldn’t this DML statement be always relevant to the trigger event .???

Reply
    David Liu
    July 27, 2014 @ 10:01 pm

    hahahaha you’re right, I didn’t think anyone would notice that! I used insert only to make the code simpler

    Reply
      Lutgardo García Escalera
      September 23, 2014 @ 1:22 pm

      I understood that the trigger fires everytime an Opportunity is inserted, but actually updates accounts. Therefore you have to write a DML statement since you are “acting” over a different object that the triggered-object.

      And it is update instead of insert since all accounts have to be created prior to opportunities.

      Reply
Dean
July 17, 2014 @ 3:46 pm

Hi David,

Im getting “Invalid field CSR__c” . I pretty much copied/paste same code above. Not sure where to look to correct..

Reply
    David Liu
    July 17, 2014 @ 10:03 pm

    Gotta create that lookup field on the Account first! Sorry I didn’t make that clear!

    Reply
      Tony Groome
      September 12, 2014 @ 6:57 am

      What Account? Is this a custom account that we created earlier? As far as I know we can’t create a lookup field on the Account object? Thanks :)
      ps Nice SpiderMonster suit!!

      Reply
      Chuck
      October 11, 2014 @ 9:02 pm

      David, regarding creating the custom field “CSR__c” on the accounts object, did you literally mean it should be a LookUp type? Shouldn’t it be a type of Text(18) (Unique Case Sensitive)? Thx.

      Reply
        David Liu
        October 11, 2014 @ 10:13 pm

        Gotta be a lookup type! Even though it’s a lookup, it’s populated by an ID.

        Reply
Roy
July 3, 2014 @ 2:10 pm

Thank you for this David. Your humor is clever and really does help to keep people engaged! I am still working my way through but Chapter 6 is absolutely my favorite so far! :)

Reply
    David Liu
    July 3, 2014 @ 2:12 pm

    hehehe someone thinks I’m funny!!! ^_^_^_^_^

    Reply
Virginia
May 16, 2014 @ 11:41 am

Note to self (and anyone else this might help):
* Make sure that your Custom Setting visibility is set to “Public”
* The record name is case-sensative. Bye != bye

Reply
    David Liu
    May 17, 2014 @ 10:30 am

    Thank you Virginia!! You are right on!!

    Reply
Dave Lea
April 11, 2014 @ 1:44 pm

I’ve been trying to write a test class for this trigger and I think I’m almost there but I can’t seem to figure out how to get the id of the account I created in the test class to then assign it to the Opportunity I’m creating as well.

Here is the section of the test class I’m struggling with. Earlier in the test class I created a test account. Here you can see I’m searching for it and using it to do an assertion. I’m also trying to reuse that id to create a new opportunity related to that Account but I keep getting the error “Error: Compile Error: Illegal assignment from Id to SOBJECT:Account at line 41 column 9”. I’m guessing there is a proper way to create a record and get that right back? If so whats the best way to use that when you create a new record?

Thanks so much and your site/tutorials are AMAZING! Keep up the great work!

List accountAssert = [SELECT Name, Id, CSR__c FROM Account
WHERE Name = ‘Test Account’
LIMIT 1];

System.assertEquals(users[0].Id, accountAssert[0].CSR__c);

Opportunity o = new Opportunity();
o.Name = ‘Test’;
o.Account = accountAssert[0].Id;
o.Amount = 10.00;
o.CloseDate = ’01/01/2099′;
o.Stage = ‘Prospecting’;

Reply
    David Liu
    April 11, 2014 @ 11:44 pm

    hehehe all you need to do is change that line to:
    o.AccountId = accountAssert[0].Id;

    Then give yourself a pat on the back for getting even that far on your own!

    P.S. you can find a full list of valid fields of Opps here:
    http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_opportunity.htm

    David

    Reply
      SD
      July 22, 2014 @ 3:25 am

      Hi David, i have written a test class for this but i am getting only 18% coverage.
      Unable to understand where am I going wrong, could you pl have a look at the below code and suggest [Also, post testing coverage,some lines are blue and some red or sometimes its purple and pink on the trigger written.. : what does they mean?)

      @isTest
      public class TestClassAddCSR {

      static testmethod void NewOppWithMinAmount()
      {
      Opportunity op = new Opportunity();
      op.Name =’test ADDCSR’;
      op.closeDate = date.today() + 30;
      op.stagename = ‘Prospecting’;
      op.AccountId = ‘001i000000kHASP’;
      op.Amount = 600;

      insert op;

      }
      }

      Reply
        SD
        July 22, 2014 @ 3:46 am

        Feeling goood David, i could fix the above test class and now got the 100% coverage. :D…but now unable to understand how test class data exactly works in salesforce.

        I am not able to understand is, when i write insert DML statement in test class, why it is not creating a new opportunity in the application. As i was expecting after running the test class i would see a new opportunity “test ADDCSR’ in the application, but i dont ???

        Reply
          David Liu
          July 27, 2014 @ 10:00 pm

          Great question – anything created during your test class simply exists during the test. After the test is done it’s all deleted =)

          Reply
            SD
            July 28, 2014 @ 1:19 am

            Thanks David. I am waiting for more series from you : On Integration and Dynamic APex/Visuaforce.
            Cant wait to learn more… Cheers!!

            Reply
Anonymous
April 8, 2014 @ 12:44 am

Since custom settings are cached, if you update the value of an existing one is there a way to refresh the cache?

Reply
    David Liu
    April 8, 2014 @ 9:39 pm

    Salesforce will automatically do this for you =) No need to worry about Custom Setting updates not reflecting!

    Reply
Sourav Biswal
March 27, 2014 @ 1:50 am

This is one of the Best chapters that i have come in the Site. I have been reading the chapters from the very first and i just cannot leave it. Really a great explanation of the things in apex . I remember reading the Force.com fundamentals and dozing off countless times, but David you add a whole new dimension , a great spark to Apex learning. keep up the good work!!!!

Reply
    David Liu
    March 27, 2014 @ 2:29 am

    Sourav, I am so glad you feel this way about my site!! It is an honor!!!

    Reply
Ayan Hore
March 14, 2014 @ 5:33 am

David,
Can I update the costom settings variables’ value using any trigger or workflow? The reason I’m asking this is because sometimes any Org wants to dynamically change the values based on some conditions and they don’t want to depend on manual intervention (Admin) to do so. If you can share some inputs on this, would be very helpful..!!

Reply
    David Liu
    March 15, 2014 @ 11:25 am

    Hey Ayan,

    You definitely can!

    Let’s say your custom setting is called “My_Settings__c”.
    Your settings record is called “default”
    And you have a field on it called “Number__c”

    You’d be able to update it simply like this:
    My_Settings__c settings = My_Settings__c.getInstance(‘default’);
    settings.Number__c = 2;
    update settings;

    Note that these scenarios should be rare – sometimes it’s better in these cases to create a custom object!
    David

    Reply
      Paul Coleman
      March 19, 2014 @ 3:37 pm

      Just pointing out that custom settings are really custom objects and their records stored like any other custom object. The difference is they are cached so their records can be accessed quickly via the getInstance() method. That is, for a custom object that is not a custom setting, the getInstance() method is the same as executing a SOQL query by Name (WHERE Name = :parm). Because custom settings are custom objects that are cached, there are limits on how much data can be stored in each record and in the custom setting cache in total (10Mb in API v29). Otherwise all interactions such as queries, loading records, and record sharing that apply to all custom objects also apply to custom settings. Indeed, the meta component xml for a custom object vs custom setting is identical except the custom setting will include the additional elements:
      List
      Public

      Reply
        Paul Coleman
        March 19, 2014 @ 3:39 pm

        Sorry, those elements got escaped out:
        [customSettingsType>List[/customSettingsType]
        [customSettingsVisibility>Public[/customSettingsVisibility]

        Reply
        David Liu
        March 19, 2014 @ 9:44 pm

        Totally right! Thank you Paul!

        That is the perfect answer to #10 on the Chapter 6 quiz!
        https://www.sfdc99.com/2014/03/17/quiz-chapter-6/

        Reply
John
March 3, 2014 @ 2:53 pm

David, any specific recommendations/considerations for handling custom settings in Test Code?

Reply
    David Liu
    March 3, 2014 @ 10:41 pm

    This goes in the hall of fame as one of the best questions asked on this site!

    If you’re relatively new to Apex, consider yourself an awesome student with lots of promise =)

    The correct way to test this is to create your Custom Setting record in your test class, ie:
    CSR_Settings__c settings = new CSR_Settings__c();
    settings.Name = ‘csr’;
    settings.CSR_User_ID__c = // Some user ID
    settings.Opp_Minimum_Value__c = 5000;
    insert settings;

    Salesforce treats Custom Settings very similarly to a custom object, the biggest difference is that you don’t need to do a SOQL query to get this information into your trigger, which is very convenient!

    Keep on learning how to code, you are making good progress.
    David

    Reply
      John
      March 4, 2014 @ 6:28 am

      Thanks for the quick response, David. Appreciate it!

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *


*

*

Theme: Simple Style by Fimply