You can use the following trigger to count the number of Contact records associated with an account record.
Note:
For existing records, do a one time data load with the count.
Sample Trigger:
trigger ContactCount on Contact (after insert, after update, after delete, after undelete) {
Map < Id, List< Contact > > mapAcctIdContactList = new Map < Id, List < Contact > >();
Map < Id, List< Contact > > mapAcctIdDelContactList = new Map < Id, List < Contact > >();
Set < Id > AcctIds = new Set < Id >();
if ( trigger.isInsert ) {
for(Contact Con : trigger.New) {
if ( String.isNotBlank( Con.AccountId ) ) {
if ( !mapAcctIdContactList.containsKey( Con.AccountId ) ) {
mapAcctIdContactList.put( Con.AccountId, new List < Contact >());
}
mapAcctIdContactList.get( Con.AccountId ).add( Con );
AcctIds.add( Con.AccountId );
}
}
}
if ( trigger.isUpdate ) {
for ( Contact Con : trigger.New ) {
Id oldAcctId = trigger.oldMap.get( Con.Id ).AccountId;
if ( String.isNotBlank ( Con.AccountId ) && Con.AccountId != oldAcctId ) {
if ( !mapAcctIdContactList.containsKey ( Con.AccountId ) ) {
mapAcctIdContactList.put ( Con.AccountId, new List < Contact >() );
}
mapAcctIdContactList.get( Con.AccountId ).add ( Con );
AcctIds.add ( Con.AccountId );
if ( !mapAcctIdDelContactList.containsKey ( oldAcctId ) ){
mapAcctIdDelContactList.put ( oldAcctId, new List < Contact >() );
}
mapAcctIdDelContactList.get( oldAcctId ).add( Con );
AcctIds.add ( oldAcctId );
} else if ( String.isBlank ( Con.AccountId ) && String.isNotBlank( oldAcctId ) ) {
if ( !mapAcctIdDelContactList.containsKey ( oldAcctId ) ){
mapAcctIdDelContactList.put ( oldAcctId, new List < Contact >() );
}
mapAcctIdDelContactList.get( oldAcctId ).add( Con );
AcctIds.add( oldAcctId );
}
}
}
if ( trigger.isUndelete) {
for ( Contact Con : trigger.new ) {
if ( String.isNotBlank( Con.AccountId ) ) {
if ( !mapAcctIdContactList.containsKey( Con.AccountId ) ) {
mapAcctIdContactList.put( Con.AccountId, new List < Contact >() );
}
mapAcctIdContactList.get( Con.AccountId ).add( Con );
AcctIds.add( Con.AccountId );
}
}
}
if ( trigger.isDelete) {
for( Contact Con : trigger.Old ) {
if ( String.isNotBlank( Con.AccountId ) ) {
if ( !mapAcctIdDelContactList.containsKey( Con.AccountId ) ) {
mapAcctIdDelContactList.put( Con.AccountId, new List < Contact >() );
}
mapAcctIdDelContactList.get( Con.AccountId ).add( Con);
AcctIds.add( Con.AccountId );
}
}
}
if ( AcctIds.size() > 0 ) {
List < Account > listAcct = new List < Account >();
listAcct = [ SELECT Id, Number_of_Contacts__c FROM Account WHERE Id IN : AcctIds ];
for ( Account acct : listAcct ) {
Integer noOfConts = 0;
if ( mapAcctIdContactList.containsKey( acct.Id ) ) {
noOfConts += mapAcctIdContactList.get( acct.Id ).size();
}
if ( mapAcctIdDelContactList.containsKey( acct.Id ) ) {
noOfConts -= mapAcctIdDelContactList.get( acct.Id ).size();
}
acct.Number_of_Contacts__c = acct.Number_of_Contacts__c == null ? noOfConts : ( acct.Number_of_Contacts__c + noOfConts );
}
update listAcct;
}
}
Great Job! the code works great 😀 thank you!!!!
this trigger works but during update trigger is not work
Setup debug logs and verify. It worked for me without any issues.
Hai,This code is not Working For Me
It woks fine for me. Check whether the contact has account on it.
Cheers!!!
Hi nice work, but why do we check
if(!AcctContactList.containsKey(Con.AccountId)){
AcctContactList.put(Con.AccountId, new List());
}
since our list of contacts have all account Id?
waiting for your reply.
because we are checking if key is not present in AcctContactList then we are adding to new list if key is present we are adding to same list
Here,AccountId is a custom field in contact object
No.. AccountId is a standard field.
code is working …but why we used if(AcctIds.size() > 0)
Account is not a mandatory field in Contact. So, sometimes the set may be empty. Its why we are checking…
if we not use if condition also the code is working …
in salesforce fields are case sensitve or not ….i used Number_of_Contacts__c in trigger but in field creation i given name as Number_of_contacts__c ..but its working
Hello Guys,,
I need your help… want to know How can I learn and become expert in APEX, Triggers, VF?? I don't have any mentor except internet and u guys. I read some workbooks but not reaching anywhere… just get basic knowledge. but How can be good Salesforce Developer?
I can help you out… mail me your queries @[email protected]…
after writing the above code how to see output?
HI Sai Krishna..I saw your coding format. Its really superb. I have to improve my Coding format.Could help me ?.
Balaji.
HI Sai Krishna..I saw your coding format. Its really superb. I have to improve my Coding format.Could help me ?.
Balaji.
Thanks buddy…Code works great..Thanks a million.
On which object to I create this trigger? Contact or Account?
Ignore my question above. I placed the trigger in contact object and it worked like a charm. Is it possible to have a certain criteria on the contact: If Contact:New_Trial_c=True then trigger the count? Where do I place that filter in the code?
This code is working in sandbox, but in production it fails with 0% code coverage. How do I fix that?
Write test class before moving to production.
Cheers!!!
Do you have a test code for this that you are able to share? I tried one, but they do not work with your code. I do not know how to read code to be able to debug.
Hi refer docs to write test classes.
Thanks!
Hi I'm trying to find number of Contacts for the Account and all of its children in the Account hierarchy.
For example, assume you have an Account hierarchy like this:
• Account A – 2 Contacts
Account A1 – 3 Contacts
Account A1a – 4 Contacts
Account A2 – 5 Contacts
The end result would be:
Account A 2+3+4+5 = 14 Contacts
Account A1 3+4 = 7 Contacts
Account A1a 4 Contacts
Account A2 5 Contacts
Please let me know how we can find the child records and grand child record for an account and find it's contacts
On undelete of contact from recycle bin.. will this contact again get link with same account & will this trigger fire again ?
Hi, I have include After Undelete even too.
Check it!!!
Hi, Thanks for the code, I am new to salesforce and do not know how to test the code, can you please let me know how to run the code and write test cases for this?
Thanks in advance for your help!
Check this for test class – http://www.infallibletechie.com/2014/06/syntax-istest-private-class-classname.html
For removing the account id from contact the trigger doesn't work fine, so please correct it
Correct version:
if(trigger.isUpdate) {
for(Contact Con : trigger.New) {
if(String.isNotBlank(Con.AccountId) && Con.AccountId != trigger.oldMap.get(Con.Id).AccountId) {
if(!mapAcctIdContactList.containsKey(Con.AccountId)){
mapAcctIdContactList.put(Con.AccountId, new List());
}
mapAcctIdContactList.get(Con.AccountId).add(Con);
AcctIds.add(Con.AccountId);
} else if(String.isBlank(Con.AccountId) && String.isNotBlank(trigger.oldMap.get(Con.Id).AccountId)) {
if(!mapAcctIdDelContactList.containsKey(Con.AccountId)){
mapAcctIdDelContactList.put(trigger.oldmap.get(con.id).accountid, new List());
}
mapAcctIdDelContactList.get(trigger.oldmap.get(con.id).accountid).add(Con);
AcctIds.add(trigger.oldMap.get(Con.Id).AccountId);
}
}
}
Thanks!!!
if we change parent of contact even though value of field of account not update. It remains with previous value
I just updated the trigger to handle this scenario. Please try the new code.
Hey, can you please tell me it will work fine for bulk records or not
It will work. But, when you are doing a data migration activity, it is always better to turn off or skip trigger for better performance.
Insert parent records with the count. Insert child records next with triggers turned off.
it's not able to count existing records of Contact object
For existing data, you should do one time data load.
for existing contact records, u can try like this
Trigger contacttrigger on Contact(after insert, after update, after delete){
contacthelper ch = new contacthelper();
if(trigger.isAfter){
if((trigger.isInsert) || (trigger.IsUpdate)){
ch.updateAccount(Trigger.New);
}
if(trigger.IsDelete){
ch.updateAccount(Trigger.Old);
}
}
}
public class ContactHelper{
Set AccountIDs = new Set();
List contactfetchlist = new List();
Map> Accmap = new Map>();
public void updateAccount(List conlist){
// List contactfetchlist = [select id, AccountId from COntact where AccountId !=null];
for(Contact c: conlist){
if(String.IsNotBlank(c.AccountId)){
AccountIDs.add(c.AccountId);
}
}
List Acclist = [select id, Numberofcontacts__c, (select id from Contacts) From Account where Id in : AccountIDs ]; // parent Account field
system.debug(Acclist);
for(Account Ac : Acclist){
Accmap.put(Ac.id, Ac.contacts);
system.debug(Accmap);
}
List Accountlistupdate = new List();
Integer noOfConts = 0;
for(Account Acc : Acclist){
system.debug(Accmap.get(Acc.id).size());
Acc.Numberofcontacts__c = Accmap.get(Acc.id).size();
Accountlistupdate.add(Acc);
}
update Accountlistupdate;
}
}
thank for the code, it worked for me.