function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
LudivineLudivine 

retrieve whatId in trigger

Hi all,

I have a probleme to retrieve WhatId argument in my trigger.
When the triggers is fired on the event and Related To field is different from Opportunity,
I get the following error message on my Event when Related To is an Account :
(It works only When Event is Realted To Opportunity)

"Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger Trigger_Event_Send_Email caused an unexpected exception, contact your administrator: Trigger_Event_Send_Email: execution of BeforeUpdate caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.Trigger_Event_Send_Email: line 41, column 1"


If the Event is Related To an Account, the trigger is always looking for Related To Opportunity
The aim is to keep the WhatId value in a string ( Account, Opportunity, leads...) and print the value in the body of the email,
Could you help me correct my trigger please?
trigger Trigger_Event_Send_Email on Event (before update) {
    Set<Id> ownerIds = new Set<Id>();
    Set<Id> initiatorIds = new Set<Id>();
    Set<Id> OpptyIds = New Set<Id>();
    Set<Id> AccIds = New Set<Id>();

   
    for(Event evt: Trigger.New)
    //Assigned TO
        ownerIds.add(evt.OwnerId);
    Map<Id, User> userMap = new Map<Id,User>([select Name, Email from User where Id in :ownerIds]);
  
    For(Event evt: Trigger.New)
    //Created By
        initiatorIds.add(evt.CreatedById);
    Map<Id, User> userMap2 = new Map<Id,User>([select Name, Email from User where Id in :initiatorIds]);
  
    For(Event evt : Trigger.New)
  //WhatId = Action
        OpptyIds.add(evt.WhatId);
    Map<id, Opportunity> OpptyMap = new Map<Id,Opportunity>([select Name from Opportunity where Id in :OpptyIds]);
    
    For(Event evt : Trigger.New)
  //WhatId = Account
        AccIds.add(evt.WhatId);
    Map<id, Account> AccMap = new Map<Id,Account>([select Name from Account where Id in :AccIds]);
    
    

    for(Event evt : Trigger.New)  {
        User User = userMap2.get(evt.CreatedById);
        User Assignee = userMap.get(evt.ownerId); 
        Opportunity RelatedTo = OpptyMap.get(evt.WhatId);       
        Account RelatedTo2 = AccMap.get(evt.WhatId);       
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {Assignee.Email};
        mail.setToAddresses(toAddresses);    // Set the TO addresses
        mail.setSubject('A visit Report owned by you is due soon');    // Set the subject

      String Whatid ; 
       if (RelatedTo.Name == '')
       whatid = RelatedTo2.Name;
       
       if (RelatedTo2.Name == '')
       whatid = RelatedTo.Name;

        String template = 'Hello {0}, \nThe following Visit Report is due soon:\n';
        
        String duedate = '';       
        template+= '\n';
        template+= 'Due Date - {1}\n';
        template+= 'Type - {2}\n';     
        template+= 'Subject - {3}\n';
        template+= 'Assign To - {4}\n';
        template+= 'Related To - {5}\n';   
        template+= '\n';
        template+='Click on the following link to access the Visit Report:\n';
        template+= '{6}\n';
        
        //String duedate = '';
    If(System.now() == evt.Send_Email_Alert__c )   
         evt.SendEmailAlert__c = True;
        if (evt.EndDateTime ==null)
            duedate = '';
        Else
           duedate = evt.EndDateTime.format();
                  
               List<String> args = new List<String>();

        args.add(Assignee.Name);
        args.add(duedate);
        args.add(evt.type);
        args.add(evt.subject);
        args.add(Assignee.Name);
        args.add(whatid);
        args.add('https://'+System.URL.getSalesforceBaseURL().getHost()+'/'+evt.Id);
        
        // Here's the String.format() call.
        String formattedHtml = String.format(template, args);
       
        mail.setPlainTextBody(formattedHtml);
        Messaging.SendEmail(new Messaging.SingleEmailMessage[] {mail});
     
            
            }
    }
Many thanks!
Best Answer chosen by Ludivine
Pavan Kumar KajaPavan Kumar Kaja
Try below code and let me  its working or not.

trigger Trigger_Event_Send_Email on Event (before update) {
    Set<Id> ownerIds = new Set<Id>();
    Set<Id> initiatorIds = new Set<Id>();
    Set<Id> OpptyIds = New Set<Id>();
    Set<Id> AccIds = New Set<Id>();

   
    for(Event evt: Trigger.New)
    //Assigned TO
        ownerIds.add(evt.OwnerId);
    Map<Id, User> userMap = new Map<Id,User>([select Name, Email from User where Id in :ownerIds]);
  
    For(Event evt: Trigger.New)
    //Created By
        initiatorIds.add(evt.CreatedById);
    Map<Id, User> userMap2 = new Map<Id,User>([select Name, Email from User where Id in :initiatorIds]);
  
    For(Event evt : Trigger.New)
  //WhatId = Action
        OpptyIds.add(evt.WhatId);
    Map<id, Opportunity> OpptyMap = new Map<Id,Opportunity>([select Name from Opportunity where Id in :OpptyIds]);
    
    For(Event evt : Trigger.New)
  //WhatId = Account
        AccIds.add(evt.WhatId);
    Map<id, Account> AccMap = new Map<Id,Account>([select Name from Account where Id in :AccIds]);
    
    

    for(Event evt : Trigger.New)  {
		String Whatid ;
        User User = userMap2.get(evt.CreatedById);
        User Assignee = userMap.get(evt.ownerId); 
		if(OpptyMap.containsKey(evt.whatid)){
			Whatid = OpptyMap.get(evt.WhatId).Name;
		}
		if(AccMap.containsKey(evt.whatid)){
			Whatid = AccMap.get(evt.WhatId).Name;
		}
        // Opportunity RelatedTo = OpptyMap.get(evt.WhatId);       
        // Account RelatedTo2 = AccMap.get(evt.WhatId);       
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {Assignee.Email};
        mail.setToAddresses(toAddresses);    // Set the TO addresses
        mail.setSubject('A visit Report owned by you is due soon');    // Set the subject

       /*
       if (RelatedTo.Name == '')
       whatid = RelatedTo2.Name;
       
       if (RelatedTo2.Name == '')
       whatid = RelatedTo.Name;
		*/
        String template = 'Hello {0}, \nThe following Visit Report is due soon:\n';
        
        String duedate = '';       
        template+= '\n';
        template+= 'Due Date - {1}\n';
        template+= 'Type - {2}\n';     
        template+= 'Subject - {3}\n';
        template+= 'Assign To - {4}\n';
        template+= 'Related To - {5}\n';   
        template+= '\n';
        template+='Click on the following link to access the Visit Report:\n';
        template+= '{6}\n';
        
        //String duedate = '';
    If(System.now() == evt.Send_Email_Alert__c )   
         evt.SendEmailAlert__c = True;
        if (evt.EndDateTime ==null)
            duedate = '';
        Else
           duedate = evt.EndDateTime.format();
                  
               List<String> args = new List<String>();

        args.add(Assignee.Name);
        args.add(duedate);
        args.add(evt.type);
        args.add(evt.subject);
        args.add(Assignee.Name);
        args.add(whatid);
        args.add('https://'+System.URL.getSalesforceBaseURL().getHost()+'/'+evt.Id);
        
        // Here's the String.format() call.
        String formattedHtml = String.format(template, args);
       
        mail.setPlainTextBody(formattedHtml);
        Messaging.SendEmail(new Messaging.SingleEmailMessage[] {mail});
     
            
            }
    }


All Answers

Ramu_SFDCRamu_SFDC
In line 33 and 34 check if the map contains the data for corresponding id's something as below
if(OpptyMap.containskey(evt.WhatId)){
Opportunity RelatedTo = OpptyMap.get(evt.WhatId);
}
 and again before line 41 and 44 add the condition to see if the related to and related to 2 are not null.

if (RelatedTo!=null){
if (RelatedTo.Name == ''){

}
}
This will fix the issue.
Pavan Kumar KajaPavan Kumar Kaja
Try below code and let me  its working or not.

trigger Trigger_Event_Send_Email on Event (before update) {
    Set<Id> ownerIds = new Set<Id>();
    Set<Id> initiatorIds = new Set<Id>();
    Set<Id> OpptyIds = New Set<Id>();
    Set<Id> AccIds = New Set<Id>();

   
    for(Event evt: Trigger.New)
    //Assigned TO
        ownerIds.add(evt.OwnerId);
    Map<Id, User> userMap = new Map<Id,User>([select Name, Email from User where Id in :ownerIds]);
  
    For(Event evt: Trigger.New)
    //Created By
        initiatorIds.add(evt.CreatedById);
    Map<Id, User> userMap2 = new Map<Id,User>([select Name, Email from User where Id in :initiatorIds]);
  
    For(Event evt : Trigger.New)
  //WhatId = Action
        OpptyIds.add(evt.WhatId);
    Map<id, Opportunity> OpptyMap = new Map<Id,Opportunity>([select Name from Opportunity where Id in :OpptyIds]);
    
    For(Event evt : Trigger.New)
  //WhatId = Account
        AccIds.add(evt.WhatId);
    Map<id, Account> AccMap = new Map<Id,Account>([select Name from Account where Id in :AccIds]);
    
    

    for(Event evt : Trigger.New)  {
		String Whatid ;
        User User = userMap2.get(evt.CreatedById);
        User Assignee = userMap.get(evt.ownerId); 
		if(OpptyMap.containsKey(evt.whatid)){
			Whatid = OpptyMap.get(evt.WhatId).Name;
		}
		if(AccMap.containsKey(evt.whatid)){
			Whatid = AccMap.get(evt.WhatId).Name;
		}
        // Opportunity RelatedTo = OpptyMap.get(evt.WhatId);       
        // Account RelatedTo2 = AccMap.get(evt.WhatId);       
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {Assignee.Email};
        mail.setToAddresses(toAddresses);    // Set the TO addresses
        mail.setSubject('A visit Report owned by you is due soon');    // Set the subject

       /*
       if (RelatedTo.Name == '')
       whatid = RelatedTo2.Name;
       
       if (RelatedTo2.Name == '')
       whatid = RelatedTo.Name;
		*/
        String template = 'Hello {0}, \nThe following Visit Report is due soon:\n';
        
        String duedate = '';       
        template+= '\n';
        template+= 'Due Date - {1}\n';
        template+= 'Type - {2}\n';     
        template+= 'Subject - {3}\n';
        template+= 'Assign To - {4}\n';
        template+= 'Related To - {5}\n';   
        template+= '\n';
        template+='Click on the following link to access the Visit Report:\n';
        template+= '{6}\n';
        
        //String duedate = '';
    If(System.now() == evt.Send_Email_Alert__c )   
         evt.SendEmailAlert__c = True;
        if (evt.EndDateTime ==null)
            duedate = '';
        Else
           duedate = evt.EndDateTime.format();
                  
               List<String> args = new List<String>();

        args.add(Assignee.Name);
        args.add(duedate);
        args.add(evt.type);
        args.add(evt.subject);
        args.add(Assignee.Name);
        args.add(whatid);
        args.add('https://'+System.URL.getSalesforceBaseURL().getHost()+'/'+evt.Id);
        
        // Here's the String.format() call.
        String formattedHtml = String.format(template, args);
       
        mail.setPlainTextBody(formattedHtml);
        Messaging.SendEmail(new Messaging.SingleEmailMessage[] {mail});
     
            
            }
    }


This was selected as the best answer
LudivineLudivine
Hi both of you,

Wahhh, Thank you for your quick answers!
It works fine now!!
Now I am going to enhance the trigger with the same logic with the other possible objects in What ID.
Many many thanks to you I have saved a lot of time.

cheers!

Vinit_KumarVinit_Kumar
Isn't that expected as per your code .Your code says :-

Opportunity RelatedTo = OpptyMap.get(evt.WhatId);
If your WhatID is an Opportunity it would return a value else it would return null..

The way I should approach is by checking what is there as WhatId Event,I mean which object is there as WhatId  and then manipulate according to that.so change your code at line 18 to something like below :-

for(Event e:Trigger.new)
    {
        Schema.SObjectType tType= e.whatId.getSObjectType();
//This would only populate AccIds with Account Ids
        if(e.whatId!=null && tType == Account.Schema.SObjectType)
        {
            AccIds.Add(e.whatId);
        }
//This would only populate OpptyIds with Opportunity Ids
else if (e.whatId!=null && tType == Oportunity.Schema.SObjectType)
        {
            OpptyIds.Add(e.whatId);
        }
    }

If this helps,please mark it as best answer to help others :)