4

I am new to vf tables and repeat tags. i am trying to create the below table in vf page could anyone please help me to achieve this by telling the way how i can do the below:-

Object- Family

Fields- GrandParent,Parent,Child,Weight,Workout_Hours

Records:-

GrandParent  Parent  Child  Weight height
GrandParent1 Parent1 Child1  30       2
GrandParent1 Parent1 Child2  25       1
GrandParent1 Parent2 Child1  10       1
GrandParent2 Parent1 Child1  30       3
GrandParent2 Parent2 Child2  20       2

Expected Result-

Parents          Weight            Workout_Hours
-----------------------------------------------------
GrandParent1    65                   4
------------
Parent1---------55---------------------3
  Child1             30                  2
  Child2             25                  1

Parent2---------10---------------------1
  Child1             10                  1

GrandParent2     50                  5
------------
Parent1----------30--------------------3
  Child1             30                  3

Parent2----------20--------------------2
  Child1             20                  2

Till now i have achieved to create parent column but in that teams and childs are getting repeated and i am also not sure how to calculate each repetitive childs and then show childs weight total in parent and the total of parents in grandparents weight.

Page:-

<apex:repeat value="{!MapGP }" var="grand">
    <tr><td>{!grand}<hr></hr></td></tr>
        <apex:repeat value="{!MapGP[grand]}" var="par">
            <tr><td>{!par}</td></tr>
               <apex:repeat value="{!ChildMap[par]}" var="Child">
                 <tr><td>{!Child}</td></tr>
               </apex:repeat>
        </apex:repeat>
</apex:repeat>

Controller:-

public List<Parent__c> tableData = [Select id,GrandParent__c,Parent__c,Weight__c,Workout_Hours__c from Parent__c];
        public Map<String,List<String>> getMapGP() {

          Map<String,List<String>> MapGP = new Map<String,List<String>>();
          for(Parent__c g : tableData)
          {  
                  if(MapGP.keyset().contains(g.GrandParent__c))
                  {
                     MapGP.get(g.GrandParent__c).add(g.Parent__c);
                  }
                  else
                  {
                     MapGP.put(g.GrandParent__c,new List<String>{g.Parent__c});

                  }
          }

            return MapGP;
        }

        public Map<String,List<String>> getChildMap() {
         Map<String,List<String>> ChildMap = new Map<String,List<String>>();
          for(Parent__c g : tableData)
          {
            if(ChildMap.keyset().contains(g.Parent__c))
            {
               ChildMap.get(g.Parent__c).add(g.Child__c);
            }
            else
            {
                 ChildMap.put(g.Parent__c,new List<String>{g.Child__c});
            }

          }
          return ChildMap; 
      }
1
  • Welcome to SFSE and thanks for your nice question, see my answers below. Mar 14 '17 at 22:44
7

I could think of preparing data based on SOQL query using GROUP BY ROLLUP

I have replicated the data at my DE and following SOQL query is giving the exact formatting and summation which you are trying to achieve.

SELECT GrandParent__c, Parent__c, Child__c, SUM(Weight__c), SUM(Workout_Hours__c) ,
GROUPING (GrandParent__c) grpGrantPt, GROUPING(Parent__c) grpPT
FROM Family__c
GROUP BY ROLLUP(GrandParent__c, Parent__c,Child__c)
ORDER BY GrandParent__c, Parent__c, Child__c

Query Result:

Group by rollup query result

You just eliminate the first record as it is giving total summation.

Controller

Retrieve the records from SOQL query and store them into instance of wrapper class.

public class FamilyClass
{
    public List<FamilyData> lstFamilyRecord {get;set;}

    public PageReference displayData()
    {
        Boolean firstRecord = true;

        lstFamilyRecord = new List<FamilyData>();
         AggregateResult[] lstFamily = [SELECT GrandParent__c, Parent__c, Child__c, SUM(Weight__c) weightTotal, SUM(Workout_Hours__c) whTotal ,
                                        GROUPING (GrandParent__c) grpGrantPt, GROUPING(Parent__c) grpPT
                                        FROM Family__c
                                        GROUP BY ROLLUP(GrandParent__c, Parent__c,Child__c)
                                        ORDER BY GrandParent__c, Parent__c, Child__c];

        for(AggregateResult familyObj:lstFamily)
        {
            if(!firstRecord)
            {
                FamilyData wrapper = new FamilyData();
                wrapper.GrantParent = (String) familyObj.get('GrandParent__c');
                wrapper.Parent = (String) familyObj.get('Parent__c');
                wrapper.Child = (String) familyObj.get('Child__c');

                if(familyObj.get('GrandParent__c') !=null && familyObj.get('Parent__c') !=null && familyObj.get('Child__c') !=null)
                {
                    wrapper.isChildRecord = true;
                }
                else if (familyObj.get('GrandParent__c') !=null && familyObj.get('Parent__c') !=null && familyObj.get('Child__c') ==null)
                {
                    wrapper.isParentRecord = true;
                }
                else if(familyObj.get('GrandParent__c') !=null && familyObj.get('Parent__c') ==null && familyObj.get('Child__c') ==null)
                {
                    wrapper.isGrantParentRecord = true;
                }
                wrapper.Weight = familyObj.get('weightTotal')!=null? ((Decimal)familyObj.get('weightTotal')).intValue():null;
                wrapper.WorkoutHours = familyObj.get('whTotal')!=null? ((Decimal)familyObj.get('whTotal')).intValue() :null;
                lstFamilyRecord.add(wrapper);
            }
            firstRecord = false;
        }

        return null;
    }

    public class FamilyData
    {
        public String GrantParent {get;set;}
        public String Parent {get;set;}
        public String Child {get;set;}
        public Integer Weight {get;set;}
        public Integer WorkoutHours {get;set;}
        public Boolean isGrantParentRecord {get;set;}
        public Boolean isParentRecord {get;set;}
        public Boolean isChildRecord {get;set;}
    }

}

Visualforce

<apex:page id="familyPage" controller="FamilyClass" action="{!displayData}" showheader="true" sidebar="false"> 
    <table id="familytable" border="1"> 
        <tr>
            <th>Parents</th>
            <th>Weight</th>
            <th>Work Hours</th>
        </tr>             
        <apex:repeat id="myRepeat" value="{!lstFamilyRecord}" var="key"> 
            <tr>
                <td>
                    <apex:outputText style="color: red;" value="{!key.GrantParent}" rendered="{!key.isGrantParentRecord}"/>
                    <apex:outputText style="color: blue;" value="{!key.Parent}" rendered="{!key.isParentRecord}"/>
                    <apex:outputText value="{!key.Child}" rendered="{!key.isChildRecord}"/>
                </td>
                <td>
                    <apex:outputText value="{!key.Weight}"/>
                </td>
                <td>
                    <apex:outputText value="{!key.WorkoutHours}"/>
                </td>
            </tr>                       
        </apex:repeat>
    </table>          
</apex:page>

Expected output

visualforce

You can see only single <apex:repeat/> has been used to display the records in VFP which is more efficient in terms of performance.

3
  • yes, that's why I have experimented, you can see how clean the data is displaying Mar 14 '17 at 19:57
  • @cropredy, now based on the query, the logic become very simple, single repeat helps me to display data instead of 3 repeat statements Mar 14 '17 at 22:43
  • @Santanu - That was a nice explanation, but is it possible to make this whole table as a collapsible tree view so if the child data will be more can be shrink-ed so it will give the classy look to the table. Just like a Pivot table of Excel.
    – RAT__
    Mar 29 '17 at 17:39

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.