Create and Populate a Map<Id, Sobject> Without Loops
There are many reasons to use Maps in Apex triggers. Sometimes I want to make a List of Contacts, but I want to pull each one by its ID. This is a good reason to abandon the List and to make a Map<id, Contact>. (Some will prefer to use Map<string, Contact>, and that is okay too.)
This is how I used to populate a Map<id , Contact> of all Contacts at Accounts in a trigger:
Map<Id, Contact> cs = new Map<Id, Contact>();
for ( Contact c : [SELECT id FROM Contact WHERE accountid IN :trigger.newMap.keyset()])
{
cs.put(c.id, c);
}
This takes time and uses script statements, and in a big org/app, we want to minimize both.
Here’s my new way:
Map<Id, Contact> cs = new Map<Id, Contact>(
[select id FROM Contact WHERE accountid IN :trigger.newMap.keyset()]
);
It’s pretty simple, and it works well. It also keeps code clean.
More astute readers will note that this is similar to the Trigger context variables trigger.oldMap & trigger.newMap, which populate a map of the trigger records keyed to their record ids.
Workflow ISCHANGED() translated to Apex trigger
Workflow is great. I can simply and declaratively make changes, and can easily update things like email templates, criteria, tasks, etc. without using Eclipse and writing/running unit tests.
Sometimes, however, workflow isn’t enough; we need to use a trigger.
Today, I had a use-case that when a DateTime field is filled, a contact (identified via a lookup on a parent object – so a grandparent record) should receive a notification. That’s easy enough to do with a ISCHANGED(DateTimeField__c) workflow criteron, but the Email Alert can’t “find” the contact. A trigger is necessary.
Here’s how I coded the trigger:
trigger InterviewUpdates on Interview__c (after update, before update) {
if(Trigger.IsBefore){
for(Interview__c i : Trigger.New){
DateTime dt = i.Date_and_Time__c;
if(Trigger.oldMap.get(i.id).Date_and_Time__c != dt){
// Send email to applicant, passing Interview, DateTime, and Contact
// (which we found via a query coded outside the loop to avoid governor limits)
}
}
}
}
I’ve left out a lot of parts here, but I hope that the main bit of using Trigger.oldMap to find the old value and compare it to the new one comes through.
Happy coding!
Best Practice: Multiple Chatter Posts of the Same File
Filed under: Configuration, Native Application, Salesforce CRM, Tips and Tricks
Salesforce Administrators learn to remind users: “Search before you create a new lead.” Pretty simple, right? Duplicated records are a pain.
Then why do I see some very accomplished Salesforce users in the Dreamforce app posting duplicate Content/Files in Chatter?
Here are some examples from the Files tab:
The better thing to do – assuming that you need to post the same file multiple times (this should be rare, as it might be considered Chatter Spamming, but when referring multiple users or groups to a document, it can come in handy) is to upload the file ONCE and use references to it in subsequent feed posts.
This has a bonus: Better maintenance! Instead of other users not knowing which file to follow if they want to be notified anytime that file is updated, just ensure that there is only ONE copy in the org, and everyone can follow that. This is especially useful for legal documents, employee handbooks, FAQs, Dreamforce App Codes of Conduct… you get the idea.
Not sure how it’s done? Here are a few screenshots:
And there you have it! Go forth and attach! … and after that, just link.
Next Birthday Formula
How would you display your Contacts with upcoming birthdays? I’ve seen people use “Birthdays This Week,” “Birthdays This and Next Week,” and other reports to display the list.
I’ve also seen requirements for showing a person’s next birthday, to trigger an automatic email to each Contact on his/her birthday. Let’s see how it’s done:
if(
Month (Birthdate) < = Month(Datevalue( NOW() ) ),
if ( Month (Birthdate) < Month(Datevalue( NOW() ) ),
DATE( YEAR( DATEVALUE( NOW() ) ) + 1 , MONTH( Birthdate ) , DAY( Birthdate ) ),
if ( Day (Birthdate) < Day ( Datevalue ( NOW() ) ),
DATE( YEAR( DATEVALUE( NOW() ) ) + 1 , MONTH( Birthdate ) , DAY( Birthdate ) ),
DATE( YEAR( DATEVALUE( NOW() ) ) , MONTH( Birthdate ) , DAY( Birthdate ) )
)
),
DATE( YEAR( DATEVALUE( NOW() ) ) , MONTH( Birthdate ) , DAY( Birthdate ) )
)
Next, use Batch Apex to send an email daily to all people where Next_Birthday__c == date.today(). Easy!
Now we can put this into a report and a dashboard showing the next “n” birthdays. Sure, it’s possible that more than n people will have a birthday on a given day, but at least you know that the emails will go out to each of them! If you want to see everyone with birthdays in a certain range, make a custom report and click through from a dashboard or a custom link.
Enjoy!










