Tony Landis home

PHP Array to Text Tables

I needed this for a little project so I coded it up. I haven’t done a lot of tests but it works just fine for formatting the associative arrays I have run through it.

The class supports multi-line rows, limiting the width of the column, and automatically creating a heading based on the keys from the associative array.

Usage and Output Example
<?php

$data = array(
array('company'=>'AIG', 'id'=>1, 'balance'=> '-$99,999,999,999.00'),
array('company'=>'Wachovia', 'id'=>2, 'balance'=> '-$10,000,000.00'),
array('company'=>'HP', 'id'=>3, 'balance'=> '$555,000.000.00'),
array('company'=>'IBM', 'id'=>4, 'balance'=> '$12,000.00')
);

$renderer = new ArrayToTextTable($data);
$renderer->showHeaders(true);
$renderer->render();

?>
Text Table Formatted Output of above example:
+----------+----+---------------------+
| COMPANY  | ID |       BALANCE       |
+----------+----+---------------------+
| AIG      | 1  | -$99,999,999,999.00 |
| Wachovia | 2  | -$10,000,000.00     |
| HP       | 3  | $555,000.000.00     |
| IBM      | 4  | $12,000.00          |
+----------+----+---------------------+

Here is the class:

<?php
/**
* Array to Text Table Generation Class
*
* @author Tony Landis <tony@tonylandis.com>
* @link http://www.tonylandis.com/
* @copyright Copyright (C) 2006-2009 Tony Landis
* @license http://www.opensource.org/licenses/bsd-license.php
*/
class ArrayToTextTable
{
    /**
* @var array The array for processing
*/
    private $rows;

    /**
* @var int The column width settings
*/
    private $cs = array();

    /**
* @var int The Row lines settings
*/
    private $rs = array();

    /**
* @var int The Column index of keys
*/
    private $keys = array();

    /**
* @var int Max Column Height (returns)
*/
    private $mH = 2;

    /**
* @var int Max Row Width (chars)
*/
    private $mW = 30;

    private $head = false;
    private $pcen = "+";
    private $prow = "-";
    private $pcol = "|";
    
    
    /** Prepare array into textual format
*
* @param array $rows The input array
* @param bool $head Show heading
* @param int $maxWidth Max Column Height (returns)
* @param int $maxHeight Max Row Width (chars)
*/
    public function ArrayToTextTable($rows)
    {
        $this->rows =& $rows;
        $this->cs=array();
        $this->rs=array();
 
        if(!$xc = count($this->rows)) return false;
        $this->keys = array_keys($this->rows[0]);
        $columns = count($this->keys);
        
        for($x=0; $x<$xc; $x++)
            for($y=0; $y<$columns; $y++)
                $this->setMax($x, $y, $this->rows[$x][$this->keys[$y]]);
    }
    
    /**
* Show the headers using the key values of the array for the titles
*
* @param bool $bool
*/
    public function showHeaders($bool)
    {
       if($bool) $this->setHeading();
    }
    
    /**
* Set the maximum width (number of characters) per column before truncating
*
* @param int $maxWidth
*/
    public function setMaxWidth($maxWidth)
    {
        $this->mW = (int) $maxWidth;
    }
    
    /**
* Set the maximum height (number of lines) per row before truncating
*
* @param int $maxHeight
*/
    public function setMaxHeight($maxHeight)
    {
        $this->mH = (int) $maxHeight;
    }
    
    /**
* Prints the data to a text table
*
* @param bool $return Set to 'true' to return text rather than printing
* @return mixed
*/
    public function render($return=false)
    {
        if($return) ob_start(null, 0, true);
  
        $this->printLine();
        $this->printHeading();
        
        $rc = count($this->rows);
        for($i=0; $i<$rc; $i++) $this->printRow($i);
        
        $this->printLine(false);

        if($return) {
            $contents = ob_get_contents();
            ob_end_clean();
            return $contents;
        }
    }

    private function setHeading()
    {
        $data = array();
        foreach($this->keys as $colKey => $value)
        {
            $this->setMax(false, $colKey, $value);
            $data[$colKey] = strtoupper($value);
        }
        if(!is_array($data)) return false;
        $this->head = $data;
    }

    private function printLine($nl=true)
    {
        print $this->pcen;
        foreach($this->cs as $key => $val)
            print $this->prow .
                str_pad('', $val, $this->prow, STR_PAD_RIGHT) .
                $this->prow .
                $this->pcen;
        if($nl) print "\n";
    }

    private function printHeading()
    {
        if(!is_array($this->head)) return false;

        print $this->pcol;
        foreach($this->cs as $key => $val)
            print ' '.
                str_pad($this->head[$key], $val, ' ', STR_PAD_BOTH) .
                ' ' .
                $this->pcol;

        print "\n";
        $this->printLine();
    }

    private function printRow($rowKey)
    {
        // loop through each line
        for($line=1; $line <= $this->rs[$rowKey]; $line++)
        {
            print $this->pcol;
            for($colKey=0; $colKey < count($this->keys); $colKey++)
            {
                print " ";
                print str_pad(substr($this->rows[$rowKey][$this->keys[$colKey]], ($this->mW * ($line-1)), $this->mW), $this->cs[$colKey], ' ', STR_PAD_RIGHT);
                print " " . $this->pcol;
            }
            print "\n";
        }
    }

    private function setMax($rowKey, $colKey, &$colVal)
    {
        $w = mb_strlen($colVal);
        $h = 1;
        if($w > $this->mW)
        {
            $h = ceil($w % $this->mW);
            if($h > $this->mH) $h=$this->mH;
            $w = $this->mW;
        }
 
        if(!isset($this->cs[$colKey]) || $this->cs[$colKey] < $w)
            $this->cs[$colKey] = $w;

        if($rowKey !== false && (!isset($this->rs[$rowKey]) || $this->rs[$rowKey] < $h))
            $this->rs[$rowKey] = $h;
    }
}
?>
blog comments powered by Disqus