Group Data on Visualforce Page

I am using Apex to find all opportunities related to certain tasks. We want to recognize reps that complete a demo which leads to an opportunity. We can count the Opps with a roll up field but we want to see more information. Custom Reporting will not allow us to relate any object to Task. Here is the controller:

public with sharing class DemoOppsController {

//set up controller & extension for vf page
ApexPages.StandardSetController setCon;

public DemoOppsController(ApexPages.StandardSetController controller) {
    setCon = controller;

//set up variables
public List<Task> demoList {get;set;}
public List<Task> ownerList {get;set;}
public List<Id> repIdList {get;set;}
public List<User> repList {get;set;}
public List<Id> conIdList {get;set;}
public List<Contact> conList {get;set;}
public List<Id> accIdList {get;set;}
public Set<Id> accSet {get;set;}
public List<Account> accList {get;set;}
public List<Id> oppIdList {get;set;}
public Set<Id> oppSet {get;set;}
public List<Opportunity> oppList1 {get;set;}
public List<Opportunity> oppList {get;set;}
public List<Commission_Split__c> csList {get;set;}
public List<Id> IdList {get;set;}
public List<Account> oppAccList {get;set;}

public void getDemos(){
    //get tasks
    demoList = new List<Task> ([SELECT Id, ActivityDate, WhoId,Who.Name,Type,Subject,Status,AccountId,Account.Name,OwnerId,Owner.Name,Owner.UserRole.Name, WhatId
                                FROM Task 
                                WHERE ActivityDate<=TODAY AND ActivityDate=THIS_YEAR AND Type='Call:DM' ORDER BY Owner.UserRole.Name]);
    //get rep Ids
    repIdList = new List<Id>();
    repList = new List<User>();
    for(Task t :demoList){
    repList = [SELECT Id,Name,UserRole.Name,Territory__c From User WHERE Id IN :repIdList ORDER BY UserRole.Name];
    system.debug('repIdList : '+repIdList);
    //get contact Ids
    conIdList = new List<Id>();
    conList = new List<Contact>();
    for(Task t :demoList){
    conList = [SELECT Id, LeadSource,OwnerId,AccountId,Owner.Name FROM Contact WHERE Id IN :conIdList ORDER BY Owner.UserRole.Name];
    //get account Ids from Tasks
    accSet = new Set<Id>();
    accList = new List<Account>();
    for(Task t :demoList){
    //get account Ids from conList
    for(Contact cons :conList){
    //accList is the list of accounts related to contacts and demos
    accList = [SELECT Id, OwnerId,Owner.UserRole.Name,Owner.Name FROM Account WHERE Id IN :accSet ORDER BY Owner.UserRole.Name];
    //get Opps Ids
    oppIdList = new List<Id>();
    oppList1 = new List<Opportunity>();
    oppList = new List<Opportunity>();
    oppSet = new Set<Id>();
    //oppList1 is list of opps owned by same rep as demos, and same account as accList
    oppList1 = [SELECT Id,AccountId,Account.Name,Owner.UserRole.Name,Amount,Owner.Name,Name FROM Opportunity WHERE OwnerId IN :repIdList AND AccountId IN :accList AND CloseDate = THIS_YEAR ORDER BY Owner.UserRole.Name];
    for(Opportunity opp :oppList1){
    //csList is list of commission splits with same rep as demos and same opp as oppList
    csList = [SELECT Id,User__c,Opportunity__r.Account.Name,Opportunity__r.Amount,Opportunity__c,Opportunity__r.Name,Opportunity__r.Id,User__r.Name FROM Commission_Split__c 
                                 WHERE Opportunity__r.CloseDate = THIS_YEAR AND Opportunity__r.AccountId IN :accList AND User__c IN :repIdList];
    for(Commission_Split__c cs :csList){
    //create oppList from opportunities and commission splits
    oppList = [SELECT Id,AccountId,Account.Name,Owner.UserRole.Name,Amount,Owner.Name,Name FROM Opportunity WHERE Id IN :oppSet];

This is working but the data is displayed as two side by side lists. I need them to be grouped by Rep, then by Account then by Opportunity. Is this possible? Here is my vf code:

    <apex:page standardController="Opportunity" extensions="DemoOppsController" recordSetVar="users" tabStyle="User" sidebar="false" action="{!getDemos}">


        <apex:pageBlock title="SMB Demos with Opportunity Info">
                <div id="col1">
            <apex:pageBlockSection title="Demos">
                <apex:pageBlockTable value="{!demoList}" var="d" id="demo">
                    <apex:column headerValue="Account"><apex:outputField value="{!d.AccountId}"/></apex:column>
                    <apex:column headerValue="Team" value="{!d.Owner.UserRole.Name}"></apex:column>
                    <apex:column headerValue="Rep Name" value="{!d.Owner.Name}"></apex:column>
                    <apex:column headerValue="Contact Name"><apex:outputField value="{!d.WhoId}"></apex:outputField></apex:column>
                    <apex:column headerValue="Date" value="{!d.ActivityDate}"></apex:column>
                    <apex:column headerValue="Demos" value="{!d.Subject}"></apex:column>

    <div id="col2">
            <apex:pageBlockSection title="Opportunities">
                <apex:pageBlockTable value="{!oppList}" var="o" id="opp">
                    <apex:column headerValue="Account"><apex:outputField value="{!o.AccountId}"/></apex:column>
                    <apex:column headerValue="Team" value="{!o.Owner.UserRole.Name}"></apex:column>
                    <apex:column headerValue="Opportunity Owner" value="{!o.Owner.Name}"></apex:column>
                    <apex:column headerValue="Name"><a href="/{!o.Id}">{!o.Name}</a></apex:column>
                    <apex:column headerValue="Amount" value="{!o.Amount}"></apex:column>


What can I do to my VF code to display the data in groups instead of two lists?