+ Start a Discussion
sourav046sourav046 

Trigger for Roll up summary

I know this is weird I can achieve this using Roll up summary .But what I want is to achieve this using trigger.

 

I want to write a trigger on Account ,which is having a field named Count__c .I want to autopopulate the nos of Contacts associated with that Account .

 

My code is not working thats why seeking help .

Laxman RaoLaxman Rao

Hi Sourav,

 

You cannot create roll-up summary field on Account.

When ever you want to count the number of contacts, You should write a trigger on Contact not on Account.

Below is the code :

 

trigger CountOfChild on Contact (after insert, after update, after delete, after undelete)
{
List<Contact> VLstContact;
set<String> vAccId = new set<String>();

if(trigger.isInsert || trigger.isUndelete || trigger.isdelete)
{
if(!trigger.isdelete)
{
VLstContact = trigger.new;
}
else
{
VLstContact = trigger.old;
}

for(Contact vContact : VLstContact)
{
if(vContact.AccountId != null)
{
vAccId.add(vContact.AccountId);
}
}
}
else
{
if(trigger.isUpdate)
{
for(Contact vNewContact : VLstContact)
{
Contact oldContact = trigger.oldMap.get(vNewContact.Id);
if(vNewContact.AccountId != oldContact.AccountId)
{
if(vNewContact.AccountId != null)
{
vAccId.add(vNewContact.AccountId);
}

if(oldContact.AccountId != null)
{
vAccId.add(oldContact.AccountId);
}
}
}
}
}

List<AggregateResult> vLstAggr = [SELECT count(Id) NoOfContacts,AccountId
FROM Contact
WHERE AccountId In :vAccId
GROUP BY AccountId];
Account vAcccount;
list<Account> vLstAccounts = new list<Account>();
for(AggregateResult vAggr : vLstAggr)
{

System.debug('Account Id'+vAggr.get('AccountId'));
System.debug('AggregateResult valuesare'+vAggr.get('NoOfContacts'));

string accId = (string) vAggr.get('AccountId');
decimal countOfChild = (decimal) vAggr.get('NoOfContacts');

vAcccount = new Account(Id = accId , Count_Of_Contact__c = countOfChild);
vLstAccounts.add(vAcccount);
}

update vLstAccounts;
}

liron169liron169
Note only that the trigger should also work on delete
Laxman RaoLaxman Rao

I have modified the code, now it works for delete and undelete also.

bob_buzzardbob_buzzard

Rather than writing your own, you might want to take a look at Anthony Victorio's generic solution:

 

http://www.anthonyvictorio.com/salesforce/roll-up-summary-utility/

 

I've used this a few times and its a great solution.  Adding another roll up summary is a new trigger with very few lines of code.

Laxman RaoLaxman Rao

Hi Bob,

 

I have used that, Only problem with that solution is if we change the parentId on child, it does not calculate the roll-up on old parent.

 

I mean to say A1 is the account and intitally C1 is the contact for A1.If the change the parent of C1 to A2, then roll-up is not calculated in A1 but it is calculated on A2.

 

Thanks for the generic solution.

LBartonLBarton

Where is the code which works for delete and undelete?

 

 

jennigikijennigiki

LBarton wrote:

Where is the code which works for delete and undelete?

 

 


Hi, Laxman Rao edited their inital response to cover deletes and undeletes. Just look at the second entry in this thread, above, timestamped: 10-18-2012 12:26 AM - edited ‎10-18-2012 01:23 AM

 
Laxman Rao, I am having a problem with this trigger, on update. "execution of AfterUpdate caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.CountOfChild: line 29, column 1"
 
Any ideas? Your assistance is very much appreciated -- this trigger will solve a big problem for me.
lakshman.mattilakshman.matti
Hi Laxman rao,

Can u please post that modified code.


Thanks
Lakshman
Rohit Kumar MalikRohit Kumar Malik
Below is the updated code which is working for all the scenario, Insert, Update Delete, Undelete. Hope this helps
trigger CountOfChild on Contact (after delete, after insert, after undelete, after update) {
    
    List<Contact> VLstContact;
    set<String> vAccId = new set<String>();
    
    if(trigger.isInsert || trigger.isUndelete || trigger.isdelete)
    {
        // Check if this is trigger is fired by inser/undelete/update
        if(!trigger.isdelete)
        {
            VLstContact = trigger.new;
        }
        
        // If this is fired by delete then get the trigger.old.
        else
        {
            VLstContact = trigger.old;
        }
        
        
        for(Contact vContact : VLstContact)
        {
            if(vContact.AccountId != null)
            {
                vAccId.add(vContact.AccountId);
            }
        }
        
        // This is the case when the contact is updated with some info. 
        // There may be the case when already created contact is added to the 
        // Account
    } else {
        if(trigger.isUpdate)
        {
            VLstContact = trigger.new;
            
            for(Contact vNewContact : VLstContact){
                Contact oldContact = trigger.oldMap.get(vNewContact.Id);
                if(vNewContact.AccountId != oldContact.AccountId){
                    if(vNewContact.AccountId != null) {
                        vAccId.add(vNewContact.AccountId);
                    }
    
                }
        
                if(oldContact.AccountId != null){
                    vAccId.add(oldContact.AccountId);
                }
            }
        }
    }
    
    List<AggregateResult> vLstAggr = [SELECT count(Id) NoOfContacts,AccountId FROM Contact
    WHERE AccountId In :vAccId GROUP BY AccountId];


    Account vAcccount;
    list<Account> vLstAccounts = new list<Account>();

    for(AggregateResult vAggr : vLstAggr) {
        System.debug('Account Id'+vAggr.get('AccountId'));
        System.debug('AggregateResult valuesare'+vAggr.get('NoOfContacts'));

        string accId = (string) vAggr.get('AccountId');
        decimal countOfChild = (decimal) vAggr.get('NoOfContacts');

        vAcccount = new Account(Id = accId , Count_Of_Contact__c = countOfChild);
        vLstAccounts.add(vAcccount);
    }

    update vLstAccounts;
}
Cindy Reynolds 6Cindy Reynolds 6
Please help me get past a Compile error. I would be forever grateful! I have struggled far too long on my own and do not understand what other alternative variable name it should be.
My child Object is "Assigned_Contractor__c", while the Lookup Parent Object is the standard "Contact" Object.  
Error: Variable does not exist: ContactId at line 22 column 29
--------------------------------------------------------------------------------------------------------

trigger AssignedContractorTrigger on Assigned_Contractor__c (after insert, after update, after delete, after undelete) {

List <Assigned_Contractor__c> VLstAssignedContractor;
set <String> vContId = new set <string>();

if (trigger.isInsert || trigger.isUndelete || trigger.isDelete)
{
    // Check if this trigger is fired by insert/undellete/update
    if(!trigger.isdelete)
    {
    VLstAssignedContractor = trigger.new;
    }
    
    //IF this is fired by delete then get the trigger.old.
    else
    {
    VLstAssignedContractor = trigger.old;
    }
    
    for(Assigned_Contractor__c vAssignedContractor : VLstAssignedContractor)
    {
     if(vAssignedContractor.ContactId != null)
     {
       vContId.add(vAssignedContractor.ContactId);
       }
     }
     
     //This is the case when the Assigned Contractor is updatred with some info.
     //There may be the case when already created Assigned Contractor is added to the Contact
 } else {
   if(trigger.isUpdate)
   {
      vLstAssignedContractor = trigger.new;
      
      for(Assigned_Contractor vNewAssignedContractor : VLstAssignedContractor){
         Assigned_Contractor__c oldAssignedContractor = trigger.oldMap.get(vNewAssignedContractor.Id);
         if(vNewAssignedContractor.ContactId != oldAssignedContractor.ContactId){
           if(vNewAssignedContractor.ContactId != null) {
              vContId.add(vNewAssignedContractor.ContactId);
            }
       }
       
       if(oldAssignedContractor.ContactId != null){
          vContId.add(oldAssignedContractor.ContactId);
        }
     }
    }
   }
   
   List <AggregateResult> vLstAggr = [SELECT count(id) z, ContactId FROM Assigned_Contractors__c
   WHERE ContactId IN : vContId  GROUP BY ContactId];
   
   Contact vContact;
   list <Contact> vLstContacts = new list <Contact>();
   
   for (AggregateResult vAggr : VLstAggr) {
       System.Debug('Contact id'+vAggr.get('ContactId'));
       System.Debug('AggregateResult values are ' +vAggr.get('z'));
       
       string conId = (string) vAggr.get('ContactId');
       decimal countofChild = (decimal) vAggr.get('z');
       
       vContact = new Contact(id = conId,  FY_Total_Assigned_Contractors_YTD__c = countofChild);
       vLstContacts.add(vContact);
    }
    
    update vLstContacts;
   }                      
       
Priya AdwaniPriya Adwani
trigger CountContactTrigger on Contact (after delete,after update,after insert,after undelete) {
    
    Set<Id> AccIds=new Set<Id>();
    List<Account> AccListtoUpdate=new List<Account>();
    if(Trigger.isInsert||Trigger.isUndelete){
        for(Contact con:Trigger.new)
        {
            AccIds.add(con.AccountId);
        }
    }
    if(Trigger.isUpdate||Trigger.isdelete)
    {
        for(Contact con:Trigger.old)
        {
            AccIds.add(con.AccountId);
        }
    }
    for(Account acc:[Select Id ,Total_Contacts__c,(Select Id from Contacts) from Account where Id IN: AccIds])
    {
        acc.Total_Contacts__c=acc.Contacts.size();
        AccListtoUpdate.add(acc);
    }
    try{
        update AccListtoUpdate;
    }
    catch(Exception e){
        
        System.debug('Exception e'+e.getMessage());
    }
}