skik/prints3/class.fpdf_table.php
2023-02-27 10:20:09 +01:00

643 lines
21 KiB
PHP
Executable File

<?php
/****************************************************************************
* Software: FPDF class extention *
* Creates Pdf Tables *
* Version: 3.2 *
* Date: 2005/07/20 *
* Author: Bintintan Andrei -- klodoma@ar-sd.net *
* *
* Last Modification: 2006/09/25 *
* *
* License: Free for non-commercial use *
* *
* You may use and modify this software as you wish. *
* PLEASE REPORT ANY BUGS TO THE AUTHOR. THANK YOU *
****************************************************************************/
/**
Modifications:
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::Set_Table_SplitMode(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('class.multicelltag.php');
//extension class
class FPDF_TABLE extends FPDF_MULTICELLTAG
{
var $tb_columns; //number of columns of the table
var $tb_header_type; //array which contains the header characteristics and texts
var $tb_header_draw; //TRUE or FALSE, the header is drawed or not
var $tb_header_height; //This is the Table Header Maximum Height
var $tb_border_draw; //TRUE or FALSE, the table border is drawed or not
var $tb_data_type; //array which contains the data characteristics (only the characteristics)
var $tb_table_type; //array which contains the table charactersitics
var $table_startx, $table_starty; //the X and Y position where the table starts
var $tb_split_normal; /* << ** special request from Marc Ulfig >>
= false - the split is made only if the cell width does not fit into a page height
= true - the split of a cell will ocuur whenever necesary
*/
var $Draw_Header_Command; //command which determines in the DrawData first the header draw
var $Data_On_Current_Page; // = true/false ... if on current page was some data written
//returns the width of the page in user units
function PageWidth(){
return (int) $this->w-$this->rMargin-$this->lMargin;
}
//constructor(not a real one, but have to call it first)
//we initialize all the variables that we use
function Table_Init($col_no = 0, $header_draw = true, $border_draw = true){
$this->tb_columns = $col_no;
$this->tb_header_type = Array();
$this->tb_header_draw = $header_draw;
$this->tb_header_height = 0;
$this->tb_border_draw = $border_draw;
$this->tb_data_type = Array();
$this->tb_split_normal = true;
$this->tb_type = Array();
$this->table_startx = $this->GetX();
$this->table_starty = $this->GetY();
$this->Draw_Header_Command = false; //by default we don't draw the header
$this->Data_On_Current_Page = false;
}
//Sets the number of columns of the table
function Set_Table_Columns($nr){
$this->tb_columns = $nr;
}
//Sets the number of columns of the table
function Set_Table_SplitMode($pSplit = true){
$this->tb_split_normal = $pSplit;
}
/*
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!!!!
*/
/*
Function: Set_Header_Type($type_arr) -- sets the array for the header type
type array =
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
*/
function Set_Header_Type($type_arr){
$this->tb_header_type = $type_arr;
}
/*
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!!!!
*/
/*
Function: Set_data_Type($type_arr) -- sets the array for the header type
type array =
array(
0=>array(
"T_COLOR" => array(120,120,120),
"T_SIZE" => 5,
...
"BRD_TYPE" => 1
),
1=>array(
...
),
);
where 0,1... are the column number
*/
function Set_Data_Type($type_arr){
$this->tb_data_type = $type_arr;
}
/*
Function Set_Table_Type
$type_arr = array(
"BRD_COLOR"=> array (120,120,120), //border color
"BRD_SIZE"=>5), //border line width
"TB_COLUMNS"=>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
)
*/
function Set_Table_Type($type_arr){
if (isset($type_arr['TB_COLUMNS'])) $this->tb_columns = $type_arr['TB_COLUMNS'];
if (!isset($type_arr['L_MARGIN'])) $type_arr['L_MARGIN']=0;//default values
$this->tb_table_type = $type_arr;
}
//this functiondraws the exterior table border!!!!
function Draw_Table_Border(){
/* "BRD_COLOR"=> array (120,120,120), //border color
"BRD_SIZE"=>5), //border line width
"TB_COLUMNS"=>5), //the number of columns
"TB_ALIGN"=>"L"), //the align of the table, possible values = L, R, C equivalent to Left, Right, Center
*/
if ( ! $this->tb_border_draw ) return;
if ( ! $this->Data_On_Current_Page) return; //there was no data on the current page
//set the colors
list($r, $g, $b) = $this->tb_table_type['BRD_COLOR'];
$this->SetDrawColor($r, $g, $b);
//set the line width
$this->SetLineWidth($this->tb_table_type['BRD_SIZE']);
#echo $this->GetY()-$this->table_starty." ";;
//draw the border
$this->Rect(
$this->table_startx,
$this->table_starty,
$this->Get_Table_Width(),
$this->GetY()-$this->table_starty);
}
function End_Page_Border(){
if (isset($this->tb_table_type['BRD_TYPE_END_PAGE'])){
if (strpos($this->tb_table_type['BRD_TYPE_END_PAGE'], 'B') >= 0){
//set the colors
list($r, $g, $b) = $this->tb_table_type['BRD_COLOR'];
$this->SetDrawColor($r, $g, $b);
//set the line width
$this->SetLineWidth($this->tb_table_type['BRD_SIZE']);
//draw the line
$this->Line($this->table_startx, $this->GetY(), $this->table_startx + $this->Get_Table_Width(), $this->GetY());
}
}
}
//returns the table width in user units
function Get_Table_Width()
{
//calculate the table width
$tb_width = 0;
for ($i=0; $i < $this->tb_columns; $i++){
$tb_width += $this->tb_header_type[$i]['WIDTH'];
}
return $tb_width;
}
//alignes the table to C, L or R(default is L)
function Table_Align(){
//check if the table is aligned
if (isset($this->tb_table_type['TB_ALIGN'])) $tb_align = $this->tb_table_type['TB_ALIGN']; else $tb_align='';
//set the table align
switch($tb_align){
case 'C':
$this->SetX($this->lMargin + $this->tb_table_type['L_MARGIN'] + ($this->PageWidth() - $this->Get_Table_Width())/2);
break;
case 'R':
$this->SetX($this->lMargin + $this->tb_table_type['L_MARGIN'] + ($this->PageWidth() - $this->Get_Table_Width()));
break;
default:
$this->SetX($this->lMargin + $this->tb_table_type['L_MARGIN']);
break;
}//if (isset($this->tb_table_type['TB_ALIGN'])){
}
//Draws the Header
function Draw_Header(){
$this->Draw_Header_Command = true;
$this->tb_header_height = 0;
}
function Init_Table_Position(){
$this->Table_Align();
$this->table_startx = $this->GetX();
$this->table_starty = $this->GetY();
}
/**
Draws the header line from a table.
Call:
@param none
@return nothing
*/
function Draw_Header_(){
$this->tb_header_height = 0;
$this->Init_Table_Position();
$this->Draw_Header_Command = false;
//if the header will be showed
if ( ! $this->tb_header_draw ) return;
$this->DrawTableLine($this->tb_header_type, false, 1, $height);
$this->Data_On_Current_Page = true;
}
/**
Draws a data line from the table.
Call this function after the table initialization, table, header and data types are set
Call:
@param $data - array containing line informations
$header - header will be drawed or not in case of new page
@return nothing
*/
function Draw_Data($data, $header = true, $height){
$this->DrawTableLine($data, $header, 0, $height);
}
/** Draws a data or header line from the table.
Call:
@param $data - array containing line informations
$header - header will be drawed or not in case of new page
$pDataType = 0 - normal line
1 - header line
2 - not implemented
$heigt = Zellenhöhe
@return nothing
*/
function DrawTableLine($data, $header, $pDataType = 0, $height){
$h = $height;
$hm = 0;
$xx = Array();
$tt = Array();
if (!$this->Data_On_Current_Page) $this->Init_Table_Position();
if ($pDataType == 0){//data line
if ($this->Draw_Header_Command){//draw the header
$this->Draw_Header_();
}
}
//maximum Height available on this page
$AvailPageH = $this->PageBreakTrigger - $this->GetY();
if ($AvailPageH <= 0){ //there is no more space on this page
$this->TableAddPage($header);//add a page without header
$this->DrawTableLine($data, $header, $pDataType, $height);//recall this function
return;//exit this function
}
$MaxPageH = $this->PageBreakTrigger - $this->tMargin;
$split = false;
$backdata = $data; //backup data in case of split or recall;
//calculate the maximum height of the cells
for($i=0; $i < $this->tb_columns; $i++)
{
if (!isset($data[$i]['TEXT']) || ($data[$i]['TEXT']=='')) $data[$i]['TEXT'] = " ";
if (!isset($data[$i]['T_FONT'])) $data[$i]['T_FONT'] = $this->tb_data_type[$i]['T_FONT'];
if (!isset($data[$i]['T_TYPE'])) $data[$i]['T_TYPE'] = $this->tb_data_type[$i]['T_TYPE'];
if (!isset($data[$i]['T_SIZE'])) $data[$i]['T_SIZE'] = $this->tb_data_type[$i]['T_SIZE'];
if (!isset($data[$i]['T_COLOR'])) $data[$i]['T_COLOR'] = $this->tb_data_type[$i]['T_COLOR'];
if (!isset($data[$i]['T_ALIGN'])) $data[$i]['T_ALIGN'] = $this->tb_data_type[$i]['T_ALIGN'];
if (!isset($data[$i]['V_ALIGN'])) $data[$i]['V_ALIGN'] = $this->tb_data_type[$i]['V_ALIGN'];
if (!isset($data[$i]['LN_SIZE'])) $data[$i]['LN_SIZE'] = $this->tb_data_type[$i]['LN_SIZE'];
if (!isset($data[$i]['BRD_SIZE'])) $data[$i]['BRD_SIZE'] = $this->tb_data_type[$i]['BRD_SIZE'];
if (!isset($data[$i]['BRD_COLOR'])) $data[$i]['BRD_COLOR'] = $this->tb_data_type[$i]['BRD_COLOR'];
if (!isset($data[$i]['BRD_TYPE'])) $data[$i]['BRD_TYPE'] = $this->tb_data_type[$i]['BRD_TYPE'];
if (!isset($data[$i]['BG_COLOR'])) $data[$i]['BG_COLOR'] = $this->tb_data_type[$i]['BG_COLOR'];
$this->SetFont( $data[$i]['T_FONT'],
$data[$i]['T_TYPE'],
$data[$i]['T_SIZE']);
$data[$i]['CELL_WIDTH'] = $this->tb_header_type[$i]['WIDTH'];
if (isset($data[$i]['COLSPAN'])){
$colspan = (int) $data[$i]['COLSPAN'];//convert to integer
for ($j = 1; $j < $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->tb_columns)
$data[$i]['CELL_WIDTH'] += $this->tb_header_type[$i + $j]['WIDTH'];
}
}
$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->StringToLines($data[$i]['CELL_WIDTH'], $data[$i]['TEXT']);
$NoLines = count($data[$i]['TEXT_STRLINES']);
$hm = max($hm, $data[$i]['LN_SIZE'] * $NoLines);//this would be the normal height
if ($NoLines > $MaxLines){
$split = true;
$NoLines = $MaxLines;
$data[$i]['TEXT_SPLITLINES'] = array_splice($data[$i]['TEXT_STRLINES'], $MaxLines);
}
$data[$i]['CELL_LINES'] = $NoLines;
//this is the maximum cell height
$h = max($h, $data[$i]['LN_SIZE'] * $data[$i]['CELL_LINES']);
if (isset($data[$i]['COLSPAN'])){
//just skip the other cells
$i = $i + $colspan - 1;
}
}
if ($pDataType == 0){//data line
if (!$this->tb_split_normal){//split only if the cell height is bigger than a page size
if ($split && (($hm + $this->tb_header_height) < $MaxPageH)){//if the header is splitted and it has space on a page
$this->TableAddPage($header);//add a page without header
$this->DrawTableLine($backdata, $header, 0, $height);//recall this function
return;
}
}
}
if ($pDataType == 1){//header line
$this->tb_header_height = $hm;
if ($split && ($hm < $MaxPageH)){//if the header is splitted and it has space on a page
//new page
$this->TableAddPage(false);//add a page without header
$this->DrawTableLine($backdata, $header, 1, $height);//recall this function
return;
}
if ( ((2*$h) > $AvailPageH) && ((2*$h) < $MaxPageH)){
/*
if the header double size is bigger then the available size
but the double size is smaller than a page size
>>> we draw a new page
**/
$this->TableAddPage(false);//add a page withot header
$this->DrawTableLine($backdata, $header, 1, $height);//recall this function
return;
}
}
$this->Table_Align();
//Draw the cells of the row
for( $i = 0; $i < $this->tb_columns; $i++ )
{
//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']);
//Save the current position
$x=$this->GetX();
$y=$this->GetY();
//print the text
$this->MultiCellTable(
$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]['LN_SIZE'] * $data[$i]['CELL_LINES']
);
//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;
}
}
$this->Data_On_Current_Page = true;
//Go to the next line
$this->Ln($h);
if ($split){
//calculate the maximum height of the cells
for($i=0; $i < $this->tb_columns; $i++){
$backdata[$i]['TEXT_STRLINES'] = isset($data[$i]['TEXT_SPLITLINES']) ? $data[$i]['TEXT_SPLITLINES'] : array();
}
$this->TableAddPage($header);//we have a page split, add a page
if ($pDataType == 1) $header = false;
$this->DrawTableLine($backdata, $header, $pDataType, $height);
}
}//DrawTableLine
/** Adds a new page in the pdf document and initializes the table and the header if necessary.
Call:
@param
$header - boolean - if the header is drawed or not
@return nothing
*/
function TableAddPage($header = true){
$this->Draw_Table_Border();//draw the table border
$this->End_Page_Border();//if there is a special handling for end page??? this is specific for me
$this->AddPage($this->CurOrientation);//add a new page
$this->Data_On_Current_Page = false;
$this->table_startx = $this->GetX();
$this->table_starty = $this->GetY();
if ($header) $this ->Draw_Header();//if we have to draw the header!!!
}//TableAddPage
/** 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!!!!
@return nothing
*/
function MultiCellTable($w, $h, $txtData, $border=0, $align='J', $valign='T', $fill=0, $vh=0)
{
$b1 = '';//border for top cell
$b2 = '';//border for middle cell
$b3 = '';//border for bottom cell
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;
}
}
switch ($valign){
case 'T':
$wh_T = 0;//Top width
$wh_B = $vh - $wh_T;//Bottom width
break;
case 'M':
$wh_T = $vh/2;
$wh_B = $vh/2;
break;
case 'B':
$wh_T = $vh;
$wh_B = 0;
break;
default://default is TOP ALIGN
$wh_T = 0;//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);
}
$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->MultiCell($w,$h,$txt,$b2,$align,$fill);
$this->MultiCellTag($w, $h, $txtData, $b2, $align, 1, 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);
$this->x=$this->lMargin;
}
}
}//end of pdf_table class
?>