I am new to Salesforce . I am having a bit of problem wriiting a trigger, any help would be appriciated.

I want to Write a trigger that will set the name of an Opportunity record when it is created and when the fields below are updated. The opportunity name should contain the following, each separated by a space: Account Name,Owner Last Name, Opportunity Close Date.

trigger SetOpportunityName on Opportunity (before insert, before update) {
for (Opportunity op: Trigger.new) {
   op.Name = op.Account.Name+' '+Op.Owner.LastName+' '+op.ClosedDate;
   system.debug('*****************************' + op.Name);    

But I am getting op.Account.Name and Op.Owner.LastName values as null.

I know there is a mistake, Please guide me.

  • This sounds like a good use for Workflows. Is that an option for you?
    – Mike Chale
    Jan 28, 2014 at 20:18
  • No I want to use Trigger :) Jan 28, 2014 at 20:29

3 Answers 3


You need to query for those values since they don't come down natively in the trigger. Anything that is related will be null (like op.Account.Name)

So I would gather up all the account and OwnerIds and then do separate queries outside of the for loop (otherwise you will have other issues), and then loop again to set the values... Also the owner could be a group so this may be tricky :-P

Set<Id> ownerIds = new Set<Id>();
Set<Id> AccountIds = new Set<Id>();
for (Opportunity op : Trigger.new) {

Map<Id, Account> accountMap = new Map<Id, Account>([SELECT Name FROM Account WHERE Id IN :accountIds]);
Map<Id, User> userMap = new Map<Id, User>([SELECT Name, LastName FROM User WHERE Id IN :OwnerIds]);
Map<Id, Group> groupMap = new Map<Id, Group>([SELECT Name FROM Group WHERE Id IN :OwnerIds]);

String sName;
for (Opportunity op : Trigger.new) {

  // add the account name
  sName = accountMap.get(op.AccountId).Name;

  // add either the group or user name
  if (userMap.get(op.OwnerId) != null) {
    sName += ' ' + userMap.get(op.OwnerId).LastName;
  } else if (groupMap.get(op.OwnerId) != null) {
    sName += ' ' + groupMap.get(op.OwnerId).Name;

  // set the name :-)
  op.Name = sName;

There's absolutely nothing wrong with SalesForceGirl's solution, but I don't see the advantage in creating maps when you can just query those fields directly from the opportunity. Simpler is always better imo. You can always refactor later if the need arises.

Obviously this is dependent on whether an owner is always a user:

for (Opportunity op : [select Account.Name, Owner.LastName from Opportunity where Id in :Trigger.new]) {
    Trigger.newMap.get(op.Id).Name = op.Account.Name + ' ' + op.Owner.LastName;

If one knows about Salesforces limits and best coding practices you NEVER write a select statement in a loop.

Always use in memory maps in a trigger.

If you consult for a client that has numerous classes and triggers like that you'll never deploy to production without eventually hitting SOQL limits.

SalesforceGirl is 100% correct in the trigger code but I would go with a workflow where those are all standard objects and accessible. Managers and admins can edit those easily if need be.


You must log in to answer this question.

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