+ 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?