I'm writing a trigger to create a new Event on update of Opportunity. There are some required fields and others are optional in the form that the user submits. I'm trying to determine a good way to filter for fields that don't contain any data when creating the new events. The trigger operates on a check box custom Opportunity object field that gets set when the opportunity is submitted/updated which tells the trigger to create the event.

If possible, I'd prefer not to have a series of nested if statements to test each field for data. Only about 40% of the possible fields are required or locked into the form the user submits.

trigger ScheduleAmbassadorEvent on Opportunity (after update) {

/* Get Opp IDs being processed by trigger where box is checked for opps After Update */

Integer s = [SELECT Count() FROM Opportunity WHERE Id IN :Trigger.new AND Opportunity.Schedule_Ambassador__c = true];

   If (s != 0) {

list <opportunity> NwEvnt = [SELECT Id, Name, Description, CloseDate, LeadSource, CreatedDate, Account_Address__c, Recap_Type__c, Event_Start_Time__c, Event_Info__c, Schedule_Ambassador__c, Planned_Mintues__c, ECAL_c__c, Campaign.Name, Owner.Name, Program_PO__r.Name, SWS_Recomended_CE__r.Name, SWS_Recomended_CE__r.Phone, SWS_Recomended_CE__r.Email, Customer_Contact__r.Name, Customer_Contact__r.Phone, Customer_Contact__r.Email FROM Opportunity WHERE Id IN :Trigger.new AND Schedule_Ambassador__c = true]; 

From here, I can either create a huge multitude of maps, or I can begin building the list of Events using the required information, then later add the optional information. Once I'm done, I'll be resetting the Schedule_Ambassor__c field to false so it won't trip the trigger again unless a another opportunity on the acct requires a new event to be created.

I've seen the following code which I'll admit I don't fully understand. Consequently I've wondered how I could apply it to what I have above.

String queryString = 'SELECT Id, Name, ' + 
       '(SELECT FirstName, LastName FROM Contacts LIMIT 1) FROM Account';
SObject[] queryParentObject = Database.query(queryString);

for (SObject parentRecord : queryParentObject){ 
Object ParentFieldValue = parentRecord.get('Name'); 
// Prevent a null relationship from being accessed
SObject[] childRecordsFromParent = parentRecord.getSObjects('Contacts');
if (childRecordsFromParent != null) {
    for (SObject childRecord : childRecordsFromParent){ 
        Object ChildFieldValue1 = childRecord.get('FirstName'); 
        Object ChildFieldValue2 = childRecord.get('LastName'); 
        System.debug('Account Name: ' + ParentFieldValue + 
        '. Contact Name: '+ ChildFieldValue1 + ' ' + ChildFieldValue2);

I'm not accessing a record from a parent, thus part of why it confuses me. I am however accessing related lists. Regardless, it seems that the same concept should work to determine whether or not a record is null. If it's not then add it to the list. Once an Event record was populated, I presume I could then insert it and later do a query to run a system assert for validation that each one was properly inserted into the database; something I've never had to do before in a trigger. I've seen code that would look like this:

Event[] event = new Event[]{};

for (list<Opportunity> e : NwEvnt) {
Event event = new Event(Owner = 'e.Owner.Name' + ',' + 'e.ECAL_c__c'), Start = e.Event_Start_Time__c,  ActivityDate = e.CloseDate, Description = e.Description, DurationInMinutes = e.Planned_Minutes__c, Location = e.Event_Info__c, Who = e.Customer_Contact__c, Phone = e.Customer_Contact__r.Phone, Start = e.Event_Start_Time__c, IsVisibleInSelfService = true, CreatedBy = e.Owner.Name, Subject='EventAssignment');

/* my thought was to add the required fields first, and then use If statements to add the optional fields to each new event once I determined whether or not it was null if I couldn't come up with some kind of SObject describe method to determine whether or not a field was null. If I could, it would be inserted here before continuing. */


try {
    insert Event;
    } catch (DmlException e) {

Am I on the right track with this final part? Any suggestions for improvement would be appreciated. Thanks!

  • Why do you need to check if the fields are null? I assume those opportunity fields are just being mapped to the event but if they are null won't the event just have a null value in the field. I.E. where is the nullpointer exception coming from? Commented Jan 16, 2013 at 19:19
  • I think you are on the right track with respect to using if statements for optional fields. Couldn't figure what did you want from the "sample" code though :)
    – Sai
    Commented Jan 16, 2013 at 19:22
  • crmprogdev -- I happened upon this OP after independently arriving at something you observed without much comment, then discovered your post -= see salesforce.stackexchange.com/a/104709/2602
    – cropredy
    Commented Jan 9, 2016 at 1:43
  • Interesting. 3 Yrs after asking it and someone finally truly understood my question! LOL! Figures that it would take a Wolverine to do it. ;) Can't tell you how many try-catch blocks that trigger ultimately wound up with. Developed a complete error handler to process all of the data issues it captured when data was loaded via batch.
    – crmprogdev
    Commented Jan 9, 2016 at 15:15

1 Answer 1


There are a couple of other issues with your trigger. If all you want to do is create an event based on the opportunity fields when this box is checked then the following should work.

trigger ScheduleAmbassadorEvent on Opportunity (after update)
    //Note: You don't need to do any soql queries since trigger.new already has the opportunities.
    list<Opportunity> NwEvnt = new list<Opportunity>();
    for(Opportunity opp: trigger.new) 
        if(opp.Schedule_Ambassador__c) nwEvnt.add(opp);

    list<Event> ToInsert = new list<Event>();
    for(Opportunity opp : newEvnt)
        Event e = New Event(//was this meant to be Name? Ownerid is a lookup field to user so it wouldn't normally have text in there.
                            //Owner = opp.Owner.Name + ',' + opp.ECAL_c__c, 
                            Start = opp.Event_Start_Time__c,  
                            ActivityDate = opp.CloseDate, 
                            Description = opp.Description, 
                            DurationInMinutes = opp.Planned_Minutes__c, 
                            Location = opp.Event_Info__c, 
                            Who = opp.Customer_Contact__c, 
                            Phone = opp.Customer_Contact__r.Phone, 
                            Start = opp.Event_Start_Time__c, 
                            IsVisibleInSelfService = true, 
                            //I think you want to set ownerID as createdBy is a system field and cannot normally be set.
                            //CreatedBy = opp.Owner.Name, 
                            OwnerID = opp.OwnerID,

    if(ToInsert.IsEmpty() == false)
        /**using database.insert allows you to do a partial success so if some of the events fail because of missing required fields or something else it will still go through (assuming this is what you want). You can then handle the errors in the saveresult any way you want, debugging them to the log, sending yourself an email, etc.
        list<Database.SaveResult> InsertResults = Database.Insert(ToInsert,false);
  • I'm not getting a null exception (yet), but know it often happens when accessing fields with null data, so was trying to prevent it from happening. By def, in this org, Event.Owner = (User, ECAL_c__c). Should I use the ID or the Opp Owner's Name (also the Event Owner)? Have assumed they want to see the name. Since trigger is creating the Event, don't I need to set CreatedBy to the owner of the Event? This is where my lack of experience with this kind of programming really shows. Glad to know the database insert allows partial success! Learn something new every day. :)
    – crmprogdev
    Commented Jan 16, 2013 at 20:20
  • You'll only get a null exception if you try and do null.somemethod. So if the opportunity was null you would get a null pointer exception but not if it was just one of the fields. Event.Owner is a lookup so it is always populated with the ID (foreign key) even though it shows a name. CreatedBy is filled in automatically with the running user (whoever kicked off the trigger). Commented Jan 16, 2013 at 22:48

You must log in to answer this question.

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