Thursday 8 November 2012

A PHP Class/Object to make html tables

A PHP Class/Object to make html tables

I have been working on a project recently that had cause for a lot of tables to be generated from PHP looking up a database.  After the first couple I got somewhat bored of the amount of time and typing that each table was taking to manualy code on each page.  So I knocked up this little class/object to generate the tables for me, saving me a load of typing in the long run.  I have commented it at the top for usage and stuff, but it's not standards complient, it's just something I put together quick to save me some time, and thought I would share with you all in case you find it helpfull too.

If you need anything explained, or have a suggestion for additions to it, just leave a comment.

p.s. If you lift the code, I'd appreciate if you left a comment for that too ;)

class makeHTMLTable{
/*~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#
Class for dynamicly rendering HTML Tables from nothing more than a single
dataset.

USAGE :-
call something like $table = new makeHTMLTable($myDataset) in your code
where $myDataset is a valid dataset array.
This can be the result of a database query / xml array / dom array / any array
as long as it is a multidimensional, associative array in the form of

array([0]=>array([heading1]=>'value1-1', [heading2]=>'value1-2',....),
array([1]=>array([heading1]=>'value2-1', [heading2]=>'value2-2',....),
...)

you can then call either
$tableOut = $table->newBasicTable($id[string], $class[string], $style[string])
or
$tableOut = $table->newSplitSumTable($split[string], $sum[array], $class[string], $style[string])

newBasicTable :- when calling this method you have the option to pass in three
peices of string information to be applied to the table that is created.
$id will be set as the DOM_id of the table
$class will apply the DOM_class entered to the table
$style applys inline CSS to the table.

all three of these are completly optional and may be left out.
e.g. with no data passed in :-
$tblOut = $tbl->newBasicTable();
this will simply produce
"<table>"

e.g. with extra data :-
$tblOut = $tbl->newBasicTable("myTbl1','content ui-table-widget','color:blue;');
this will produce
"<table id='myTb1' class='content ui-table-widget' style='color:blue;'"


newSplitSumTable :- when calling this class you must pass in the first two
paramaters ($split[string], $sum[array]). $class and $style are exactly the same
as in the newBasicTable, but as this method outputs multiple tables $id has been
dropped.
$split should be the string value that is exactly equal to the heading of the
column that you want to split the data on. $sum should be a simple number key
array of string values that exactly match the headings of the columns that you
want summed.  This sums the values, it does not count the records. As well as
summing each split, there is also an overall total produced at the end.  This
type of table is handy for analysis, such as checking sales by area or duration
 of support tickets by assigned group.

e.g.
$tblOut = $tbl->newSplitSumTable('Sales Area', array('Monthly Turnover','Units Sold', '% To Proffit'));

This will produce a series of tables, one for each sales area, and have a group
totals table after each with the sum per area of the turnover, units and profit
as well as an overall total for everything at the very end.

Additionaly, when the class is created it strips out the heading information,
storing it in $headers.  This can be used for making lists for splitSum tables
so you don't need to depend on user input for the column headers. The data is
also held indipendant of the column headers, so can be manipulated indipendantly.
The class also maintains a "master" copy of the dataset passed to it, so it can
be re-used without needing aditional querys on the datasource.
As well as this the row count and column count are stored, this can be used to
help with pagination, display and further calculations.

$tbl = new makeHTMLTable($dataset);
$headerArray = $tbl->headers;
$dataArray = $tbl->data;
$orginalData = $tbl->dataset;
$rowCount = $tbl->rows;
$columnCount = $tbl->cols;

--added newSplitCountTable()
This works exactly like the newSplitSumTable() but counts the records returned
rather than adding the values.  

~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#*/
    public $headers;
    public $data;
    public $cols;
    public $rows;
    public $dataset;
   
    public function __construct($dataset){
        $this->dataset = $dataset;
        $this->headers = $this->getHeadings();
        $this->cols = count($this->headers);
        $this->rows = count($this->dataset);
        $this->data = $this->getValues();
    }
   
    public function getHeadings(){
        $first = true;
        $results = $this->dataset;
        foreach($results as $record){
            if($first === true){
                foreach($record as $heading=>$value){
                    $headings[] = $heading;   
                }
            $first = false;
            }
        }
        return $headings;
    }
   
    public function getValues($visible=null, $start=0){
        if($visible===null){
            $visible = $this->rows;
        }
        if(($start+$visible) > $this->rows){
            $visible = $this->recCount - $start;
        }
        $dispCount = 0;
        $headArray = $this->headers;
        for ($disp=$start;$disp<($start+$visible);$disp++) {
            foreach($headArray as $valueHeading){
                $values[$dispCount][] = $this->dataset[$disp][$valueHeading];
            }
            $dispCount++;     
        }
        return $values;
    }
   
    public function newBasicTable($id="", $class="", $style=""){
        $meta = "";
        if($id != "") {$meta .= " id=\"{$id}\"";}
        if($class != "") {$meta .= " class=\"{$class}\"";}
        if($style != "") {$meta .= " style=\"${style}\"";}
        $table = "<table{$meta}><tr>";
        foreach($this->headers as $hk=>$hv){
            $table .= "<th>$hv</th>";
        }
        $table .= "</tr>";
        $end = $this->rows-1;
        for($counter=0;$counter<=$end;$counter++){
            $table .= "<tr>";
            $subData = $this->data[$counter];
            foreach($subData as $dk => $dv){
                $table .= "<td>$dv</td>";
            }
            $table .= "</tr>";
        }
        $table .= "</table>";
        return $table;
    }
   
    public function newSplitSumTable($splitField, $sumOnColumns, $class="", $style=""){
        $return = "";
        $subSum = array();
        $totSum = array();
        $meta = "";
        $splitIDX = array_search($splitField, $this->headers);
        if($class != "") {$meta .= " class=\"{$class}\"";}
        if($style != "") {$meta .= " style=\"${style}\"";}
        $sumColCount = count($sumOnColumns)-1;
        foreach($sumOnColumns as $colName){
            $colNameIDX[$colName] = array_search($colName, $this->headers);
            $subSum[$colName] = 0;
            $totSum[$colName] = 0;
            for($i=0;$i<=$this->cols-1;$i++){
                $headings[$i] = $this->headers[$i];
            }
        }
        $colValIDX = array_flip($colNameIDX);
        foreach($colValIDX as $sumByVal => $colName){
            $subSumV[$sumByVal] = 0.00    ;
        }       
        foreach($this->data as $rows){
            $temp[] = $rows[$splitIDX];
        }
        $temp = array_unique($temp);
        foreach($temp as $uselessKey=>$splitVal){
            $splitList[] = $splitVal;
        }   
        $splitCount = count($temp)-1;
        for($i=0;$i<=$splitCount;$i++){
            foreach($this->data as $noGroup){
                if($noGroup[$splitIDX] == $splitList[$i]){
                    $group[$i][]= $noGroup;
                }
            }
        }
        for($i=0;$i<=$splitCount;$i++){
            $return .= "<h2>{$splitList[$i]}</h2>";
            $return .= "<table {$meta}>\n";
            $return .= "<tr>";
            foreach($this->headers as $heading){
                $return .= "<th>{$heading}</th>";
            }
            $return .= "</tr>\n <tr>";
            foreach($group[$i] as $split){
                foreach($split as $key => $value){
                    $return .= "<td>{$value}</td>";
                    $colNo = array_search($key, $colNameIDX);
                    if($colNo){
                        $strToRemove = array("&pound;", ",");
                        $add = (float)$subSum[$colNo] + str_replace($strToRemove, "", $value);
                        $addT = (float)$totSum[$colNo] + str_replace($strToRemove, "", $value);
                        $subSum[$colNo] = $add;
                        $totSum[$colNo] = $addT;
                    }
                }
                $return .="</tr> \n";
            }
            $return .= "</tr>\n </table> \n ";
            $return .= "<h3>Group Totals</h3> ";
            $return .= " <table".$meta."><tr> ";
            foreach ($colValIDX as $h){
                $return .= "<th>{$h}</th>";
            }
            $return .= "</tr>\n <tr>";
            foreach ($subSum as $subKey => $subVal){
                    $subVal = number_format($subVal,2,".",",");
                    $return .= "<td>{$subVal}</td>";
            }
            $return .= "</tr>\n </table> \n <br /> \n <br /> \n";
            foreach($sumOnColumns as $colName){
                $subSum[$colName] = 0;
            }
        }
        $return .= "</tr>\n </table>\n";
        $return .= "<h3>Overall Totals</h3>";
        $return .= "<table{$meta}><tr>";
        foreach ($colValIDX as $oh){
            $return .= "<th>{$oh}</th>";
        }
        $return .= "</tr>\n <tr>";
        foreach ($totSum as $totKey => $totVal){
          $totVal = number_format($totVal,2,".",",");
           $return .= "<td>{$totVal}</td>";
        }
        $return .= "</tr> \n </table> \n";
    return $return;
    }
 
      public function newSplitCountTable($splitField, $countOnColumns, $class="", $style=""){
        $return = "";
        $subSum = array();
        $totSum = array();
        $meta = "";
        $splitIDX = array_search($splitField, $this->headers);
        if($class != "") {$meta .= " class=\"{$class}\"";}
        if($style != "") {$meta .= " style=\"${style}\"";}
        $sumColCount = count($countOnColumns)-1;
        foreach($countOnColumns as $colName){
            $colNameIDX[$colName] = array_search($colName, $this->headers);
            $subSum[$colName] = 0;
            $totSum[$colName] = 0;
            for($i=0;$i<=$this->cols-1;$i++){
                $headings[$i] = $this->headers[$i];
            }
        }
        $colValIDX = array_flip($colNameIDX);
        foreach($colValIDX as $sumByVal => $colName){
            $subSumV[$sumByVal] = 0    ;
        }       
        foreach($this->data as $rows){
            $temp[] = $rows[$splitIDX];
        }
        $temp = array_unique($temp);
        foreach($temp as $uselessKey=>$splitVal){
            $splitList[] = $splitVal;
        }   
        $splitCount = count($temp)-1;
        for($i=0;$i<=$splitCount;$i++){
            foreach($this->data as $noGroup){
                if($noGroup[$splitIDX] == $splitList[$i]){
                    $group[$i][]= $noGroup;
                }
            }
        }
        for($i=0;$i<=$splitCount;$i++){
            $return .= "<h2>{$splitList[$i]}</h2>";
            $return .= "<table{$meta}>\n";
            $return .= "<tr>";
            foreach($this->headers as $heading){
                $return .= "<th>{$heading}</th>";
            }
            $return .= "</tr>\n <tr>";
            foreach($group[$i] as $split){
                foreach($split as $key => $value){
                    $return .= "<td>{$value}</td>";
                    $colNo = array_search($key, $colNameIDX);
                    if($colNo){
                        $strToRemove = array("&pound;", ",");
                        $add = $subSum[$colNo]+1;
                        $addT = $totSum[$colNo]+1;
                        $subSum[$colNo] = $add;
                        $totSum[$colNo] = $addT;
                    }
                }
                $return .="</tr> \n";
            }
            $return .= "</tr>\n </table> \n ";
            $return .= "<h3>Group Totals</h3> ";
            $return .= " <table".$meta."><tr> ";
            foreach ($colValIDX as $h){
                $return .= "<th>Count Of {$h}</th>";
            }
            $return .= "</tr>\n <tr>";
            foreach ($subSum as $subKey => $subVal){
                    $subVal = number_format($subVal,0,".",",");
                    $return .= "<td>{$subVal}</td>";
            }
            $return .= "</tr>\n </table> \n <br /> \n <br /> \n";
            foreach($countOnColumns as $colName){
                $subSum[$colName] = 0;
            }
        }
        $return .= "</tr>\n </table>\n";
        $return .= "<h3>Overall Totals</h3>";
        $return .= "<table{$meta}><tr>";
        foreach ($colValIDX as $oh){
            $return .= "<th>Count Of {$oh}</th>";
        }
        $return .= "</tr>\n <tr>";
        foreach ($totSum as $totKey => $totVal){
          $totVal = number_format($totVal,0,".",",");
           $return .= "<td>{$totVal}</td>";
        }
        $return .= "</tr> \n </table> \n";
    return $return;
    }   
}

No comments:

Post a Comment