I have a requirement where I need to show contacts based on Account hierarchy on Account layout.

For example : The below is 3 level one,but we can have up to 5 levels

 **Grand Parent** - See All contacts of [Grand Parent/Parent1/parent2/6 childs]

    **Parent 1** - [See All contact of parent 1/3 childs]
        Child 1 [All contacts of child 1]
        Child 2
        Child 3
    **Parent 2** -[See All contact of parent 2/3 childs] 
        Child 1
        Child 2
        Child 3

I created a inline VF page for this but it covers only 2 level. Can anyone please help me on this to show it in multiple levels?

Page :

<apex:pageBlock title="Contact">
               <apex:outputPanel id="cont">
                 <apex:pageBlockTable value="{!conList}" var="con" id="conlist" title="Contact">
                     <apex:column value="{!con.Name}"/>
                     <apex:Column value="{!con.Phone}" />
                     <apex:Column value="{!con.Email}" />

Controller :

public with sharing class AccController {
    public List <Contact> conList {get;set;}
    public ApexPages.StandardController controller {get; set;}
    public Account acc;
    public AccController(ApexPages.StandardController controller) {
         this.controller = controller;
        this.acc = (Account)controller.getRecord();
        Account accRec =[Select id,ParentId from Account where id =:acc.id];
            conList = [Select Id,Name, Phone, Email from Contact where account.Parent.ParentId =: acc.id];
            conList = [Select Id, Name, Phone, Email from Contact where account.ParentId =: acc.id];
  • Favorited so I can answer when I have the time as this is going to require writing some code and testing to make sure It works. – gNerb Jan 25 '18 at 19:45
  • 2
    Is the requirement to show the current account's contacts and any child accounts' contacts from that point down, up to 5 levels? Or, if you are looking at an Account that is level 3, do you need to show the two levels above and the two levels below? – Thomas Taylor Jan 25 '18 at 19:45

Normally, the first rule of Salesforce is never to perform SOQL in a loop. I'm going to advise you to break that rule here, because as you say the depth of the Account hierarchy is limited and it's safe to do so in a certain sense.

That said, a very large and complex account hierarchy will likely cause heap size and CPU time exceptions, and there is a limit to how much can be done to address that without writing a huge amount of code. Visualforce view state size is also going to be a concern.

Here's what I think you need to do. Note that this code traverses the Account hierarchy downwards only per your comments.


public with sharing class AccountHierarchyController {
    public Account acc { get; private set; }
    public List<Account> accountList { get; private set; }
    public ApexPages.StandardController controller { get; private set; }

    public AccountHierarchyController(ApexPages.StandardController controller) {
        this.acc = (Account)controller.getRecord();
        this.accountList = new List<Account>();

        Account baseAccount = [SELECT Id, 
                               (SELECT Id, Name, Phone, Email from Contacts),
                               (SELECT Id, Name FROM ChildAccounts)
                               FROM Account 
                               WHERE Id = :acc.id];

        // Traverse the hierarchy downwards
        Set<Id> accountsToQuery = new Map<Id, Account>(baseAccount.ChildAccounts).keySet();
        while (accountsToQuery.size() > 0) {
            List<Account> thisLevelAccounts = [SELECT Id, Name, Parent.Name,
                                               (Select Id, Name, Phone, Email from Contacts),
                                               (SELECT Id, Name FROM ChildAccounts)
                                               FROM Account
                                               WHERE Id IN :accountsToQuery];
            accountsToQuery = new Set<Id>();

            for (Account a : thisLevelAccounts) {
                // Add this Account (with its Contacts) to the list.

                // Add this Account's children to the query for the next level.
                for (Account child : a.ChildAccounts) {

Visualforce Page

<apex:page title="Contact" standardController="Account" extensions="AccountHierarchyController">
    <apex:outputPanel id="cont">
        <apex:pageBlock title="Contacts">
            <apex:repeat value="{! accountList }" var="a">
                <apex:pageBlockSection title="{! a.Name + IF(NOT(ISBLANK(a.ParentId)), ' (child of ' + a.Parent.Name + ')', '') }">
                    <apex:pageBlockTable value="{! a.Contacts }" var="con" id="conlist" title="Contact">
                        <apex:column value="{!con.Name}"/>
                        <apex:column value="{!con.Phone}" />
                        <apex:column value="{!con.Email}" />

Here's what it looks like for a very simple 3-level hierarchy, with 2 children on one of the levels.

Screenshot of Visualforce page

  • thanks for your response I implemented the code you provide. Here what I found is when I added that page to a Account it is showing for all the levels including GrandParent. But what I want is to just show that Account contacts and its child Contact. – Learner Jan 26 '18 at 16:05
  • So you only want to traverse the hierarchy downwards? You'll show the account with its contacts and all of the account's children with their contacts? That's an easy change; please see my edited answer. – David Reed Jan 26 '18 at 16:33
  • If you find the answer acceptable and covering your question fully, please consider awarding the bounty. – David Reed Jan 26 '18 at 18:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.