1567 lines
44 KiB
PHP
Executable File
1567 lines
44 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* FPDF Table - FPDF class extension
|
|
* Copyright (c) 2005-2010, http://www.interpid.eu
|
|
*
|
|
* FPDF Table is licensed under the terms of the GNU Open Source GPL 3.0
|
|
* license.
|
|
*
|
|
* Commercial use is prohibited. Visit <http://www.interpid.eu/fpdf-components>
|
|
* if you need to obtain a commercial license.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
* Foundation, either version 3 of the License, or any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
|
|
*
|
|
*
|
|
* Version: 3.4.3
|
|
* Date: 2005/07/20
|
|
* Author: Bintintan Andrei <andy@interpid.eu>
|
|
|
|
|
|
|
|
/**
|
|
Modifications:
|
|
2007.03.03
|
|
- added support for ROWSPAN
|
|
- changed the class functions/variables for PHP5
|
|
2006.09.25
|
|
- corrected a bug for empty cell texts
|
|
- corrected a bug for cell lines aligment error on new page
|
|
2006.05.18
|
|
- added support for cell splitting if new page ocuurs. FPDF_TABLE::tbSetSplitMode(true/false)
|
|
sets the splitting mode.
|
|
true = normal mode, the cell is splitted where the split ocuurs.
|
|
false = if splitting is required then the cell is drawed on the new page. If the cell
|
|
Height is bigger then the page height then the cell will be splitted.
|
|
- if the header does not have enough space for double it's Height then a new page ocuurs.
|
|
*/
|
|
require_once(dirname(__FILE__).'/class.multicelltag.php');
|
|
|
|
/**
|
|
* FPDF_TABLE - FPDF TABLE Add On Class
|
|
* @author Bintintan Andrei
|
|
* @copyright 2005 - 2007
|
|
*/
|
|
class fpdf_table extends fpdf_multicelltag
|
|
{
|
|
|
|
/**
|
|
* Number of Columns of the Table
|
|
* @access protected
|
|
* @var int
|
|
*/
|
|
protected $iColumnsNr = 0;
|
|
|
|
/**
|
|
* Contains the Header Data - header characteristics and texts
|
|
*
|
|
* Characteristics constants for Header Type:
|
|
* EVERY CELL FROM THE TABLE IS A MULTICELL
|
|
*
|
|
* WIDTH - this is the cell width. This value must be sent only to the HEADER!!!!!!!!
|
|
* T_COLOR - text color = array(r,g,b);
|
|
* T_SIZE - text size
|
|
* T_FONT - text font - font type = "Arial", "Times"
|
|
* T_ALIGN - text align - "RLCJ"
|
|
* V_ALIGN - text vertical alignment - "TMB"
|
|
* T_TYPE - text type (Bold Italic etc)
|
|
* LN_SPACE - space between lines
|
|
* BG_COLOR - background color = array(r,g,b);
|
|
* BRD_COLOR - border color = array(r,g,b);
|
|
* BRD_SIZE - border size --
|
|
* BRD_TYPE - border size -- up down, with border without!!! etc
|
|
* BRD_TYPE_NEW_PAGE - border type on new page - this is user only if specified(<>'')
|
|
* TEXT - header text -- THIS ALSO BELONGS ONLY TO THE HEADER!!!!
|
|
*
|
|
* all these setting conform to the settings from the multicell functions!!!!
|
|
*
|
|
* @access protected
|
|
* @var array
|
|
*/
|
|
protected $aTableHeaderType = array();
|
|
|
|
/**
|
|
* Header is drawed or not
|
|
* @access protected
|
|
* @var boolean
|
|
*/
|
|
protected $bTableHeaderDraw = true;
|
|
|
|
/**
|
|
* Table Border is drawed or not
|
|
* @access protected
|
|
* @var boolean
|
|
*/
|
|
protected $bTableBorderDraw = true;
|
|
|
|
/**
|
|
* Table Data Characteristics
|
|
* @access protected
|
|
* @var array
|
|
*/
|
|
protected $aTableDataType = array();
|
|
|
|
/**
|
|
* Table Characteristics
|
|
* @access protected
|
|
* @var array
|
|
*/
|
|
protected $aTableType = array();
|
|
|
|
/**
|
|
* Page Split Variable - if the table does not have enough space on the current page then the cells will be splitted.
|
|
* This onlu if $bTableSplit == TRUE
|
|
* If $bTableSplit == FALSE then the current cell will be drawed on the next page
|
|
*
|
|
* @access protected
|
|
* @var boolean
|
|
*/
|
|
protected $bTableSplit = true;
|
|
|
|
/**
|
|
* TRUE - if on current page was some data written
|
|
* @access protected
|
|
* @var boolean
|
|
*/
|
|
protected $bDataOnCurrentPage = false;
|
|
|
|
/**
|
|
* Table Data Cache. Will contain the information about the rows of the table
|
|
* @access protected
|
|
* @var array
|
|
*/
|
|
protected $aDataCache = array();
|
|
|
|
/**
|
|
* TRUE - if there is a Rowspan in the Data Cache
|
|
* @access protected
|
|
* @var boolean
|
|
*/
|
|
protected $bRowSpanInCache = false;
|
|
|
|
/**
|
|
* Sequence for Rowspan ID's. Every Rowspan gets a unique ID
|
|
* @access protected
|
|
* @var int
|
|
*/
|
|
protected $iRowSpanID = 0;
|
|
|
|
/**
|
|
* Table Header Cache. Will contain the information about the header of the table
|
|
* @access protected
|
|
* @var array
|
|
*/
|
|
protected $aHeaderCache = array();
|
|
|
|
/**
|
|
* Header Height. In user units!
|
|
* @access protected
|
|
* @var int
|
|
*/
|
|
protected $iHeaderHeight = 0;
|
|
|
|
/**
|
|
* Table Start X Position
|
|
* @access protected
|
|
* @var int
|
|
*/
|
|
protected $iTableStartX = 0;
|
|
|
|
/**
|
|
* Table Start Y Position
|
|
* @access protected
|
|
* @var int
|
|
*/
|
|
protected $iTableStartY = 0;
|
|
|
|
/**
|
|
* CLASS FUNCTIONS
|
|
*/
|
|
|
|
/**
|
|
* Returns the current page Width
|
|
*
|
|
* @access protected
|
|
* @param void
|
|
* @return integer - the Page Width
|
|
*/
|
|
protected function PageWidth(){
|
|
return (int) $this->w - $this->rMargin - $this->lMargin;
|
|
}//function PageWidth
|
|
|
|
|
|
/**
|
|
* Returns the current page Height
|
|
*
|
|
* @access protected
|
|
* @param void
|
|
* @return integer - the Page Height
|
|
*/
|
|
protected function PageHeight(){
|
|
return (int) $this->h - $this->tMargin - $this->bMargin;
|
|
}//function PageHeight
|
|
|
|
|
|
|
|
/**
|
|
* CONSTRUCTOR
|
|
* Table Initialization Function
|
|
*
|
|
* @access public
|
|
* @param integer - $iColumnsNr - Number of Colums
|
|
* @param boolean - $bTableHeaderDraw - true => Draw the table header on a new page
|
|
* @param boolean - $bTableBorderDraw - true => Draw the table border
|
|
* @return null
|
|
*/
|
|
public function tbInitialize($iColumnsNr = 0, $bTableHeaderDraw = true, $bTableBorderDraw = true){
|
|
|
|
$this->iColumnsNr = $iColumnsNr;
|
|
$this->aTableHeaderType = Array();
|
|
$this->bTableHeaderDraw = $bTableHeaderDraw;
|
|
$this->aTableDataType = Array();
|
|
|
|
$this->aDataCache = Array();
|
|
$this->aHeaderCache = Array();
|
|
|
|
$this->bTableBorderDraw = $bTableBorderDraw;
|
|
$this->bTableHeaderDraw = $bTableHeaderDraw;
|
|
|
|
$this->iTableStartX = $this->GetX();
|
|
$this->iTableStartY = $this->GetY();
|
|
|
|
$this->bDataOnCurrentPage = false;
|
|
}
|
|
|
|
/**
|
|
* Sets the number of Columns in the Table
|
|
*
|
|
* @access public
|
|
* @param integer $iNr - the number of Columns
|
|
* @return void
|
|
*/
|
|
public function tbSetColumnsNo($iNr){
|
|
$this->iColumnsNr = $iNr;
|
|
}
|
|
|
|
/**
|
|
* Sets the Split Mode of the Table. Default is ON(true)
|
|
*
|
|
* @access public
|
|
* @param boolean $bSplit - if TRUE then Split is Active
|
|
* @return void
|
|
*/
|
|
public function tbSetSplitMode($bSplit = true){
|
|
$this->bTableSplit = $bSplit;
|
|
}
|
|
|
|
/**
|
|
* Sets the Header Type
|
|
*
|
|
* $aHeaderType=
|
|
* array(
|
|
* 0=>array(
|
|
* "WIDTH" => 10,
|
|
* "T_COLOR" => array(120,120,120),
|
|
* "T_SIZE" => 5,
|
|
* ...
|
|
* "TEXT" => "Header text 1"
|
|
* ),
|
|
* 1=>array(
|
|
* ...
|
|
* ),
|
|
* );
|
|
*
|
|
* where 0,1... are the column number
|
|
*
|
|
* If the Header has multiple lines than $aHeaderType WILL HAVE TO Contain an array, which elements are composed from the array
|
|
* desribed above.
|
|
* $aHeaderType = array ($aHeaderType1, $aHeaderType2) where $aHeaderType1 and $aHeaderType2 have the above description
|
|
*
|
|
* @access public
|
|
* @param array $type_arr - header type
|
|
* @param boolean $bMultiLines - the header has multiple lines or not
|
|
* @return void
|
|
*/
|
|
public function tbSetHeaderType($aHeaderType, $bMultiLines = false){
|
|
if ($bMultiLines == false)
|
|
$this->aTableHeaderType[0] = $aHeaderType;
|
|
else
|
|
$this->aTableHeaderType = $aHeaderType;
|
|
|
|
//create the header cache data
|
|
foreach ($this->aTableHeaderType as $val)
|
|
$this->_tbAddDataToCache($val, 'header');
|
|
|
|
$this->_tbCacheParseRowspan(0, 'header');
|
|
|
|
$this->tbHeaderHeight();
|
|
}
|
|
|
|
|
|
/**
|
|
* Calculates the Header Height.
|
|
* If the Header height is bigger than the page height then the script dies.
|
|
*
|
|
* @access private
|
|
* @param void
|
|
* @return void
|
|
*/
|
|
private function tbHeaderHeight(){
|
|
$this->iHeaderHeight = 0;
|
|
|
|
$iItems = count($this->aHeaderCache);
|
|
for ($i=0; $i< $iItems; $i++){
|
|
$this->iHeaderHeight += $this->aHeaderCache[$i]['HEIGHT'];
|
|
}
|
|
|
|
if ($this->iHeaderHeight > $this->PageHeight()){
|
|
die("Header Height({$this->iHeaderHeight}) bigger than Page Height({$this->PageHeight()})");
|
|
}
|
|
}//private function tbHeaderHeight
|
|
|
|
|
|
|
|
/**
|
|
* Calculates the X margin of the table depending on the ALIGN
|
|
*
|
|
* @access protected
|
|
* @param void
|
|
* @return void
|
|
*/
|
|
protected function tbMarkMarginX(){
|
|
|
|
|
|
if (isset($this->aTableType['TB_ALIGN'])){
|
|
$tb_align = $this->aTableType['TB_ALIGN'];
|
|
}else{
|
|
$tb_align='';
|
|
}
|
|
|
|
//set the table align
|
|
switch($tb_align){
|
|
case 'C':
|
|
$this->iTableStartX = $this->lMargin + $this->aTableType['L_MARGIN'] + ($this->PageWidth() - $this->tbGetWidth())/2;
|
|
break;
|
|
case 'R':
|
|
$this->iTableStartX = $this->lMargin + $this->aTableType['L_MARGIN'] + ($this->PageWidth() - $this->tbGetWidth());
|
|
break;
|
|
default:
|
|
$this->iTableStartX = $this->lMargin + $this->aTableType['L_MARGIN'];
|
|
break;
|
|
}//
|
|
|
|
}//protected function tbMarkMarginX
|
|
|
|
|
|
/*
|
|
Characteristics constants for Data Type:
|
|
EVERY CELL FROM THE TABLE IS A MULTICELL
|
|
T_COLOR - text color = array(r,g,b);
|
|
T_SIZE - text size
|
|
T_FONT - text font - font type = "Arial", "Times"
|
|
T_ALIGN - text align - "RLCJ"
|
|
V_ALIGN - text vertical alignment - "TMB"
|
|
T_TYPE - text type (Bold Italic etc)
|
|
LN_SPACE - space between lines
|
|
BG_COLOR - background color = array(r,g,b);
|
|
BRD_COLOR - border color = array(r,g,b);
|
|
BRD_SIZE - border size --
|
|
BRD_TYPE - border size -- up down, with border without!!! etc
|
|
BRD_TYPE_NEW_PAGE - border type on new page - this is user only if specified(<>'')
|
|
|
|
all these settings conform to the settings from the multicell functions!!!!
|
|
*/
|
|
|
|
/**
|
|
* Sets the Data Type. This Data Type is used as the default type for datas in the entire table. Of corse the user can
|
|
* specify for every cell some specific data types
|
|
* $aDataType=
|
|
* array(
|
|
* 0=>array(
|
|
* "WIDTH" => 10,
|
|
* "T_COLOR" => array(120,120,120),
|
|
* "T_SIZE" => 5,
|
|
* ...
|
|
* "TEXT" => "Header text 1"
|
|
* ),
|
|
* 1=>array(
|
|
* ...
|
|
* ),
|
|
* );
|
|
*
|
|
* where 0,1... are the column number
|
|
*
|
|
* @access public
|
|
* @param array - $aDataType - Array Containing the Data Type
|
|
* @return void
|
|
*/
|
|
public function tbSetDataType($aDataType){
|
|
$this->aTableDataType = $aDataType;
|
|
}//function tbSetDataType
|
|
|
|
|
|
/**
|
|
* Sets the Table Type
|
|
*
|
|
* $aTableType = array(
|
|
* "BRD_COLOR"=> array (120,120,120), //border color
|
|
* "BRD_SIZE"=>5), //border line width
|
|
* "iColumnsNr"=>5), //the number of columns
|
|
* "TB_ALIGN"=>"L"), //the align of the table, possible values = L, R, C equivalent to Left, Right, Center
|
|
* 'L_MARGIN' => 0// left margin... reference from this->lmargin values
|
|
* );
|
|
*
|
|
* @access public
|
|
* @param array $aTableType - array containing the Table Type
|
|
* @return void
|
|
*/
|
|
public function tbSetTableType($aTableType){
|
|
|
|
if (isset($aTableType['iColumnsNr'])) $this->iColumnsNr = $aTableType['iColumnsNr'];
|
|
if (!isset($aTableType['L_MARGIN'])) $aTableType['L_MARGIN']=0;//default values
|
|
|
|
$this->aTableType = $aTableType;
|
|
$this->tbMarkMarginX();
|
|
|
|
}//function tbSetTableType
|
|
|
|
|
|
/**
|
|
* Draws the Table Border
|
|
*
|
|
* @access public
|
|
* @param void
|
|
* @return void
|
|
*/
|
|
public function tbDrawBorder(){
|
|
|
|
if ( ! $this->bTableBorderDraw ) return;
|
|
|
|
if ( ! $this->bDataOnCurrentPage) return; //there was no data on the current page
|
|
|
|
//set the colors
|
|
list($r, $g, $b) = $this->aTableType['BRD_COLOR'];
|
|
$this->SetDrawColor($r, $g, $b);
|
|
|
|
//set the line width
|
|
$this->SetLineWidth($this->aTableType['BRD_SIZE']);
|
|
|
|
//draw the border
|
|
$this->Rect(
|
|
$this->iTableStartX,
|
|
$this->iTableStartY,
|
|
$this->tbGetWidth(),
|
|
$this->GetY() - $this->iTableStartY);
|
|
|
|
}//function tbDrawBorder
|
|
|
|
|
|
/**
|
|
* End Page Special Border Draw. This is called in the case of a Page Split
|
|
*
|
|
* @access protected
|
|
* @param void
|
|
* @return void
|
|
*/
|
|
protected function _tbEndPageBorder(){
|
|
if (isset($this->aTableType['BRD_TYPE_END_PAGE'])){
|
|
|
|
if (strpos($this->aTableType['BRD_TYPE_END_PAGE'], 'B') >= 0){
|
|
|
|
//set the colors
|
|
list($r, $g, $b) = $this->aTableType['BRD_COLOR'];
|
|
$this->SetDrawColor($r, $g, $b);
|
|
|
|
//set the line width
|
|
$this->SetLineWidth($this->aTableType['BRD_SIZE']);
|
|
|
|
//draw the line
|
|
$this->Line($this->table_startx, $this->GetY(), $this->table_startx + $this->tbGetWidth(), $this->GetY());
|
|
}//fi
|
|
}//fi
|
|
}//function _tbEndPageBorder
|
|
|
|
/**
|
|
* Returns the table width in user units
|
|
*
|
|
* @access public
|
|
* @param void
|
|
* @return integer - table width
|
|
*/
|
|
public function tbGetWidth()
|
|
{
|
|
//calculate the table width
|
|
$tb_width = 0;
|
|
|
|
for ($i=0; $i < $this->iColumnsNr; $i++){
|
|
$tb_width += $this->aTableHeaderType[0][$i]['WIDTH'];
|
|
}
|
|
|
|
return $tb_width;
|
|
}//tbGetWidth
|
|
|
|
|
|
/**
|
|
* Aligns the table to the Start X point
|
|
*
|
|
* @access protected
|
|
* @param void
|
|
* @return void
|
|
*
|
|
*/
|
|
protected function _tbAlign(){
|
|
$this->SetX($this->iTableStartX);
|
|
}//function _tbAlign(){
|
|
|
|
|
|
/**
|
|
* "Draws the Header".
|
|
* More specific puts the data from the Header Cache into the Data Cache
|
|
*
|
|
* @access public
|
|
* @param void
|
|
* @return void
|
|
*/
|
|
public function tbDrawHeader(){
|
|
|
|
foreach($this->aHeaderCache as $val){
|
|
$this->aDataCache[] = $val;
|
|
}
|
|
}//function tbDrawHeader
|
|
|
|
|
|
/**
|
|
* Adds a line to the Table Data or Header Cache.
|
|
* Call this function after the table initialization, table, header and data types are set
|
|
*
|
|
* @access public
|
|
* @param array $data - Data to be Drawed
|
|
* @param booleab $header - Array Containing data is Header Data or Data Data
|
|
* @return null
|
|
*/
|
|
public function tbDrawData($data, $header = true){
|
|
$this->_tbAddDataToCache($data);
|
|
}
|
|
|
|
/**
|
|
* Adds the data to the cache
|
|
*
|
|
* @access protected
|
|
* @param array $data - array containing the data to be added
|
|
* @param string $sDataType - data type. Can be 'data' or 'header'. Depending on this data the $data is put in the selected cache
|
|
* @return void
|
|
*/
|
|
protected function _tbAddDataToCache($data, $sDataType = 'data'){
|
|
|
|
|
|
if (!is_array($data)) {
|
|
//this is fatal error
|
|
trigger_error("Invalid data value 0x00012. (not array)", E_USER_ERROR);
|
|
}
|
|
|
|
//IF UTF8 Support is needed then
|
|
if (isset($this->utf8_support) && ($this->utf8_support)){
|
|
for($i=0; $i < $this->iColumnsNr; $i++){
|
|
$data[$i]['TEXT'] = utf8_decode($data[$i]['TEXT']);
|
|
}
|
|
|
|
//keep the compatibility with the "old" fpdf utf8 support.
|
|
if (isset($this->utf8_decoded)) $this->utf8_decoded = true;
|
|
}
|
|
|
|
if ($sDataType == 'data')
|
|
$aDataCache = & $this->aDataCache;
|
|
elseif ($sDataType == 'header')
|
|
$aDataCache = & $this->aHeaderCache;
|
|
|
|
$aRowSpan = array();
|
|
|
|
|
|
$hm = 0;
|
|
$rowspan = false;
|
|
|
|
/**
|
|
* If datacache is empty initialize it
|
|
*/
|
|
if (count($aDataCache) > 0) $aLastDataCache = end($aDataCache);
|
|
else $aLastDataCache = array();
|
|
|
|
//this variable will contain the active colspans
|
|
$iActiveColspan = 0;
|
|
|
|
//calculate the maximum height of the cells
|
|
for($i=0; $i < $this->iColumnsNr; $i++){
|
|
|
|
if (!isset($data[$i]['TEXT']) || ($data[$i]['TEXT']=='')) $data[$i]['TEXT'] = ' ';
|
|
if (!isset($data[$i]['T_FONT'])) $data[$i]['T_FONT'] = $this->aTableDataType[$i]['T_FONT'];
|
|
if (!isset($data[$i]['T_TYPE'])) $data[$i]['T_TYPE'] = $this->aTableDataType[$i]['T_TYPE'];
|
|
if (!isset($data[$i]['T_SIZE'])) $data[$i]['T_SIZE'] = $this->aTableDataType[$i]['T_SIZE'];
|
|
if (!isset($data[$i]['T_COLOR'])) $data[$i]['T_COLOR'] = $this->aTableDataType[$i]['T_COLOR'];
|
|
if (!isset($data[$i]['T_ALIGN'])) $data[$i]['T_ALIGN'] = $this->aTableDataType[$i]['T_ALIGN'];
|
|
if (!isset($data[$i]['V_ALIGN'])) $data[$i]['V_ALIGN'] = $this->aTableDataType[$i]['V_ALIGN'];
|
|
if (!isset($data[$i]['LN_SIZE'])) $data[$i]['LN_SIZE'] = $this->aTableDataType[$i]['LN_SIZE'];
|
|
if (!isset($data[$i]['BRD_SIZE'])) $data[$i]['BRD_SIZE'] = $this->aTableDataType[$i]['BRD_SIZE'];
|
|
if (!isset($data[$i]['BRD_COLOR'])) $data[$i]['BRD_COLOR'] = $this->aTableDataType[$i]['BRD_COLOR'];
|
|
if (!isset($data[$i]['BRD_TYPE'])) $data[$i]['BRD_TYPE'] = $this->aTableDataType[$i]['BRD_TYPE'];
|
|
if (!isset($data[$i]['BG_COLOR'])) $data[$i]['BG_COLOR'] = $this->aTableDataType[$i]['BG_COLOR'];
|
|
if (!isset($data[$i]['COLSPAN'])) $data[$i]['COLSPAN'] = 1; else $data[$i]['COLSPAN'] = (int) $data[$i]['COLSPAN'];
|
|
if (!isset($data[$i]['ROWSPAN'])) $data[$i]['ROWSPAN'] = 1; else $data[$i]['ROWSPAN'] = (int) $data[$i]['ROWSPAN'];
|
|
$data[$i]['HEIGHT'] = 0; //default HEIGHT
|
|
$data[$i]['SKIP'] = false; //default SKIP (don't skip)
|
|
$data[$i]['CELL_WIDTH'] = $this->aTableHeaderType[0][$i]['WIDTH']; //copy this from the header settings
|
|
$data[$i]['ROWSPAN_PRIMARY'] = FALSE; //==true then this row has generated the rowspan
|
|
$data[$i]['ROWSPAN_ID'] = 0; //rowspan ID
|
|
$data[$i]['HEIGHT'] = 0; //default HEIGHT
|
|
|
|
if ($data[$i]['LN_SIZE'] <= 0){
|
|
trigger_error("Invalid Line Size {$data[$i]['LN_SIZE']}", E_USER_ERROR);
|
|
}
|
|
|
|
|
|
//if there is an active colspan on this line we just skip this cell
|
|
if ($iActiveColspan > 1){
|
|
$data[$i]['SKIP'] = true;
|
|
//if ($i>0) $data[$i]['ROWSPAN'] = $data[$i-1]['ROWSPAN'];
|
|
$iActiveColspan --;
|
|
continue;
|
|
}
|
|
|
|
|
|
if (!empty($aLastDataCache)){
|
|
|
|
//there was at least one row before
|
|
|
|
if ( $aLastDataCache['DATA'][$i]['ROWSPAN'] > 1 ){
|
|
/**
|
|
* This is rowspan over this cell. The cell will be ignored but some characteristics are kept
|
|
*/
|
|
|
|
//this cell will be skipped
|
|
$data[$i]['SKIP'] =true;
|
|
//decrease the rowspan value... one line less to be spanned
|
|
$data[$i]['ROWSPAN'] = $aLastDataCache['DATA'][$i]['ROWSPAN'] - 1;
|
|
$data[$i]['ROWSPAN_ID'] = $aLastDataCache['DATA'][$i]['ROWSPAN_ID'];
|
|
$data[$i]['ROWSPAN_PRIMARY'] = false;
|
|
//copy the colspan from the last value
|
|
$data[$i]['COLSPAN'] = $aLastDataCache['DATA'][$i]['COLSPAN'];
|
|
//cell with is the same as the one from the line before it
|
|
$data[$i]['CELL_WIDTH'] = $aLastDataCache['DATA'][$i]['CELL_WIDTH'];
|
|
|
|
if ($data[$i]['COLSPAN'] > 1){
|
|
$iActiveColspan = $data[$i]['COLSPAN'];
|
|
}
|
|
|
|
continue; //jump to the next column
|
|
|
|
}//if
|
|
|
|
}//if
|
|
|
|
|
|
//set the font settings
|
|
$this->SetFont( $data[$i]['T_FONT'],
|
|
$data[$i]['T_TYPE'],
|
|
$data[$i]['T_SIZE']);
|
|
|
|
|
|
/**
|
|
* If we have colspan then we ignore the "colspanned" cells
|
|
*/
|
|
if ( $data[$i]['COLSPAN'] > 1 ){
|
|
|
|
for ($j = 1; $j < $data[$i]['COLSPAN']; $j++){
|
|
//if there is a colspan, then calculate the number of lines also with the with of the next cell
|
|
if (($i + $j) < $this->iColumnsNr)
|
|
$data[$i]['CELL_WIDTH'] += $this->aTableHeaderType[0][$i + $j]['WIDTH'];
|
|
}//for
|
|
|
|
}//if
|
|
|
|
//add the cells that are with rowspan to the rowspan array - this is used later
|
|
if ( $data[$i]['ROWSPAN'] > 1 ){
|
|
$data[$i]['ROWSPAN_PRIMARY'] = true;
|
|
$this->iRowSpanID++;
|
|
$data[$i]['ROWSPAN_ID'] = $this->iRowSpanID;
|
|
$aRowSpan[] = $i;
|
|
}
|
|
|
|
|
|
//$MaxLines = floor($AvailPageH / $data[$i]['LN_SIZE']);//floor this value, must be the lowest possible
|
|
|
|
if (!isset($data[$i]['TEXT_STRLINES'])) $data[$i]['TEXT_STRLINES'] = $this->mt_StringToLines($data[$i]['CELL_WIDTH'], $data[$i]['TEXT']);
|
|
$data[$i]['CELL_LINES'] = count($data[$i]['TEXT_STRLINES']);
|
|
|
|
/**
|
|
* IF THERE IS ROWSPAN ACTIVE Don't include this cell Height in the calculation.
|
|
* This will be calculated later with the sum of all heights
|
|
*/
|
|
|
|
$data[$i]['HEIGHT'] = $data[$i]['LN_SIZE'] * $data[$i]['CELL_LINES'];
|
|
|
|
if ( $data[$i]['ROWSPAN'] == 1 ){
|
|
$hm = max($hm, $data[$i]['HEIGHT']);//this would be the normal height
|
|
}
|
|
|
|
if ( $data[$i]['COLSPAN'] > 1 ){
|
|
//just skip the other cells
|
|
$iActiveColspan = $data[$i]['COLSPAN'];
|
|
}//if
|
|
|
|
}//for($i=0; $i < $this->iColumnsNr; $i++)
|
|
|
|
|
|
$aDataCache[] = array(
|
|
'HEIGHT' => $hm, //THIS LINE MAXIMUM HEIGHT
|
|
'DEFAULT_HEIGHT' => $hm, //THIS LINE DEFAULT MAXIMUM HEIGHT
|
|
'DEFAULT_HEIGHT_SET' => true,
|
|
'DATATYPE' => $sDataType, //The data Type - Data/Header
|
|
'DATA' => $data, //this line's data
|
|
'ROWSPAN' => $aRowSpan //rowspan ID array
|
|
);
|
|
|
|
//we set the rowspan in cache variable to true if we have a rowspan
|
|
if (! empty($aRowSpan) && (!$this->bRowSpanInCache)){
|
|
$this->bRowSpanInCache = true;
|
|
}
|
|
|
|
return;
|
|
}//function _tbAddDataToCache
|
|
|
|
|
|
|
|
/**
|
|
* Parses the Data Cache and calculates the maximum Height of each row. Normally the cell Height of a row is calculated
|
|
* when the data's are added, but when that row is involved in a Rowspan then it's Height can change!
|
|
*
|
|
* @access protected
|
|
* @param integer $iStartIndex - the index from which to parse
|
|
* @param string $sCacheType - what type has the cache - possible values: 'header' && 'data'
|
|
* @return void
|
|
*/
|
|
protected function _tbCacheParseRowspan($iStartIndex = 0, $sCacheType = 'data'){
|
|
|
|
if ($sCacheType == 'data')
|
|
$aDataCache = & $this->aDataCache;
|
|
else
|
|
$aDataCache = & $this->aHeaderCache;
|
|
|
|
$aRowSpans = array();
|
|
|
|
$iItems = count($aDataCache);
|
|
|
|
for ($ix = $iStartIndex; $ix < $iItems; $ix++){
|
|
|
|
$val = & $aDataCache[$ix];
|
|
|
|
if (!in_array($val['DATATYPE'], array('data', 'header') )) continue;
|
|
|
|
//if there is no rowspan jump over
|
|
if (empty($val['ROWSPAN'])) continue;
|
|
|
|
foreach ($val['ROWSPAN'] as $k){
|
|
|
|
#$val['HEIGHT'] = $val['DEFAULT_HEIGHT'];
|
|
|
|
if ($val['DATA'][$k]['ROWSPAN'] < 1) continue; //skip the rows without rowspan
|
|
|
|
/**
|
|
if ($val['DEFAULT_HEIGHT_SET'] == false){
|
|
$val['HEIGHT'] = $val['DEFAULT_HEIGHT'];
|
|
}
|
|
*/
|
|
|
|
$aRowSpans[] = array(
|
|
'row_id' => $ix,
|
|
'cell_id' => &$val['DATA'][$k]
|
|
);
|
|
|
|
$h_rows = 0;
|
|
|
|
//calculate the sum of the Heights for the lines that are included in the rowspan
|
|
for ( $i=0; $i < $val['DATA'][$k]['ROWSPAN']; $i++){
|
|
if (isset($aDataCache[$ix + $i]))
|
|
$h_rows += $aDataCache[$ix + $i]['HEIGHT'];
|
|
}
|
|
|
|
//this is the cell height that makes the rowspan
|
|
$h_cell = $val['DATA'][$k]['HEIGHT'];
|
|
|
|
//if the
|
|
//$val['DATA'][$k]['HEIGHT_MAX'] = max($h_cell, $h_rows);
|
|
|
|
/**
|
|
* The Rowspan Cell's Height is bigger than the sum of the Rows Heights that he is spanning
|
|
* In this case we have to increase the height of each row
|
|
*/
|
|
if ($h_cell > $h_rows){
|
|
//calculate the value of the HEIGHT to be added to each row
|
|
$add_on = ($h_cell - $h_rows) / $val['DATA'][$k]['ROWSPAN'];
|
|
for ( $i=0; $i < $val['DATA'][$k]['ROWSPAN']; $i++){
|
|
if (isset($aDataCache[$ix + $i])){
|
|
$aDataCache[$ix + $i]['HEIGHT'] += $add_on;
|
|
$aDataCache[$ix + $i]['DEFAULT_HEIGHT_SET'] = false;
|
|
}
|
|
}//for
|
|
}//
|
|
|
|
}//foreach
|
|
}//foreach
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Calculate the height of each cell that makes the rowspan.
|
|
* The height of this cell is the sum of the heights of the rows where the rowspan occurs
|
|
*/
|
|
|
|
foreach ($aRowSpans as $val1){
|
|
$h_rows = 0;
|
|
//calculate the sum of the Heights for the lines that are included in the rowspan
|
|
for ( $i=0; $i < $val1['cell_id']['ROWSPAN']; $i++){
|
|
if (isset($aDataCache[$val1['row_id'] + $i]))
|
|
$h_rows += $aDataCache[$val1['row_id'] + $i]['HEIGHT'];
|
|
}
|
|
$val1['cell_id']['HEIGHT_MAX'] = $h_rows;
|
|
if (false == $this->bTableSplit){
|
|
$aDataCache[$val1['row_id']]['HEIGHT_ROWSPAN'] = $h_rows;
|
|
}
|
|
}
|
|
|
|
}//function _tbCacheParseRowspan
|
|
|
|
|
|
/**
|
|
* Splits a cell into 2 cells. The first cell will have maximum $iHeightMax height
|
|
*
|
|
* @access protected
|
|
* @param array - $aCellData - array containing cell data
|
|
* @param integer - $iRowHeight - the Height of the row that contains this cell
|
|
* @param integer - $iHeightMax - the maximum Height of the first cell
|
|
* @return $aNewData - the second cell value
|
|
*/
|
|
protected function tbSplitCell(&$aCellData, $iHeightRow = 0, $iHeightMax = 0){
|
|
|
|
//$aTData will contain the second cell data
|
|
$aCell2Data = $aCellData;
|
|
$fHeightSplit = 0; //The Height where the split will be made
|
|
|
|
/**
|
|
* Have to look at the V_ALIGN of the cells and calculate exaclty for each cell how much space is left
|
|
*/
|
|
switch($aCellData['V_ALIGN']){
|
|
case 'M':
|
|
//Middle align
|
|
$x = ($iHeightRow - $aCellData['HEIGHT']) / 2;
|
|
|
|
if ($iHeightMax <= $x){
|
|
//CASE 1
|
|
$fHeightSplit = 0;
|
|
$aCellData['V_OFFSET'] = $x - $iHeightMax;
|
|
$aCellData['V_ALIGN'] = 'T';//top align
|
|
|
|
}elseif( ($x + $aCellData['HEIGHT']) >= $iHeightMax){
|
|
//CASE 2
|
|
$fHeightSplit = $iHeightMax - $x;
|
|
$aCellData['V_ALIGN'] = 'B';//top align
|
|
$aCell2Data['V_ALIGN'] = 'T';//top align
|
|
}else{//{
|
|
//CASE 3
|
|
$fHeightSplit = $iHeightMax;
|
|
$aCellData['V_OFFSET'] = $x;
|
|
$aCellData['V_ALIGN'] = 'B';//bottom align
|
|
}
|
|
|
|
break;
|
|
case 'B':
|
|
//Bottom Align
|
|
if (($iHeightRow - $aCellData['HEIGHT']) > $iHeightMax){
|
|
//if the text has enough place on the other page then we show nothing on this page
|
|
$fHeightSplit = 0;
|
|
}else{
|
|
//calculate the space that the text needs on this page
|
|
$fHeightSplit = $iHeightMax - ($iHeightRow - $aCellData['HEIGHT']);
|
|
}
|
|
|
|
break;
|
|
|
|
case 'T':
|
|
default:
|
|
//Top Align and default align
|
|
$fHeightSplit = $iHeightMax;
|
|
break;
|
|
}
|
|
|
|
//calculate the number of the lines that have space on the $fHeightSplit
|
|
$iNoLinesCPage = floor($fHeightSplit / $aCellData['LN_SIZE']);
|
|
//if the number of the lines is bigger than the number of the lines in the cell decrease the number of the lines
|
|
if ($iNoLinesCPage > $aCellData['CELL_LINES']){
|
|
$iNoLinesCPage = $aCellData['CELL_LINES'];
|
|
}
|
|
|
|
$aCellData['TEXT_SPLITLINES'] = array_splice($aCellData['TEXT_STRLINES'], $iNoLinesCPage);
|
|
#$aCellData['CELL_LINES'] = $iNoLinesCPage;
|
|
$aCellData['CELL_LINES'] = count($aCellData['TEXT_STRLINES']);
|
|
|
|
//calculate the new height for this cell
|
|
$aCellData['HEIGHT'] = $aCellData['LN_SIZE'] * $aCellData['CELL_LINES'];
|
|
|
|
#$fRowH = max($fRowH, $aData[$j]['HEIGHT'] );
|
|
|
|
//this is the second cell from the splitted one
|
|
$aCell2Data['TEXT_STRLINES'] = $aCellData['TEXT_SPLITLINES'];
|
|
$aCell2Data['CELL_LINES'] = count ($aCell2Data['TEXT_STRLINES']);
|
|
$aCell2Data['HEIGHT'] = $aCell2Data['LN_SIZE'] * $aCell2Data['CELL_LINES'];
|
|
|
|
return array($aCell2Data, $fHeightSplit);
|
|
|
|
}//function tbSplitCell()
|
|
|
|
/**
|
|
* Splits the Data Cache into Pages.
|
|
* Parses the Data Cache and when it is needed then a "new page" command is inserted into the Data Cache.
|
|
*
|
|
* @access protected
|
|
* @param void
|
|
* @return void
|
|
*/
|
|
protected function _tbCachePaginate(){
|
|
|
|
$iPageHeight = $this->PageHeight();
|
|
|
|
/**
|
|
* This Variable will contain the remained page Height
|
|
*/
|
|
$iLeftHeight = $iPageHeight - $this->GetY() + $this->tMargin;
|
|
|
|
//the number of lines that the header contains
|
|
if ($this->bTableHeaderDraw){
|
|
$iHeaderLines = count($this->aHeaderCache);
|
|
}else {
|
|
$iHeaderLines = 0;
|
|
}
|
|
|
|
$bWasData = true; //can be deleted
|
|
$iLastOkKey = -1; //can be deleted
|
|
|
|
$bDataOnThisPage = false;
|
|
$bHeaderOnThisPage = false;
|
|
$iLastDataKey = 0;
|
|
|
|
|
|
//will contain the rowspans on the current page, EMPTY THIS VARIABLE AT EVERY NEW PAGE!!!
|
|
$aRowSpans = array();
|
|
|
|
$aDC = & $this->aDataCache;
|
|
|
|
$iItems = count($aDC);
|
|
|
|
for ($i=0; $i < $iItems; $i++){
|
|
|
|
$val = & $aDC[$i];
|
|
|
|
$bIsHeader = $val['DATATYPE'] == 'header';
|
|
|
|
if (($bIsHeader) && ($bWasData)){
|
|
$iLastDataKey = $iLastOkKey;
|
|
}//fi
|
|
|
|
if (isset($val['ROWSPAN'])){
|
|
|
|
foreach ($val['ROWSPAN'] as $k=>$v){
|
|
$aRowSpans[] = array($i, $v);
|
|
$aDC[$i]['DATA'][$v]['HEIGHT_LEFT_RW'] = $iLeftHeight;
|
|
}//foreach
|
|
|
|
}//fi
|
|
|
|
$iLeftHeightLast = $iLeftHeight;
|
|
|
|
$iRowHeight = $val['HEIGHT'];
|
|
$iRowHeightRowspan = 0;
|
|
if ((false == $this->bTableSplit) && (isset($val['HEIGHT_ROWSPAN']))){
|
|
$iRowHeightRowspan = $val['HEIGHT_ROWSPAN'];
|
|
}
|
|
|
|
$iLeftHeightRowspan = $iLeftHeight - $iRowHeightRowspan;
|
|
$iLeftHeight -= $iRowHeight;
|
|
|
|
if (($iLeftHeight >= 0) && ($iLeftHeightRowspan >=0)){
|
|
//this row has enough space on the page
|
|
if (true == $bIsHeader) {
|
|
$bHeaderOnThisPage = true;
|
|
}else{
|
|
$iLastDataKey = $i;
|
|
$bDataOnThisPage = true;
|
|
}
|
|
$iLastOkKey = $i;
|
|
$bLastOkType = $bIsHeader;
|
|
|
|
}else{
|
|
|
|
/**
|
|
* THERE IS NOT ENOUGH SPACE ON THIS PAGE - HAVE TO SPLIT
|
|
* Decide the split type
|
|
*
|
|
* SITUATION 1:
|
|
* IF
|
|
* - the current data type is header OR
|
|
* - on this page we had no data(that means untill this point was nothing or just header) AND bTableSplit is off
|
|
* THEN we just add new page on the positions of LAST DATA KEY ($iLastDataKey)
|
|
*
|
|
* SITUATION 2:
|
|
* IF
|
|
* - TableSplit is OFF and the height of the current data is bigger than the Page Height minus (-) Header Height
|
|
* THEN we split the current cell
|
|
*
|
|
* SITUATION 3:
|
|
* - normal split flow
|
|
*
|
|
*/
|
|
|
|
//use this switch for flow control
|
|
switch(1){
|
|
case 1:
|
|
|
|
//SITUATION 1:
|
|
if ((true == $bIsHeader) OR ((false == $bHeaderOnThisPage) AND (false == $bDataOnThisPage) AND (false == $this->bTableSplit)) ){
|
|
$iItems = $this->tbInsertNewPage($iLastDataKey, null, (!$bIsHeader) && (!$bHeaderOnThisPage));
|
|
break;//exit from switch(1);
|
|
}
|
|
|
|
$bSplitCommand = $this->bTableSplit;
|
|
|
|
//SITUATION 2:
|
|
if ($val['HEIGHT'] > ($iPageHeight - $this->iHeaderHeight)){
|
|
//even if the bTableSplit is OFF - split the data!!!
|
|
$bSplitCommand = true;
|
|
}
|
|
|
|
if (true == $bSplitCommand){
|
|
/***************************************************
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* SPLIT IS ACTIVE
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
***************************************************/
|
|
|
|
//if we can draw on this page at least one line from the cells
|
|
$bAtLeastOneLine = false;
|
|
|
|
$aData = $val['DATA'];
|
|
|
|
$fRowH = $iLeftHeightLast;
|
|
#$fRowH = 0;
|
|
$fRowHTdata = 0;
|
|
|
|
$aTData = array();
|
|
|
|
//parse the data's on this line
|
|
for( $j=0; $j < $this->iColumnsNr; $j++){
|
|
|
|
$aTData[$j] = $aData[$j];
|
|
|
|
/**
|
|
* The cell is Skipped or is a Rowspan. For active split we handle rowspanned cells later
|
|
*/
|
|
if (($aData[$j]['SKIP'] === TRUE) || ($aData[$j]['ROWSPAN'] > 1)) continue;
|
|
|
|
list($aTData[$j]) = $this->tbSplitCell($aData[$j], $val['HEIGHT'], $iLeftHeightLast);
|
|
|
|
$fRowH = max($fRowH, $aData[$j]['HEIGHT'] );
|
|
$fRowHTdata = max($fRowHTdata, $aTData[$j]['HEIGHT'] );
|
|
|
|
}//for
|
|
|
|
$val['HEIGHT'] = $fRowH;
|
|
$val['DATA'] = $aData;
|
|
|
|
$v_new = $val;
|
|
$v_new['HEIGHT'] = $fRowHTdata;
|
|
$v_new['ROWSPAN'] = array();
|
|
/**
|
|
* Parse separately the rows with the ROWSPAN
|
|
*/
|
|
|
|
|
|
$bNeedParseCache = false;
|
|
|
|
$aRowSpan = $aDC[$i]['ROWSPAN'];
|
|
|
|
|
|
foreach ($aRowSpans as $rws_key => $rws){
|
|
|
|
$rData = & $aDC[$rws[0]]['DATA'][$rws[1]];
|
|
|
|
if ($rData['HEIGHT_MAX'] > $rData['HEIGHT_LEFT_RW']){
|
|
/**
|
|
* This cell has a rowspan in IT
|
|
* We have to split this cell only if its height is bigger than the space to the end of page
|
|
* that was set when the cell was parsed. HEIGHT_LEFT_RW
|
|
*/
|
|
|
|
list($aTData[$rws[1]], $fHeightSplit) = $this->tbSplitCell($rData, $rData['HEIGHT_MAX'] , $rData['HEIGHT_LEFT_RW']);
|
|
|
|
$rData['HEIGHT_MAX'] = $rData['HEIGHT_LEFT_RW'];
|
|
|
|
$aTData[$rws[1]]['ROWSPAN'] = $aTData[$rws[1]]['ROWSPAN'] - ($i - $rws[0]);
|
|
|
|
$v_new['ROWSPAN'][] = $rws[1];
|
|
|
|
$bNeedParseCache = true;
|
|
}//fi
|
|
}//foreach
|
|
|
|
$v_new['DATA'] = $aTData;
|
|
|
|
//Insert the new page, and get the new number of the lines
|
|
$iItems = $this->tbInsertNewPage($i, $v_new);
|
|
|
|
if ($bNeedParseCache) $this->_tbCacheParseRowspan($i+1);
|
|
|
|
}else{
|
|
|
|
/***************************************************
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* SPLIT IS INACTIVE
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
***************************************************/
|
|
|
|
/**
|
|
* Check if we have a rowspan that needs to be splitted
|
|
*/
|
|
|
|
#var_dump($aRowSpans); die();
|
|
$bNeedParseCache = false;
|
|
|
|
$aRowSpan = $aDC[$i]['ROWSPAN'];
|
|
|
|
foreach ($aRowSpans as $rws){
|
|
|
|
$rData = & $aDC[$rws[0]]['DATA'][$rws[1]];
|
|
|
|
if ($rws[0] == $i)continue; //means that this was added at the last line, that will not appear on this page
|
|
|
|
if ($rData['HEIGHT_MAX'] > $rData['HEIGHT_LEFT_RW']){
|
|
/**
|
|
* This cell has a rowspan in IT
|
|
* We have to split this cell only if its height is bigger than the space to the end of page
|
|
* that was set when the cell was parsed. HEIGHT_LEFT_RW
|
|
*/
|
|
|
|
list($aTData, $fHeightSplit) = $this->tbSplitCell($rData, $rData['HEIGHT_MAX'] , $rData['HEIGHT_LEFT_RW'] - $iLeftHeightLast);
|
|
|
|
$rData['HEIGHT_MAX'] = $rData['HEIGHT_LEFT_RW'] - $iLeftHeightLast;
|
|
|
|
$aTData['ROWSPAN'] = $aTData['ROWSPAN'] - ($i - $rws[0]);
|
|
|
|
$aDC[$i]['DATA'][$rws[1]] = $aTData;
|
|
|
|
$aRowSpan[] = $rws[1];
|
|
$aDC[$i]['ROWSPAN'] = $aRowSpan;
|
|
|
|
$bNeedParseCache = true;
|
|
|
|
}//fi
|
|
}//for
|
|
|
|
if ($bNeedParseCache) $this->_tbCacheParseRowspan($i);
|
|
|
|
//Insert the new page, and get the new number of the lines
|
|
$iItems = $this->tbInsertNewPage($i);
|
|
|
|
}//else
|
|
|
|
|
|
}//switch(1);
|
|
|
|
$iLeftHeight = $iPageHeight;
|
|
$aRowSpans = array();
|
|
$bDataOnThisPage = false; //new page
|
|
|
|
}//else
|
|
|
|
|
|
}//for
|
|
|
|
}//function _tbCachePaginate
|
|
|
|
|
|
|
|
/**
|
|
* Inserts a new page in the Data Cache, after the specified Index. If sent then also a new data is inserted after the new page
|
|
*
|
|
* @access protected
|
|
* @param integer - $iIndex - after this index is the new page inserted
|
|
* @param resource - $rNewData - default null. If specified this data is inserted after the new page
|
|
* @param boolean - $bInsertHeader - true then the header is inserted, false - no header is inserted
|
|
* @return integer - the new number of lines that the Data Cache Contains.
|
|
*/
|
|
protected function tbInsertNewPage($iIndex, $rNewData = null, $bInsertHeader = true){
|
|
|
|
//the number of lines that the header contains
|
|
if ((true == $this->bTableHeaderDraw) && (true == $bInsertHeader)){
|
|
$iHeaderLines = count($this->aHeaderCache);
|
|
}else {
|
|
$iHeaderLines = 0;
|
|
}
|
|
|
|
$aDC = & $this->aDataCache;
|
|
$iItems = count($aDC); //the number of elements in the cache
|
|
|
|
//if we have a NewData to be inserted after the new page then we have to shift the data with 1
|
|
if( null != $rNewData) $iShift = 1;
|
|
else $iShift = 0;
|
|
|
|
//shift the array with the number of lines that the header contains + one line for the new page
|
|
for($j = $iItems; $j > $iIndex; $j--){
|
|
$aDC[$j + $iHeaderLines + $iShift] = $aDC[$j - 1];
|
|
}//for
|
|
|
|
$aDC[$iIndex + $iShift] = array(
|
|
'HEIGHT' => 0,
|
|
'DATATYPE' => 'new_page',
|
|
);
|
|
|
|
$j = $iShift;
|
|
|
|
|
|
if ($iHeaderLines > 0){
|
|
//only if we have a header
|
|
|
|
//insert the header into the corresponding positions
|
|
foreach ($this->aHeaderCache as $rHeaderVal){
|
|
$j++;
|
|
$aDC[$iIndex + $j] = $rHeaderVal;
|
|
}//foreach
|
|
|
|
}//fi
|
|
|
|
if( 1 == $iShift ){
|
|
$j++;
|
|
$aDC[$iIndex + $j] = $rNewData;
|
|
}//fi
|
|
|
|
/**/
|
|
$this->bDataOnCurrentPage = false;
|
|
|
|
return count($aDC);
|
|
|
|
}//function tbInsertNewPage
|
|
|
|
|
|
|
|
/**
|
|
* Sends all the Data Cache to the PDF Document.
|
|
* This is the REAL Function that Outputs the table data to the pdf document
|
|
*
|
|
* @access protected
|
|
* @param void
|
|
* @return void
|
|
*/
|
|
protected function _tbCachePrepOutputData(){
|
|
|
|
$aDataCache = & $this->aDataCache;
|
|
|
|
$iItems = count($aDataCache);
|
|
|
|
for ($k=0; $k < $iItems; $k++){
|
|
|
|
$val = & $aDataCache[$k];
|
|
|
|
//each array contains one line
|
|
$this->_tbAlign();
|
|
|
|
if ($val['DATATYPE'] == 'new_page') {
|
|
//add a new page
|
|
$this->tbAddPage();
|
|
continue;
|
|
}
|
|
|
|
$data = &$val['DATA'];
|
|
|
|
//Draw the cells of the row
|
|
for( $i = 0; $i < $this->iColumnsNr; $i++ )
|
|
{
|
|
|
|
//Save the current position
|
|
$x=$this->GetX();
|
|
$y=$this->GetY();
|
|
|
|
if ($data[$i]['SKIP'] === FALSE){
|
|
|
|
if (isset($data[$i]['HEIGHT_MAX']))
|
|
$h = $data[$i]['HEIGHT_MAX'];
|
|
else
|
|
$h = $val['HEIGHT'];
|
|
|
|
|
|
//border size BRD_SIZE
|
|
$this->SetLineWidth($data[$i]['BRD_SIZE']);
|
|
|
|
//fill color = BG_COLOR
|
|
list($r, $g, $b) = $data[$i]['BG_COLOR'];
|
|
$this->SetFillColor($r, $g, $b);
|
|
|
|
//Draw Color = BRD_COLOR
|
|
list($r, $g, $b) = $data[$i]['BRD_COLOR'];
|
|
$this->SetDrawColor($r, $g, $b);
|
|
|
|
//Text Color = T_COLOR
|
|
list($r, $g, $b) = $data[$i]['T_COLOR'];
|
|
$this->SetTextColor($r, $g, $b);
|
|
|
|
//Set the font, font type and size
|
|
$this->SetFont( $data[$i]['T_FONT'],
|
|
$data[$i]['T_TYPE'],
|
|
$data[$i]['T_SIZE']);
|
|
|
|
//print the text
|
|
$this->tbMultiCellTbl(
|
|
$data[$i]['CELL_WIDTH'],
|
|
$data[$i]['LN_SIZE'],
|
|
$data[$i]['TEXT_STRLINES'],
|
|
$data[$i]['BRD_TYPE'],
|
|
$data[$i]['T_ALIGN'],
|
|
$data[$i]['V_ALIGN'],
|
|
1,
|
|
$h - $data[$i]['HEIGHT']
|
|
);
|
|
}
|
|
|
|
//Put the position to the right of the cell
|
|
$this->SetXY($x + $data[$i]['CELL_WIDTH'],$y);
|
|
|
|
//if we have colspan, just ignore the next cells
|
|
if (isset($data[$i]['COLSPAN'])){
|
|
$i = $i + (int) $data[$i]['COLSPAN'] - 1;
|
|
}
|
|
|
|
}//for
|
|
|
|
$this->bDataOnCurrentPage = true;
|
|
|
|
//Go to the next line
|
|
$this->Ln($val['HEIGHT']);
|
|
}//foreach
|
|
|
|
}//function _tbCachePrepOutputData
|
|
|
|
|
|
/**
|
|
* Prepares the cache for Output.
|
|
*
|
|
* Parses the cache for Rowspans, Paginates the cache and then send the data to the pdf document
|
|
* @access protected
|
|
* @param void
|
|
* @return void
|
|
*/
|
|
protected function _tbCachePrepOutput(){
|
|
|
|
if ($this->bRowSpanInCache) $this->_tbCacheParseRowspan();
|
|
|
|
$this->_tbCachePaginate();
|
|
|
|
$this->_tbCachePrepOutputData();
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Adds a new page in the pdf document and initializes the table and the header if necessary.
|
|
*
|
|
* @access protected
|
|
* @param void
|
|
* @return void
|
|
*/
|
|
protected function tbAddPage($bHeader = true){
|
|
|
|
$this->tbDrawBorder();//draw the table border
|
|
|
|
$this->_tbEndPageBorder();//if there is a special handling for end page??? this is specific for me
|
|
|
|
$bUtf8Set = false;
|
|
|
|
//IF UTF8 Support is needed then
|
|
if (isset($this->utf8_support) && ($this->utf8_support)){
|
|
//keep the compatibility with the "old" fpdf utf8 support.
|
|
if (isset($this->utf8_decoded)){
|
|
$old_utf8_decoded = $this->utf8_decoded;
|
|
$this->utf8_decoded = false;
|
|
$bUtf8Set = true;
|
|
}
|
|
}
|
|
|
|
$this->AddPage($this->CurOrientation);//add a new page
|
|
|
|
//IF UTF8 Support is needed then
|
|
if ($bUtf8Set){
|
|
$this->utf8_decoded = $old_utf8_decoded;
|
|
}
|
|
|
|
$this->bDataOnCurrentPage = false;
|
|
|
|
$this->iTableStartX = $this->GetX();
|
|
$this->iTableStartY = $this->GetY();
|
|
$this->tbMarkMarginX();
|
|
|
|
}//function tbAddPage
|
|
|
|
|
|
/** This method allows printing text with line breaks.
|
|
It works like a modified MultiCell
|
|
Call:
|
|
@param
|
|
$w - width
|
|
$h - line height
|
|
$txtData - the outputed text
|
|
$border - border(LRTB 0 or 1)
|
|
$align - horizontal align 'JLR'
|
|
$valign - Vertical Alignment - Top, Middle, Bottom
|
|
$fill - fill (1/0)
|
|
$vh - vertical adjustment - the Multicell Height will be with this VH Higher!!!!
|
|
$vtop - vertical top add-on
|
|
@return nothing
|
|
*/
|
|
/**
|
|
* Ouputs a Table Cell. It works like a modified MultiCell.
|
|
*
|
|
* @param integer $w - cell width
|
|
* @param integer $h - line height
|
|
* @param array $txtData - variable that contains the data to be outputted. This data is already formatted!!!
|
|
* @param string $border - border(LRTB 0 or 1)
|
|
* @param string $align - horizontal align 'JLR'
|
|
* @param string $valign - Vertical Alignment - Top, Middle, Bottom
|
|
* @param string $fill - Cell Fill (0 no Fill, 1 fill)
|
|
* @param integer $vh - Vertical Adjustment - the Multicell Height will be with this VH Higher!!!!
|
|
* @param integer $vtop - vertical top add-on
|
|
* @param integer $pad_left - Cell Pad left - NOT IMPLEMENTED
|
|
* @param integer $pad_top - Cell Pad left - NOT IMPLEMENTED
|
|
* @param integer $pad_right - Cell Pad left - NOT IMPLEMENTED
|
|
* @param integer $pad_bottom - Cell Pad left - NOT IMPLEMENTED
|
|
* @return void
|
|
*/
|
|
function tbMultiCellTbl($w, $h, $txtData, $border=0, $align='J', $valign='T', $fill=0, $vh=0, $vtop=0, $pad_left=0, $pad_top=0, $pad_right=0, $pad_bottom=0){
|
|
|
|
$b1 = '';//border for top cell
|
|
$b2 = '';//border for middle cell
|
|
$b3 = '';//border for bottom cell
|
|
$wh_Top = 0;
|
|
|
|
if ($vtop > 0){//if this parameter is set
|
|
if($vtop < $vh){//only if the top add-on is bigger than the add-width
|
|
$wh_Top = $vtop;
|
|
$vh = $vh - $vtop;
|
|
}
|
|
}
|
|
|
|
if($border)
|
|
{
|
|
if($border==1)
|
|
{
|
|
$border = 'LTRB';
|
|
$b1 = 'LRT';//without the bottom
|
|
$b2 = 'LR';//without the top and bottom
|
|
$b3 = 'LRB';//without the top
|
|
}
|
|
else
|
|
{
|
|
$b2='';
|
|
if(is_int(strpos($border,'L')))
|
|
$b2.='L';
|
|
if(is_int(strpos($border,'R')))
|
|
$b2.='R';
|
|
$b1=is_int(strpos($border,'T')) ? $b2.'T' : $b2;
|
|
$b3=is_int(strpos($border,'B')) ? $b2.'B' : $b2;
|
|
|
|
}
|
|
}
|
|
|
|
if (empty($txtData)){
|
|
//draw the top borders!!!
|
|
$this->Cell($w,$vh,'',$border,2,$align,$fill);//19.01.2007 - andy
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
switch ($valign){
|
|
case 'T':
|
|
$wh_T = $wh_Top;//Top width
|
|
$wh_B = $vh - $wh_T;//Bottom width
|
|
break;
|
|
case 'M':
|
|
$wh_T = $wh_Top + $vh/2;
|
|
$wh_B = $vh/2;
|
|
break;
|
|
case 'B':
|
|
$wh_T = $wh_Top + $vh;
|
|
$wh_B = 0;
|
|
break;
|
|
default://default is TOP ALIGN
|
|
$wh_T = $wh_Top;//Top width
|
|
$wh_B = $vh - $wh_T;//Bottom width
|
|
}
|
|
|
|
//save the X position
|
|
$x = $this->x;
|
|
/*
|
|
if $wh_T == 0 that means that we have no vertical adjustments so I will skip the cells that
|
|
draws the top and bottom borders
|
|
*/
|
|
|
|
if ($wh_T > 0)//only when there is a difference
|
|
{
|
|
//draw the top borders!!!
|
|
$this->Cell($w,$wh_T,'',$b1,2,$align,$fill);//19.01.2007 - andy
|
|
}
|
|
|
|
$b2 = is_int(strpos($border,'T')) && ($wh_T == 0) ? $b2.'T' : $b2;
|
|
$b2 = is_int(strpos($border,'B')) && ($wh_B == 0) ? $b2.'B' : $b2;
|
|
$this->MultiCellTag($w, $h, $txtData, $b2, $align, 1, $pad_left, $pad_top, $pad_right, $pad_bottom, false);
|
|
|
|
if ($wh_B > 0){//only when there is a difference
|
|
|
|
//go to the saved X position
|
|
//a multicell always runs to the begin of line
|
|
$this->x = $x;
|
|
|
|
$this->Cell($w, $wh_B, '', $b3, 2, $align,$fill);//19.01.2007 - andy
|
|
|
|
#$this->x = $this->lMargin;//andy 23.02.2006
|
|
$this->x = $x;
|
|
}
|
|
|
|
}//function tbMultiCellTbl
|
|
|
|
|
|
/**
|
|
* Sends to the pdf document the cache data
|
|
*
|
|
* @access public
|
|
* @param void
|
|
* @return void
|
|
*/
|
|
public function tbOuputData(){
|
|
$this->_tbCachePrepOutput();
|
|
|
|
//IF UTF8 Support is needed then
|
|
if (isset($this->utf8_support) && ($this->utf8_support)){
|
|
//keep the compatibility with the "old" fpdf utf8 support.
|
|
if (isset($this->utf8_decoded)) $this->utf8_decoded = false;
|
|
}
|
|
}//function tbOuputData
|
|
|
|
|
|
}//end of pdf_table class
|
|
|
|
?>
|