I've been searching for hours and haven't found a good example of how to do this...

I would like to send an email whenever a custom object updated; I would like the body of the email to contain only the values of the updated fields.

trigger eventUpdateTrigger on Event__c (after update) {

    //pseudo code
    for(each field in Trigger.new) {
        if(Trigger.new.value != Trigger.old.value) {
            emailBody = Field.Name + ' changed from ' + Trigger.old.value + ' to ' + Trigger.new.value;
    SendEmailTo('[email protected]', emailBody);

How do I compare the value of each Trigger.new with value Trigger.old?

Thank you in advance!

1 Answer 1


You'll need to have a look at "describe calls" - set of methods that let us learn at runtime what fields are on given object. The topic is pretty long so it might take you a while to go through it all and understand it...

In your case a good starting point would be something like this:

Map<String, Schema.SObjectField> describeResult = Schema.SObjectType.Event__c.fields.getMap();
Set<String> allFieldNames = describeResult.keySet();

This should give you set with all field API names (the other part - Schema.SObjectField we skip for now). The next trick is that you can fetch field values dynamically:

Event__c e = new Event__c(Name = 'Something');
System.debug(e.Name == (String) e.get('Name'));

So you could loop through trigger.new and trigger.old comparing all fields by fetching their values with get(String fieldName) method.

There's more to it because you'll realize that sometimes data renders ugly:

  • date fields cast to string look so-so out of the box;
  • lookup fields will report that value changed from one Id to another - not too user-friendly);
  • picklists will always be in English (or whatever is your org's default language) while user would like to see the email in French.
  • etc.

Around this time you'll have to consider looking at the other piece of the equation, the Schema.SObjectField we got in the map. And get back to reading how we can use this to learn more about the field type (is it Date/lookup/picklist; if lookup - where to get the Name value; if picklist - what would the localized label be)...

If your object is small (less than 20 fields or you can convince SF support to increase the limit) - maybe simply set field history tracking on every field ;) It'll also require some tricks (@future maybe because these don't get written until the commit) but might be less hassle...

  • Thank you! I'm fairly new to SF and I'm stumbling my way around. I thought it would have been an easy task to email changes made to one record after it's updated. In either case, you have given me direction where to go start and continue learning. Unfortunately my object is fairly large (larger than 100 fields :/ so tracking isn't really an option) Dec 11, 2013 at 6:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .