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!

Example: How to write an Apex trigger

May 12, 2013

Preface: this post is part of the Write Your First Trigger From Start to Finish series.

Let’s write a trigger that’s both simple and practical!

We’ll write a trigger on the User object – all it will do is check the “Allow Forecasting” checkbox on every newly created user. Salesforce won’t let us modify this permission in a workflow, but the joke’s on them… we can just write a trigger!

trigger ForceForecasting on User (before insert) {
for (User userInLoop : Trigger.new) {
userInLoop.ForecastEnabled = true;
}
}

I added some color to the code to help you focus on what’s important. More importantly though, the colors will show you what you can ignore… save your brain power!

  • Green highlighted lines means it’s important! The deeper the green, the more useful the code. Skim the code without any highlights, that’s just boilerplate code.
  • Blue colored text are Salesforce reserved variables or sObjects. They have useful functionality that I will teach you to master!
  • Purple colored text are variables that we define. We can name them anything we want!

For now, try to guess what each word/line does based on its color.

Next post: An extended look: How to write a simple Apex trigger

60 Comments
Noah
November 18, 2020 @ 2:42 pm

Why does this code not work?:

// Write a trigger that automatically creates an Account
// whenever a Lead is created. The Account must be named
// after the last name of the Lead.

trigger AccountCreater on Lead(after insert) {
for (Lead lead : Trigger.new) {
Account acc = new Account();
acc.Name = lead.Lastname;
insert acc;
}
}

Reply
    Giang
    December 3, 2020 @ 11:55 am

    Hi Noah, Do you think Lastname causing this problem? I am using LastName (CamelCase). I am new too so not sure if it helps.

    Reply
      Rohan
      January 20, 2022 @ 9:44 am

      it is case insenesitive

      Reply
    Anonymous
    February 11, 2021 @ 4:39 am

    Hi Noah,
    I’m having the same issue as well. My code is the same as yours, but the Account does not get created.

    Any ideas?

    Reply
    Mani
    February 11, 2021 @ 4:47 am

    Hi Noah – when you click on the Accounts tab, you’d have to change List View from “Recently Viewed” to “All Contacts”. You should then be able to see the accounts that you create.

    Reply
    Preksha
    June 29, 2021 @ 4:51 pm

    acc.Name=lead.LastName; // line 3

    Reply
    Isteyak Hussain
    July 15, 2021 @ 10:56 am

    I think you also have to add id.

    Reply
    Samyak Jain
    October 24, 2021 @ 11:07 pm

    maybe bcoz of the variable name(lead) which creates confusion between a datatype and a variable to its compiler…just change the variable name and it’ll work

    Reply
Alex Chudacoff
April 1, 2016 @ 2:32 pm

Well, I think the folks at SFDC are on to your little workaround.

After clicking save, an error appears next to he Allow Forecasting check box.

Error: Allow Forecasting is not allowed for this License Type.

But I get it, the trigger affected the field.

Reply
Shefali
February 4, 2016 @ 5:12 am

Hi David,

When I am trying to create a user to test this trigger, I am getting an error ” Allow Forecasting is not allowed for this License Type”, eventhough I have enabled Forecasting. I tried to create this user with every license type but I am getting the same error. Could you please help me out?
And, thank you for this awesome site!

Thanks,
Shefali

Reply
    David Liu
    February 4, 2016 @ 7:40 pm

    Check out some of the earlier comments in this post, some others have solved the issue!

    Reply
    Anonymous
    April 13, 2021 @ 11:51 pm

    To turn on forecasting:
    Setup >> customize >> forecast >> forecast setting >> Enable forecast

    To overcome the “Allow Forecasting…” error, User License = ‘Salesforce’ when creating a new user.

    If a ‘Salesforce’ user license is not available, this means you have used up all allowed ‘Salesforce’ licenses and will have to change some of the users with ‘Salesforce’ license to a different license.

    Reply
Pavan
January 22, 2016 @ 5:32 pm

Iam new to salesforce. Thats why Iam asking this question.

“We’ll write a trigger on the User object – all it will do is check the “Allow Forecasting” checkbox on every newly created user. Salesforce won’t let us modify this permission in a workflow,”.

Why can’t we do this with field update operation through workbench?

Reply
    David Liu
    January 25, 2016 @ 11:02 pm

    Not possible through workflow but it is possible through process builder! This trigger really is just practice =)

    Reply
Mohammed Faizan
October 28, 2015 @ 12:35 pm

Hai David,

I have started learning salesforce, but when iam trying to execute this trigger it is not working.
Everytime when iam creating a new user allow forecasting is not checked. but the trigger is correct.

Reply
    David Liu
    November 2, 2015 @ 9:29 pm

    The trigger definitely isn’t correct!

    Reply
Priyanka
January 13, 2015 @ 1:05 am

Hi David,

While executing above trigger, I get below error:
Error: Allow Forecasting is not allowed for this License Type.

Reply
    David Liu
    January 13, 2015 @ 7:51 pm

    Turn on Forecasting!

    Reply
      Pavan Kumar
      May 16, 2018 @ 3:09 am

      Please let me know how to turn on “Forecasting” and fix the error “Allow Forecasting is not allowed for this License Type”.

      Iam new to salesforce as well. Please help me.

      Reply
        pavan
        May 24, 2018 @ 3:57 am

        Please respond

        Reply
        Zafar
        December 4, 2018 @ 9:47 am

        To turn on forecasting:
        Setup >> customize >> forecast >> forecast setting >> Enable forecast

        To overcome the “Allow Forecasting…” error, User License = ‘Salesforce’ when creating a new user.

        If a ‘Salesforce’ user license is not available, this means you have used up all allowed ‘Salesforce’ licenses and will have to change some of the users with ‘Salesforce’ license to a different license.

        Reply
      Teja
      March 31, 2021 @ 4:25 am

      Hi David.. even am Turn on Forecasting I am getting the same Error :Allow Forecasting is not allowed for this License Type.
      can you help me on this.

      Reply
    Neeraj
    June 26, 2015 @ 1:46 am

    I got error Invalid field ForCastEnabled for Sobject user

    Reply
      Ian Clancy
      July 2, 2015 @ 11:30 am

      Check the license type you have assigned to your user. Allow Forecasting is not available to certain license types.

      Reply
Gopal
November 14, 2014 @ 11:36 pm

Hi,

When i am running above trigger – I am getting compilation error. Variable does not exist: ForecastEnabled

please help to resolve this.

Reply
    David Liu
    November 15, 2014 @ 3:59 pm

    Make sure you have Forecasting turned on in your org!

    Reply
Seb
November 14, 2014 @ 12:55 am

Hi is was tryed to complete this first simple trigger but even if i copy the code into Salesforce im not able to run the APEX-Test Class. what am i doing wrong?
After running Test i become this Error Message:
Error Message System.DmlException: Insert failed. First exception on row 0; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: []

could you please help me.
Thanks

Reply
    David Liu
    November 14, 2014 @ 6:39 pm

    The problem is because we hard code an ID in the test class, but that ID is different in your own org.

    Check out the comments on the tutorial, you’ll see how a lot of other people solved it!
    https://www.sfdc99.com/2013/05/14/how-to-write-a-test-class/

    Reply
    rahul choudhary
    October 9, 2017 @ 4:02 am

    you make wrong test class pls check your test class again and insertion filed

    Reply
Mike
October 22, 2014 @ 6:40 pm

Hello David, I think I am in a position to get my hands dirty, but can’t come up with multiple meaningful scenarios. So would you be able to help me find some beginner exercises for triggers, controllers etc on standard objects?

Reply
    David Liu
    October 22, 2014 @ 7:17 pm

    Try these!

    Quizzes: https://www.sfdc99.com/beginner-tutorials/
    Challenges: https://www.sfdc99.com/challenges/

    Reply
      Mike
      October 23, 2014 @ 5:41 am

      Oh… sorry I missed to mentioned that I completed both of those sections from this site. I was hoping you could point me to some external resources or perhaps, come up with more on your own.

      Reply
        Mike
        October 23, 2014 @ 7:07 am

        And, it would be best if the problem requires to implement a meaningful business scenario. I will prefer to come up with a solution on my own than fixing bugs in something that you presented. No big deal if you can’t, I was just hoping you would have some already. Wouldn’t be too bad to add to this site: 5 – 10 scenarios each that ask to implement trigger, web services, controllers etc. Something like a mini DEV501 programming assignment.

        Reply
          David Liu
          October 23, 2014 @ 8:18 pm

          I have an unusually difficult time coming up with these scenarios surprisingly =)

          When I do I’ll post em!

          Reply
          David Liu
          October 23, 2014 @ 8:21 pm

          Actually, there seem to be some good scenarios right now on the forums =D

          https://www.sfdc99.com/forums/forum/beginning-apex/

          Reply
nibrahim
August 22, 2014 @ 3:40 am

Hi david,

I am having a triggger in which it assigns an errormessage (if error occured) to the field.
I have used addError method for assigning the error message for field .
But in my code i have called again the addError method for same field to assign the another errormessage .

My question is did it overwrite the first error message assigned to the field.

Or can you please sepecify the method to get the error message assigned for the field in salesforce if available.

Thanks in advance.

Reply
    David Liu
    August 24, 2014 @ 3:03 pm

    You are definitely overwriting the error!

    One thing you can do is create a String variable, add multiple errors to that, then add the single String variable as an error at the end.

    Reply
      Anonymous
      August 24, 2014 @ 10:35 pm

      Thanks David….:)

      Reply
Nirav
July 28, 2014 @ 2:07 am

trigger Archive_OnUserStatus on User (before update, after update)
{

User[] u1 = Trigger.old;

Id feedID = u1[0].Id;

Id id1 = null;

ArchiveAllData CMFD = new ArchiveAllData();

/*
if(Trigger.isBefore)
{
CMFD.filterUserStatus(u1);

}
*/

if(Trigger.isAfter)
{
System.debug(‘After–u1[0].Id–‘+u1[0].Id);
//CMFD.filterUserStatus(u1);
}

}

I have created this trigger but the code coverage for this trigger is 0%, So, can you please tell me how can I cover the trigger. Can you please send me the test method for it.

Reply
    David Liu
    July 29, 2014 @ 9:45 pm

    Creating/updating a User in your test class should at least get you over 0%! Keep trying!

    Reply
Rachel
June 8, 2014 @ 5:57 pm

Hey David,

In an attempt to best learn this, I tried to write the code from scratch. This prompted a few questions:

1. Does “spacing” and line separation ever count in coding?
2. What about capslock?
3. I changed the variable “ForceForecasting” and called it something else. That worked fine but not so for UserinLoop?
4. Why the semi-colon after true?

Thanks a ton for doing this! I hope to make you proud

Reply
    David Liu
    June 8, 2014 @ 8:17 pm

    Great questions!

    Spacing or caps never matters!

    You can change basically anything that’s in purple text however just make sure to find/replace 100% of the matches. You might have forgotten to change one of the other references to userInLoop !

    Semi-colon after every statement =) Don’t worry, you’ll get a better feel for this soon!

    Reply
    William Probyn
    June 10, 2014 @ 1:36 am

    Rachel, to answer you questions:

    1. yes, this is an essential part of coding, it tells the computer what it’s doing and when to do it and it keeps the code nice and tody
    2. you can use capslock as apex isn’t like javascript for example, trigger TEST would be the same as trigger test or trigger TeST
    3. if you changed the variable altogether, the computer won’t recognize the variable because you haven’t told the computer what it is
    4. the semi colon is used to tell the computer where the line of code stops and is used anywhere the curly bracket isn’t used

    Hope this helped!:)

    Reply
      David Liu
      June 10, 2014 @ 6:48 pm

      Thank you sir, WELL SAID!!!

      Reply
Mithun Sapui
May 18, 2014 @ 5:09 pm

Hi David,
Kudos on the great job you are doing. I am signed up for all your Apex programming webinars for the next few weeks.

Meanwhile, I had a question to ask. I am trying to insert a new record in my custom object Trailer. There is a Trailer # field (API name Trailer__c), which is basically a one-up number. In the new record, I want the Trailer # field to be 1 plus the highest Trailer number from the DB (basically next one-up number). How do I achieve this ?

I have started off and reached up till this point. I don’t know how to take the Max Trailer # and assign it to new record’s trailer number. Thanks in advance for your help..

public class TestAddTrailer {
static testMethod void insertNewTrailer() {
Trailer__c TrailerToCreate = new Trailer__c();
List groupedResults = [Select MAX(Trailer__c) from Trailer__c];

Thanks
Mithun

Reply
    David Liu
    May 18, 2014 @ 11:55 pm

    Hey Mithun,

    Why not simply use an auto-number field for this? =)

    Then you can convert the text field into an integer using this method:
    Integer myInt = Integer.valueOf(‘123’);

    David

    Reply
      Anonymous
      May 19, 2014 @ 10:41 am

      :) ..Thanks. Got tunnel-visioned. Worked fine

      Reply
Steven
May 12, 2014 @ 7:28 am

David,

I’m new to Apex. Created a custom object and was able to create, via a trigger, a calendar event and populate all the needed fields in the calendar event. Now I am moving on to updating the previously created calendar event fields when changes are made to the custom object record. Not sure how to find the previously created calendar event … assume I can use much of the original trigger code to update the fields…but not sure where to start or how. Can you provide some guidance or at least point me in the right direction?

Reply
    David Liu
    May 12, 2014 @ 6:37 pm

    Hey Steven,

    If you keep progressing through the chapters you’ll find out exactly how!
    https://www.sfdc99.com/beginner-tutorials/

    Chapter 2 will teach you how to find existing records, and Chapter 3 and 4 will help you integrate them into your trigger =)

    Hope this helps!
    David

    Reply
      Steven
      May 14, 2014 @ 11:36 am

      Yes, the subsequent chapters helped. But now I have different two triggers that each work in isolation: 1) one for a custom object that creates and updates a calendar event and 2) one which updates the customer object fields when the calendar event is updated. The problem appears to be that one trigger (the calendar event) is causing a custom object trigger to also trigger resulting in a recursive issue. Can you point me in the right direction to resolve?

      Reply
        David Liu
        May 15, 2014 @ 2:27 pm

        Many ways to do this but one is to only run your trigger when specific fields are changed to and from specific values. Tull find a post on this in chapter 6!

        Reply
srinivas
April 16, 2014 @ 8:13 am

Nice Explanation….

Reply
Jennifer Fisher
March 24, 2014 @ 6:58 am

Hi David,

Thank you so much for all of your advice. I am new to writing triggers and was wondering if you could give me some insight to my issue. I have been working on activating the trigger below for one of our clients:

trigger Newfield on Event (after insert){
for (Event e: Trigger.old){
event.Description = Event.LAF_Comments__c;
}
}

We keep getting the error message: Error: Compile Error: Expression cannot be assigned at line -1 column -1

LAF_Comments_c is a custom formula field. Can you help me?

Reply
    David Liu
    March 24, 2014 @ 8:34 am

    Hey Jennifer,

    Here are a few tips to help you get along =)

    1. Change it to before insert instead of after insert
    – When to use before vs. after triggers: https://www.sfdc99.com/2014/01/25/use-vs-triggers/

    2. Change it from Trigger.old to Trigger.new
    – Detailed explanation of the trigger format: https://www.sfdc99.com/2013/05/12/an-extended-look-how-to-write-a-simple-apex-trigger/

    3. Change the line from event.Description = Event.LAF_Comments__c to:
    e.Description = e.LAF_Comments__c;
    – How to do loops: https://www.sfdc99.com/2013/10/06/loops-for-and-foreach-loops/

    Hope this helps =)
    David

    Reply
Isa D
March 14, 2014 @ 9:12 am

Hi David

I’m new in apex code, and I need your Help, I need a trigger When my Opportunity StageName==’Closed Won’, but I can’ t resolve this.
When StageName== Closed Won, the number of quantity in opportunity products go decrement the quantity in stock in Product object. How can I do this?
I have write code but don’t work
If you can help me …

trigger stocknumber on Opportunity (before insert, before update) {

for (opportunity a : trigger.new){

if (a.StageName == ‘Closed Won’){

List b = new List(SELECT Id, Quantidade_em_stock__c FROM Product2);
// Opportunity product quantity
//Quantidade_em_stock__c -Quantity;
}
}
insert b;
}

Thank you

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

    Hey Isa,

    This one is definitely possible with the knowledge on this site however it is on the more advanced side!

    Here’s generally how you need to tackle this one:

    1. Detect an opp changing to Closed Won:
    https://www.sfdc99.com/2014/02/25/comparing-old-and-new-values-in-a-trigger/

    2. Get a list of all Opportunity Products on your opps

    3. Get a list of all Products related to the Opportunity Products in #2

    4. For every Opportunity Product in #2, subtract its quantity from the relevant product in #3

    I definitely want to help you here but I recommend you get a strong grasp of the concepts up until chapter 7 before tackling this one!

    David

    Reply
      Isa D
      March 17, 2014 @ 3:49 am

      Hi David,

      I’m sorry but my code not complet, I do copy/paste but some parts of code disapear sorry for that.

      Thanks a lot for the help

      Reply
        David Liu
        March 17, 2014 @ 7:44 pm

        It’s actually my site’s fault =( It reads everything like HTML so it doesn’t play well with these chars: < >

        Reply
Liz K
January 5, 2014 @ 8:25 pm

Why do you think Salesforce is not allowing this standard User field to be updated via workflow? Especially since custom User fields can now be used in a workflow.

Reply
    David Liu
    January 6, 2014 @ 12:32 am

    I think the User object is inherently a different type of object in Salesforce, which is why it took so long for them to allow workflows on it in the first place.

    On one hand, a User record is like any other record in that it has properties like Name, Email, Phone, etc. On the other hand, there’s an entire element of system permissions governed by this object. Although at face value it seems like these permissions are simply properties like Name and Email, I think in the back end it’s a little more complicated than that.

    The “Allow Forecasting” checkbox falls into the latter category of system permissions instead of simple properties, which is why I think it’s not editable via the workflow.

    Either that or it’s just one of those weird things in Salesforce that they just don’t allow, leaving you scratching your head all the time =)

    Reply

Leave a Reply Cancel reply

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


*

*

Theme: Simple Style by Fimply