DataTable column headers and footers can be combined for grouped display.
Documentation<h:form> <p:dataTable var="sale" value="#{dtGroupView.sales}"> <f:facet name="header"> Sales/Profits of Manufacturers </f:facet> <p:columnGroup type="header"> <p:row> <p:column rowspan="3" headerText="Manufacturer" /> <p:column colspan="4" headerText="Sale Rate" /> </p:row> <p:row> <p:column colspan="2" headerText="Sales" /> <p:column colspan="2" headerText="Profit" /> </p:row> <p:row> <p:column headerText="Last Year" /> <p:column headerText="This Year" /> <p:column headerText="Last Year" /> <p:column headerText="This Year" /> </p:row> </p:columnGroup> <p:column> <h:outputText value="#{sale.manufacturer}" /> </p:column> <p:column> <h:outputText value="#{sale.lastYearProfit}%" /> </p:column> <p:column> <h:outputText value="#{sale.thisYearProfit}%" /> </p:column> <p:column> <h:outputText value="#{sale.lastYearSale}"> <f:convertNumber type="currency" currencySymbol="$" /> </h:outputText> </p:column> <p:column> <h:outputText value="#{sale.thisYearSale}"> <f:convertNumber type="currency" currencySymbol="$" /> </h:outputText> </p:column> <p:columnGroup type="footer"> <p:row> <p:column colspan="3" style="text-align:right" footerText="Totals:" /> <p:column footerText="\$#{dtGroupView.lastYearTotal}" /> <p:column footerText="\$#{dtGroupView.thisYearTotal}" /> </p:row> </p:columnGroup> <f:facet name="footer"> Data between 2013-2014 </f:facet> </p:dataTable> <p:dataTable var="player" value="#{dtGroupView.players}" style="margin-top:40px"> <f:facet name="header"> Dynamic Columns </f:facet> <p:columnGroup type="header"> <p:row> <p:column rowspan="2" headerText="Player" /> <p:column colspan="#{dtGroupView.yearCount}" headerText="Goals" /> </p:row> <p:row> <ui:repeat value="#{dtGroupView.years}" var="year"> <p:column headerText="#{year}" /> </ui:repeat> </p:row> </p:columnGroup> <p:column> <h:outputText value="#{player.name}" /> </p:column> <p:columns value="#{dtGroupView.years}" var="year"> <h:outputText value="#{player.getGoals(year)}" /> </p:columns> <f:facet name="footer"> Data between 2010-2014 </f:facet> </p:dataTable> </h:form>
@Named("dtGroupView") @ViewScoped public class GroupView implements Serializable { private final static String[] manufacturers; private List<Sale> sales; private final static String[] playerNames; private List<Integer> years; private List<Player> players; static { manufacturers = new String[10]; manufacturers[0] = "Apple"; manufacturers[1] = "Samsung"; manufacturers[2] = "Microsoft"; manufacturers[3] = "Philips"; manufacturers[4] = "Sony"; manufacturers[5] = "LG"; manufacturers[6] = "Sharp"; manufacturers[7] = "Panasonic"; manufacturers[8] = "HTC"; manufacturers[9] = "Nokia"; } static { playerNames = new String[10]; playerNames[0] = "Lionel Messi"; playerNames[1] = "Cristiano Ronaldo"; playerNames[2] = "Arjen Robben"; playerNames[3] = "Franck Ribery"; playerNames[4] = "Ronaldinho"; playerNames[5] = "Luis Suarez"; playerNames[6] = "Sergio Aguero"; playerNames[7] = "Zlatan Ibrahimovic"; playerNames[8] = "Neymar Jr"; playerNames[9] = "Andres Iniesta"; } @PostConstruct public void init() { sales = new ArrayList<Sale>(); for(int i = 0; i < 10; i++) { sales.add(new Sale(manufacturers[i], getRandomAmount(), getRandomAmount(), getRandomPercentage(), getRandomPercentage())); } years = new ArrayList<Integer>(); years.add(2010); years.add(2011); years.add(2012); years.add(2013); years.add(2014); players = new ArrayList<Player>(); for(int i = 0; i < 10; i++) { players.add(new Player(playerNames[i], generateRandomGoalStatsData())); } } public List<Sale> getSales() { return sales; } private int getRandomAmount() { return (int) (Math.random() * 100000); } private int getRandomPercentage() { return (int) (Math.random() * 100); } public String getLastYearTotal() { int total = 0; for(Sale sale : getSales()) { total += sale.getLastYearSale(); } return new DecimalFormat("###,###.###").format(total); } public String getThisYearTotal() { int total = 0; for(Sale sale : getSales()) { total += sale.getThisYearSale(); } return new DecimalFormat("###,###.###").format(total); } public List<Integer> getYears() { return years; } public int getYearCount() { return years.size(); } public List<Player> getPlayers() { return players; } private Map<Integer,Integer> generateRandomGoalStatsData() { Map<Integer,Integer> stats = new LinkedHashMap<Integer, Integer>(); for (int i = 0; i < 5; i++) { stats.put(years.get(i), getRandomGoals()); } return stats; } private int getRandomGoals() { return (int) (Math.random() * 50); } }