+ Start a Discussion
Gita09Gita09 

Trigger to count number of contacts associated with an account

Hi All,

I want to display number of contacts associated with an account using triggers.

for this I had created a lookup field like noofcontacts__c in account  object. and Wrote code as

trigger numberofcontacts on contact(after insert, after update, after delete) {
    Map<Id, List<Contact>> AcctContactList = new Map<Id, List<Contact>>();
    Set<Id> AcctIds = new Set<Id>();   
    List<schema.Account> AcctList = new List<schema.Account>();
    List<schema.Contact> ConList = new List<schema.Contact>();
   
    if(trigger.isInsert || trigger.isUPdate) {
        for(Contact Con : trigger.New) {
            if(String.isNotBlank(Con.AccountId)){
                AcctIds.add(Con.AccountId); 
            }  
        } 
    }
   
    if(trigger.isDelete) {
        for(Contact Con : trigger.Old) {
            AcctIds.add(Con.AccountId);    
        } 
    }          
   
    if(AcctIds.size() > 0){
        ConList = [SELECT Id, AccountId FROM Contact WHERE AccountId IN : AcctIds];
       
        for(Contact Con : ConList) {
            if(!AcctContactList.containsKey(Con.AccountId)){
                AcctContactList.put(Con.AccountId, new List<Contact>());
            }
            AcctContactList.get(Con.AccountId).add(Con);     
        }                          
      
           
        AcctList = [SELECT noofContacts__c FROM Account WHERE Id IN : AcctIds];
        for(Account Acc : AcctList) {
            List<schema.Contact> ContList = new List<schema.Contact>();
            ContList = AcctContactList.get(Acc.Id);
            Acc.Number_of_Contacts__c = ContList.size();
        }   
       
      
        update AcctList;   
    }

}
 I am   getting an error as "Variable doesnot exist:id".

Kindly support and suggest.

Thanks
Jen BennettJen Bennett
It's easier to read the code if you use the <> and paste code in there, then you can also refer to the line in the code the error is pointing to. There is a blog post out there that might help you out:
http://www.infallibletechie.com/2013/09/trigger-to-count-number-of-contacts.html
Gita09Gita09
Hi,

Thank you for response.

With the help of this link only,we wrote that code.

Iam getting same error now.

Kindly suggest and support.









Peter_sfdcPeter_sfdc
There are a couple of things I would do differently. But the main thing I would suggest is using an aggregate SOQL query to count the child contacts. See comments below: 
trigger ContactTrigger on Contact (after insert, after update, after delete, after undelete) {
    //---> above handling all states which could see a contact added to or removed from an account
   
    //---> on delete we use Trigger.Old, all else, Trigger.new
    List<Contact> contacts = Trigger.isDelete ? Trigger.old : Trigger.new;

    //---> the Set class rocks for finding the unique values in a list
    Set<Id> acctIds = new Set<Id>();
   
    for (Contact c : contacts) {
     //yes, you can have a contact without an account
        if (c.AccountId != null) {
            acctIds.add(c.AccountId);
        }
    }
   
    List<Account> acctsToRollup = new List<Account>();
    
    //****** Here is the Aggregate query...don't count in loops, let the DB do it for you*****
    for (AggregateResult ar : [SELECT AccountId AcctId, Count(id) ContactCount 
                               FROM Contact 
                               WHERE AccountId in: acctIds 
                               GROUP BY AccountId]){
        Account a = new Account();
        a.Id = (Id) ar.get('AcctId'); //---> handy trick for updates, set the id and update
        a.Contact_Count__c = (Integer) ar.get('ContactCount');
        acctsToRollup.add(a);
    }
    
    //----> probably you'll want to do a little more error handling than this...but this should work. 
    update acctsToRollup;

}

Maps are super useful, but in this instance (always increment/decrement according to changes in child) you can't beat a simple aggregate SOQL query. 



Ravi NarayananRavi Narayanan
trigger updateAccount on Account (before Update) {

List<Contact> Contactlist=[select id,name,phone,accountid from contact where accountID In :trigger.new ];
map<id,integer> countMap=new map<id,integer>();
integer i=1;
for(contact c:contactlist)
{
       if(countmap.containskey(c.accountid))
       {
           i=countmap.get(c.accountid)+1;
           countmap.put(c.accountid,i);
       }
       else
       {
              countMap.put(c.accountid,i);
       }
}

for(account a:trigger.new)
{
try{
        if(countmap.containskey(a.id))
            a.Contact_Count__c=countMap.get(a.id);
   }
   catch(exception e)
   {
  
   }
}
}
Jen BennettJen Bennett
Try adding the ID to your SELECT statement here:
AcctList = [SELECT noofContacts__c FROM Account WHERE Id IN : AcctIds];
Peter_sfdcPeter_sfdc
ID should be implicitly retrieved in SOQL queries that occur in Apex. But it would be good to check that out. 
Gita09Gita09
Hi Peter,

Thank you for response.

I had used your logic.But,I am getting same error as" Variable doesnot exist :id"

Awaiting for your response.

KbhaskarKbhaskar
hi,
the below code works well for me.
trigger noofcontacts on Contact (after insert,after delete) {


set<id>accid=new set<id>();

list<contact>contactlist=new list<contact>();
list<contact>listcon=new list<contact>();
list<account>acclist=new list<account>();
list<account>listacc=new list<account>();
map<id,integer>mapCount=new map<id,integer>();


if(trigger.isinsert)                              //insert   con
{
for(contact con:trigger.new)
{
accid.add(con.accountid);
}
}

if (trigger.isdelete)                          //delete  con
{
for(contact con:trigger.old)
{
accid.add(con.accountid);
}
}

acclist=[SELECT id,name FROM account WHERE id in:accid];
contactlist=[SELECT id,name,accountid FROM contact WHERE accountid in:accid];

for(account acc:acclist){
listcon.clear();
for(contact c:contactlist){
if(c.accountid==acc.id){
listcon.add(c);

mapCount.put(c.accountid,listcon.size());
}
}
}

if(acclist.size()>0){

for(Account a:acclist)
{
if(mapCount.get(a.id)==null)
a.No_of_Contact__c =0;

else

a.No_of_Contact__c =mapCount.get(a.id);
listacc.add(a);
}
}


if(listacc.size()>0)

update listacc;
}
User-added image 

 
Angela Toedtman 6Angela Toedtman 6
Kbhaskar would you happen to have a test class for this you can share?  Please?
Gowrishankar SubramanianGowrishankar Subramanian
A slightly modified version of Kbhaskar's code above. Uses inner query instead of multiple SELECT queries. 
 
trigger FindContactsCount on Contact (after insert, after update, after delete) {
    
   List<Contact> modContacts = Trigger.isDelete ? Trigger.old:Trigger.new;
    Set<Id> accIds  = new Set<Id>();
    for (Contact c: modContacts)  {
        accIds.add(c.AccountId);
    }
   List<Account> modAccounts = [Select Name, (Select Id from Contacts)  from Account WHERE Id in: accIds ];

    for (Account a: modAccounts) {
       List<Contact> s = a.Contacts;
       System.debug('Account:' + a.Name + ' No. of Contacts: '+ s.size()); 
       a.No_of_Contacts__c = s.size();
    }
}




User-added image
Pathan SPathan S
Any one post through workflow to count number of contacts associated with an account in salesforce?
Akanksha sharma 15Akanksha sharma 15
hi all,
As we have count total no of account associated with account .But i want to update the field when there is reparenting (Suppose i have created c1 on account a1 so  count is 1 but i do some change i changed the account from a1 to a2 on same contact c1 and then after saved it i am getting the same count on count field so anyone can can suggest how can i achieve this?
 
Sagar MauryaSagar Maurya
Hi @akanksha,

Please find below code that will cover all the scenarios-

trigger ContactTrigger on Contact(after insert,after update, after delete){
if(trigger.isAfter){
        Map<Id, Account> accounts = new Map<Id, Account>();
        
        for(Contact con : Trigger.isdelete? Trigger.old: Trigger.new){
             accounts.put(con.AccountId, new Account(Id=con.AccountId,NoOfContacts__c=0));
            if(trigger.isUpdate){                
                for(Contact co: trigger.Old){
                    if(co.AccountId!=con.AccountId){
                        accounts.put(co.AccountId, new Account(Id=co.AccountId,NoOfContacts__c=0));
                    }
                }
            }
        }
        
        for(AggregateResult result : [Select count(id) cou, AccountId Account From Contact Where AccountId IN : accounts.keySet() Group By AccountId]){
            accounts.put((Id)result.get('Account'), new Account(Id = (Id)result.get('Account'), NoOfContacts__c = Integer)result.get('cou')));
        }        
        update accounts.values();
    }
}

Hope the above code helps.

Thanks.
Rupesh BRupesh B
trigger CountofCNTonAccount on Contact (after insert,after delete) {
    if (trigger.isInsert && trigger.isAfter){
        Account acc = new Account();
        acc=[select id,NumberofLocations__c	from account where id=:trigger.new[0].accountId];
        list<contact> contsize = new list<contact>();
        contsize = [ select id,lastname from contact where accountId = :trigger.new[0].accountId];
        acc.NumberofLocations__c = contsize.size();
        update acc;
    }
    if(trigger.IsDelete && trigger.isAfter){
        Account acc = new Account();
        acc=[select id,NumberofLocations__c	from account where id=:trigger.old[0].accountId];
        list<contact> contsize = new list<contact>();
        contsize = [ select id,lastname from contact where accountId = :trigger.old[0].accountId];
        acc.NumberofLocations__c = contsize.size();
        update acc;
        
    }    
}

NumberofLocations__c  is the Count of the number of contacts associated with the account.
Hope this code helps you!!
Thanks.
ASIF ALIASIF ALI
This is very Simple , And Working fine;

trigger countContacts on Contact (after insert, after update, after delete) 
{
    list<contact> conList = new list<contact>();
    list<account> accList = new list<account>();
    set<ID> accIDs = new set<ID>();
    if(trigger.isInsert || trigger.isUpdate)
    {
        for(contact con : trigger.new)
        {
            if(String.isNotBlank(con.accountId))
            {
                accIds.add(con.accountId);
            }
        }
    }
    if(trigger.isDelete)
    {
        for(contact con : trigger.old)
        {
            accIDs.add(con.AccountId);
        }
    }
    if(accIDs.size()>0)
    {
        conList = [select name, id, accountId from contact where accountId IN:accIDs];
        accList = [select name, id , number_of_contacts__c from account where ID IN:accIDs];
    }
    for(account acc : accList)
    {
       acc.Number_of_contacts__c = conList.size();
    }
    update accList;

}
Mahesh Shimpi 4Mahesh Shimpi 4
How to test this?
 
Rohit KumawatRohit Kumawat
Hi @Mahesh Shimpi 4,

First you have to create one custom field, which you have used in your trigger for example field name as 'Number of Contacts' in the Account object.
After creating the custom field, just open any account record.
And in related contact list just create new contacts for that perticular account record.
once contacts are created or updated the account record also will be updated due to trigger  and the number of contacts asscoiated with the account in the contact related list . the total number of count of contacts in the list will show as the value of that account field 'Number of contacts'

for example:
Yoy have created 3 contacts asccoiated with an account record

so the value of the custom field in account object record aslo Number of contact = 3 .
Tharun Kumar 22Tharun Kumar 22
Hello 100% working, which works on insert, update and delete
ContactTrigger :
trigger Count_No_Contacts on Contact (before insert, after insert, after update, after delete) {
    ContactHandler handler = new ContactHandler();
    if(Trigger.isAfter && Trigger.isInsert){
        handler.countContacts(Trigger.new); }
    
    if(Trigger.isAfter && Trigger.isUpdate)  {
        handler.countContacts(Trigger.new);    }
    
    if(Trigger.isAfter && Trigger.isDelete)    {
        handler.countContacts(Trigger.old);    }
}
============================================
public class ContactHandler 
{
    List<Account> accountList = new List<Account>();
    List<Account> accountListUpdated = new List<Account>();
    public void countContacts(List<Contact> newList)   {
        for (Contact con : newList)  {
            system.debug('ContactsAccountID'+con.AccountId);
            accountList = [SELECT Id,Name,TrailApp_DonTes__Number_of_Contacts__c, (SELECT Id, Name FROM Contacts) 
                           FROM Account WHERE Id =: con.AccountId];
        }
        for (Account acc : accountList)  {
            acc.TrailApp_DonTes__Number_of_Contacts__c = acc.Contacts.size() ;
            accountListUpdated.add(acc);
        }
        update accountListUpdated;
    }
}
 
niranjan gaddam 6niranjan gaddam 6
trigger Nofcontacts on Contact (after insert,after update,after delete) {
set<id> accid=new set<id>();
    list<Account> accUpdate=new list<Account>();
    
    for(contact con:trigger.new){
        accid.add(con.accountid);
        
    }
    
    for(Account acc : [select id,no_of_contact__c,(select id from contacts) from account where id in :accid]){
         
       
            acc.no_of_contact__c=acc.contacts.size();
             accUpdate.add(acc);
         
    }
    update accUpdate;
}
kushagra gupta 23kushagra gupta 23
can someon explain why I am getting Variable does not exist: accountid at line 35 column 42? while I am trying to  write a program
Tharun Kumar 22Tharun Kumar 22
Hi 
@kushagra can u paste ur code, where u r getting the error
 
trigger Count_No_Contacts on Contact ( after insert, after update, after delete) 
{
    ContactHandler handler = new ContactHandler();
    if(Trigger.isAfter && Trigger.isInsert){
        handler.countContacts(Trigger.new); }
    
    if(Trigger.isAfter && Trigger.isUpdate)  {
        handler.countContacts(Trigger.new);    }
    
    if(Trigger.isAfter && Trigger.isDelete)    {
        handler.countContacts(Trigger.old);    }
}


public class ContactHandler 
{
    List<Account> accountList = new List<Account>();
    List<Account> accountListUpdated = new List<Account>();
    public void countContacts(List<Contact> newList)   {
        for (Contact con : newList)  {
            system.debug('ContactsAccountID'+con.AccountId);
            accountList = [SELECT Id,Name,TrailApp_DonTes__Number_of_Contacts__c, (SELECT Id, Name FROM Contacts) 
                           FROM Account WHERE Id =: con.AccountId];
        }
        for (Account acc : accountList)  {
            acc.TrailApp_DonTes__Number_of_Contacts__c = acc.Contacts.size() ;
            accountListUpdated.add(acc);
        }
        update accountListUpdated;
    }
}


 
pradeep Arukalapradeep Arukala

@Tharun kumar 22

your code works for single records.. can u please execute by entering 2 contacts with 2 Accounts on one go like below 

 

List<Contact> cons = new List<Contact>();
contact con = new contact();
con.lastName = 'Test1';
con.AccountId ='0012w000002rWuRAAU';
cons.add(con);

contact cond= new contact();
cond.lastName = 'Test2';
cond.AccountId= 'AccountId1';
cons.add(cond);
contact cone= new contact();
cone.lastName = 'Test4';
cone.AccountId= 'AccountId2';
cons.add(cone);

insert cons;


 

 

 

 

sagar077sagar077
Hello, Please me on this requirement.

Count Account with Different Industry(on account picklist fields is there)(e,g. For Industry Electronics we have 3 Accounts) using Map.

plz help me i am new in apex collection.
sagar077sagar077
Create an Apex Trigger that will count the number of contacts associated with an account(create a field at account level). Must update the count in insertion and deletion of a contact.

CODE-

trigger CountonAccountofcontact on Contact (after insert,after delete)
{
    Set<Id> mysetid = new Set <Id>();
        if(Trigger.isinsert)
        {
            System.debug('Insert new contact for trigger.new '+ Trigger.new);
            for(Contact contac :trigger.new)
                {
                    mysetid.add(contac.Accountid);
                }
            List<Account> Acc = [Select Id,Number_Of_Contact_Count__c from Account where Id in : mysetid];
            List<Contact> Con = [Select Id from Contact where Accountid in : mysetid];
            for(Account A: Acc)
                {
                    A.Number_Of_Contact_Count__c = Con.size(); 
                }
            update Acc;
            System.debug('Number of count is ' + Acc);
        }

     if(Trigger.isdelete)
        {
            System.debug('The Delete Contact Name For Trigger.old'+ Trigger.Old); 
            for(Contact contac : Trigger.Old)
                {
                    mysetid.add(contac.Accountid);
                }          
            List<Account> Acc = [Select id,Number_Of_Contact_Count__c from Account where id in: mysetid];
            List<Contact> Con = [Select id from Contact where Accountid in : mysetid];
           
            for(Account A :Acc)
                {
                    A.Number_Of_Contact_Count__c = Con.size();
                }
                update Acc;
            System.debug('The Update number is '+ Acc);
        }
    }

NOTE- This code is running but I want for After Update event also and Plz Help me in that