Search code examples
phppdffpdf

Overlap issue with tables using FPDF library


I'm working on a PHP web project using FPDF library, which is working fine. My ongoing task is to insert a table in the generated pdf page. Since I need to output the table in a specific way (see picture below), it is being very difficult to use the existing scripts one can find here : http://www.fpdf.org/fr/script/index.php. I'm using the classes provided in the link as traits in my custom PDF class.

My MySQL table: enter image description here

The specific way of rendering data: enter image description here

colonne (French) = column (English) / ligne = line

  • With "Tables HTML" script (written by Azeem Abbas, see http://www.fpdf.org/en/script/script70.php), I've been able to output the table in right way (see picture below), but could not manage to handle margins, width and other html properties. enter image description here
  • With "Table with MySQL" script (written by Olivier, see http://www.fpdf.org/en/script/script14.php), no way to ouput data the exact way I did it with "Tables HTML" script. I've tried to rewrite Table and Row function, but could get good result.
  • In both cases I encounter text overlap issue whenener I have quite long text in cells. I tried MultiCell function, it causing cells to pile up.

enter image description here

Here is the code i'm using:

Any ideas about a library that can help me get a html table inside pdf page with overlap issue and the possibility to change table html properties?

Update: Oct 10, 2019 I've just found answer to the overlap issue in the code below written by Olivier (http://www.fpdf.org/en/script/script3.php):

<?php
require('fpdf.php');

class PDF_MC_Table extends FPDF
{
var $widths;
var $aligns;

function SetWidths($w)
{
    //Set the array of column widths
    $this->widths=$w;
}

function SetAligns($a)
{
    //Set the array of column alignments
    $this->aligns=$a;
}

function Row($data)
{
    //Calculate the height of the row
    $nb=0;
    for($i=0;$i<count($data);$i++)
        $nb=max($nb,$this->NbLines($this->widths[$i],$data[$i]));
    $h=5*$nb;
    //Issue a page break first if needed
    $this->CheckPageBreak($h);
    //Draw the cells of the row
    for($i=0;$i<count($data);$i++)
    {
        $w=$this->widths[$i];
        $a=isset($this->aligns[$i]) ? $this->aligns[$i] : 'L';
        //Save the current position
        $x=$this->GetX();
        $y=$this->GetY();
        //Draw the border
        $this->Rect($x,$y,$w,$h);
        //Print the text
        $this->MultiCell($w,5,$data[$i],0,$a);
        //Put the position to the right of the cell
        $this->SetXY($x+$w,$y);
    }
    //Go to the next line
    $this->Ln($h);
}

function CheckPageBreak($h)
{
    //If the height h would cause an overflow, add a new page immediately
    if($this->GetY()+$h>$this->PageBreakTrigger)
        $this->AddPage($this->CurOrientation);
}

function NbLines($w,$txt)
{
    //Computes the number of lines a MultiCell of width w will take
    $cw=&$this->CurrentFont['cw'];
    if($w==0)
        $w=$this->w-$this->rMargin-$this->x;
    $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
    $s=str_replace("\r",'',$txt);
    $nb=strlen($s);
    if($nb>0 and $s[$nb-1]=="\n")
        $nb--;
    $sep=-1;
    $i=0;
    $j=0;
    $l=0;
    $nl=1;
    while($i<$nb)
    {
        $c=$s[$i];
        if($c=="\n")
        {
            $i++;
            $sep=-1;
            $j=$i;
            $l=0;
            $nl++;
            continue;
        }
        if($c==' ')
            $sep=$i;
        $l+=$cw[$c];
        if($l>$wmax)
        {
            if($sep==-1)
            {
                if($i==$j)
                    $i++;
            }
            else
                $i=$sep+1;
            $sep=-1;
            $j=$i;
            $l=0;
            $nl++;
        }
        else
            $i++;
    }
    return $nl;
}
}
?>

Now the only problem I have is editing Row() function in the above code so the table is rendered in the specific way I mentioned.

This is how Row() function is used as stated in the documentation of the above class (see http://www.fpdf.org/fr/script/script3.php):

function GenerateWord()
{
    //Get a random word
    $nb=rand(3,10);
    $w='';
    for($i=1;$i<=$nb;$i++)
        $w.=chr(rand(ord('a'),ord('z')));
    return $w;
}

function GenerateSentence()
{
    //Get a random sentence
    $nb=rand(1,10);
    $s='';
    for($i=1;$i<=$nb;$i++)
        $s.=GenerateWord().' ';
    return substr($s,0,-1);
}

$pdf=new PDF_MC_Table();
$pdf->AddPage();
$pdf->SetFont('Arial','',14);
//Table with 20 rows and 4 columns
$pdf->SetWidths(array(30,50,30,40));
srand(microtime()*1000000);
for($i=0;$i<20;$i++)
    $pdf->Row(array(GenerateSentence(),GenerateSentence(),GenerateSentence(),GenerateSentence()));
$pdf->Output();

In my case the array to pass on to Row function is a tridimensional one:

$table =
Array
(
    [1] => Array
        (
            [1] => Array
                (
                    [1] => colonne1 ligne1
                )

            [2] => Array
                (
                    [4] => colonne2   ligne1  
                )

            [3] => Array
                (
                    [9] => colonne3 ligne1 

                )

        )

    [pos_paragr_prec] => 0
    [2] => Array
        (
            [1] => Array
                (
                    [2] => colonne1 ligne2  
                )

            [2] => Array
                (
                    [7] => colonne2 ligne2 
                )

            [3] => Array
                (
                    [10] => colonne3 ligne2  
                )

        )

    [3] => Array
        (
            [1] => Array
                (
                    [3] => colonne1 ligne3 
                )

            [2] => Array
                (
                    [8] => colonne2 ligne3
                )

            [3] => Array
                (
                    [11] => colonne3 ligne3
                )

        )

)

Any hints on how the Row function can be edited to produce the table in the way mentioned above?

So far, I've tried to do something like this without editing the Row function:

if (count($table) > 0) {
        foreach($table as $row_array) {
            foreach($row_array as $key => $val) {
                for($i=0;$i<count($row_array);$i++) {
                    $pdf->Row($val);
                }                                       
            }
        }
    }

This, obviously, doesn't work.

Update

I have made some improvements in my code this way:

if (count($table) > 0) {

    if (is_array($table_data) && count($table_data) > 0) {
        foreach ($table_data as $key => $value) {
            $arrayWidths = [];                          

            foreach($value as $key2 => $val) {

                array_push($arrayWidths, 40);
                $pdf->SetWidths($arrayWidths);

                foreach($val as $k => $col) {

                    $w=40;//$pdf->widths[$key2];
                    $a='L';//isset($pdf->aligns[$i]) ? $pdf->aligns[$key2] : 'L';
                    //Save current position 
                    $x=$pdf->GetX();
                    $y=$pdf->GetY();
                    //Drawing the border
                    $pdf->Rect($x,$y,$w,$h);
                    //Printing text
                    $pdf->MultiCell($w,5,$table_data[$key][$key2][$k],0,$a);
                    //Putting the position to the right of the cell
                    $pdf->SetXY($x+$w,$y);                      

                }                               

            }
            $pdf->Ln();                         
        }

    }

}

By now data are being rendered the specific way I wanted. However, there is a difference between the first row and the rest. The first row is acceptable. I have the overlap issue with those rows below the first one. Here is the result that I've got:

enter image description here

I used the logic of this script : http://www.fpdf.org/en/script/script3.php (see the code pasted above).

Any ideas? Thanks in advance


Solution

  • I've been able to produce a table the right way by rewriting the code available here, so it fits the specificity of my context: fpdf.org/en/script/script14.php. Below is what I did.

    1. I created the following trait, which I used inside PDF class :

      <?php
      
      trait PDF_SQL_Table
      {
      protected $aCols=array();
      protected $TableX;
      protected $HeaderColor;
      protected $RowColors;
      protected $ColorIndex;
      
      /**
       * @return void
       */
      function TableHeader()
      {
          $this->SetFont('Arial','B',10);
          $this->SetTextColor(0); ## Couleur de police de caractères de l'en-tête du tableau
      
          ## Couleur de fond de l'en-tête du tableau
          $fill=!empty($this->HeaderColor);
          if($fill)
              $this->SetFillColor($this->HeaderColor[0],$this->HeaderColor[1],$this->HeaderColor[2]);
      }
      
      /**
       * @param array $tableData
       * @param $width
       * @param $align
       * @param $TableWidth
       * @param $key
       * @return float|int
       */
      function CalcWidths(array $tableData, $width, $align, $TableWidth, $key)
      {
          $w = $this->aCols[$key]['w'];
          if($w==-1)
              $w = $width/count($tableData);
          elseif(substr($w,-1) == '%')
              $w = $w/100 * $width;
          $this->aCols[$key]['w'] = $w;
          $TableWidth += $w;
      
          // Calcul de l'abscisse du tableau
          if($align=='C')
              $this->TableX=max(($this->w-$TableWidth)/2,0);
          elseif($align=='R')
              $this->TableX= $this->TableX=max($this->w-$this->rMargin-$TableWidth,0);//max($this->w-15-$TableWidth,0); //$this->TableX=max($this->w-$this->rMargin-$TableWidth,0);
          else
              $this->TableX=$this->lMargin;//15; // $this->TableX=$this->lMargin;
      
          return $w;
      }
      
      /**
       * @param int $field
       * @param int $width
       * @param string $caption
       * @param string $align
       */
      function AddCol($field=-1, $width=-1, $caption='', $align='L'): void
      {
          // Ajout d'une colonne du tableau
          if($field == -1)
              $field = count($this->aCols);
          $this->aCols[$field]=array('f'=>$field,'c'=>$caption,'w'=>$width,'a'=>$align);
      }
      
      /**
       * @param array $table
       * @param array $prop
       * @param array $array_paragraphes
       * @param float $interligne
       * @param array $excludedParagraphs
       * @param $dec
       */
      function TableAndParagraphs(array $table = array(), array $prop=array(), array $array_paragraphes, float $interligne, array $excludedParagraphs, $dec): void
      {
          foreach ($array_paragraphes as $ordre => $paragraphe) {
              ### $this->Ln(10); En activant ceci à cet endroit précis, un des tableaux s'affiche sur plusieurs pages de façon discontinue
              ###  Insertion d'un tableau au dessous du paragraphe correspondant à ordre_texte_saisi = $table['pos_paragr_prec']
              ### Utilisation d'une extension de la librairie FPDF disponible ici (que nous avons personnalisée) : http://www.fpdf.org/?go=script&id=14
      
              $counter = 0;
              foreach ($table as $num_tableau => $donnees_tableau) {
                  ## Insertion d'un tableau au dessous du paragraphe correspondant à ordre_texte_saisi = $table['pos_paragr_prec']
                  ## Utilisation d'une extension de la librairie FPDF disponible ici : http://www.fpdf.org/?go=script&id=14
                  // Gestion des propriétés
                  if(!isset($prop['width']))
                      $prop['width']=0;
                  if($prop['width']==0)
                      $prop['width']= $this->w-$this->lMargin-$this->rMargin;//$this->w-15-15; //($this->lMargin = 15 / $this->rMargin = 15  cf. plus haut)
                  if(!isset($prop['align']))
                      $prop['align']='C';
                  if(!isset($prop['padding']))
                      $prop['padding']=$this->cMargin;
                  $cMargin=$this->cMargin;
                  $this->cMargin=$prop['padding'];
                  if(!isset($prop['HeaderColor']))
                      $prop['HeaderColor']=array();
                  $this->HeaderColor=$prop['HeaderColor'];
                  if(!isset($prop['color1']))
                      $prop['color1']=array();
                  if(!isset($prop['color2']))
                      $prop['color2']=array();
                  $this->RowColors=array($prop['color1'],$prop['color2']);
      
                  $this->ColorIndex = 0;
      
                  if ($ordre === ($table[$num_tableau]['pos_paragr_prec'])) {
                      $excludedParagraphs[] = $ordre;
                      ### $this->Ln(10); En activant ceci un des tableaux s'affiche sur plusieurs pages de façon discontinue
                      $paragraphe = html_entity_decode($paragraphe, ENT_HTML5, "UTF-8");
                      $this->MultiCell(0,$interligne,$paragraphe);
                      ### $this->Ln($dec);  En activant ceci, à partir de la 2ème ligne du tableau l'affichage se fait sur plusieurs pages avec une cellule par page
      
                      if (count($table) > 0) {
                          $this->Ln(10); ### Un espace vertical avant d'afficher le tableau
                          if (is_array($donnees_tableau) && count($donnees_tableau) > 0) {
      
                              $iteration = 0; ### indice d'itération sur les tableaux
                              $TableWidth=0;
                              foreach ($donnees_tableau as $key => $value) { ### Début d'affichage d'un tableau
      
                                  ### Si la hauteur h = 20 provoque un débordement, on effectue un saut de page manuel
                                  ### $this->Ln(0);  juste un test : activer ceci donne une idée sur le traitement ligne par ligne (ceci produit une nette séparation entre les lignes)
      
                                  $this->CheckPageBreak(10);// ceci permet de pouvoir afficher un tableau sur 2 ou plusieurs pages
                                  $this->SetX(15);// On décale le tableau vers la droite de 18 unités (en argument de la fonction SetX()). Permet de déplacer le tableau horizontalement
      
                                  $number = 0; // Itération sur les données du tableau
      
                                  foreach($value as $key2 => $val) {
      
                                      foreach($val as $k => $col) {
                                          // Ajout dynamique d'une colonne au tableau
                                          $this->AddCol($key2, -1, '', 'R');
                                          // Calcul dynamique de la largeur de la colonne
                                          $w = $this->CalcWidths($value, $prop['width'], 'L', $TableWidth, $key2);
      
                                          $ci = $this->ColorIndex;
                                          $fill=!empty($this->RowColors[$ci]);
                                          if($fill)
                                              $this->SetFillColor($this->RowColors[$ci][0],$this->RowColors[$ci][1],$this->RowColors[$ci][2]);
      
                                          $this->SetFont('Arial','',9); // Police de caractère pour les tableaux
      
                                          if (is_numeric($donnees_tableau[$key][$key2][$k])) {
                                              $cellData = number_format($donnees_tableau[$key][$key2][$k], 2, ',',' ');
                                              $alignRight = true;
                                          } elseif (substr($donnees_tableau[$key][$key2][$k], -1) == '%') {
                                              $cellData = number_format($donnees_tableau[$key][$key2][$k], 2, ',',' ').'%';
                                              $alignRight = true;
                                          } elseif (preg_match('/^[0-9+-]{1,3}(\s|,)[0-9]{1,3}\s?[0-9]{0,3},?[0-9]{0,2}/', $donnees_tableau[$key][$key2][$k])) {
                                              $cellData = $donnees_tableau[$key][$key2][$k];
                                              $alignRight = true;
                                          } elseif (preg_match('/[0-9]{1,3},[0-9]{3}\.?[0-9]{0,2}/', $donnees_tableau[$key][$key2][$k])) {
                                              $cellData = str_replace(',', ' ', $donnees_tableau[$key][$key2][$k]);
                                              $cellData = str_replace('.', ',', $cellData);
                                              $alignRight = true;
                                          } elseif (preg_match('/^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{2,4})$/', $donnees_tableau[$key][$key2][$k])) {
                                              //$cellData = preg_replace('/^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{2,4})$/', "$2/$1/$3", $donnees_tableau[$key][$key2][$k]);
                                              $cellData = date_create($donnees_tableau[$key][$key2][$k]);
                                              $cellData = date_format($cellData, "d/m/Y");
                                              $alignRight = false;
                                          } else {
                                              $cellData = $donnees_tableau[$key][$key2][$k];
                                              $alignRight = false;
                                          }
      
                                          $x=$this->GetX();
                                          $y=$this->GetY();
      
                                          ## On évite qu'il y ait des Multicells de hauteur inférieure à celle du Cell suivant sur la même ligne
                                          if ($this->GetStringWidth($donnees_tableau[$key][$key2][$k]) < $w && $key2 == '0' /*&& $key >= '1'*/) {
                                              $spaces = "\n"." "; // Espace insécable : "&#160;"
                                              $cellData .= $spaces;
                                          }
      
                                          ## Mise en forme du header (police de caractère et couleur de l'arrière-plan)
                                          if ($key == '0') {
                                              $this->TableHeader();
                                          } else {
                                              $this->SetTextColor(0);
                                          }
      
      
                                          $this->SetDrawColor(0); ### couleur de la bordure des cellule du tableau : valeur de 0 (noir) à 255 (blanc)
                                          if ($this->GetStringWidth($donnees_tableau[$key][$key2][$k]) > $w || $key2 === 'A' || $key2 == '0') {
                                              $this->MultiCell($w,5,$cellData,1,'L',$fill);
                                              $newY = $this->GetY();
                                              $this->SetXY($x + $w, $y);
                                          } else {
                                              $H = $newY - $y;
                                              if ($alignRight) {
                                                  $this->Cell($w, $H,$cellData,1,1,'R',$fill);
                                              } else {
                                                  $this->Cell($w, $H,$cellData,1,1,'C',$fill);
                                              }
                                          }
      
                                          $this->SetFont('Arial','',11);
                                          $this->SetDrawColor(0);
                                          $this->SetXY($x+$w,$y);
                                      }
                                      $number++;
                                  }// affichage d'une ligne entière
      
                                  if ($iteration == 1) {
                                      $this->Ln(0); ###### 3 : valeur représentant l'écart entre le header du tableau et le corps du tableau
                                  } else {
                                      $this->Ln($H);
                                  }
      
                                  // Retour à la ligne afin d'afficher la ligne suivante du tableau
                                  $this->ColorIndex = 1-$ci;
      
                                  $iteration++;
      
                              }// Un tableau entier est affiché
      
                          }
                      }
                  }//if ($ordre === ($table[$num_tableau]['pos_paragr_prec']))
      
                  //Espace entre le premier tableau et le paragraphe en dessous
                  if ($counter == 0) {
                      $this->Ln(5.5);
                  }
      
                  //Empêcher qu'un paragraphe ne s'affiche plusieurs fois
                  if ($counter == count($table) - 1) {
      
                      //Les paragraphes liés à des tableaux ont été déjà affichés
                      if (!in_array($ordre, $excludedParagraphs)) {
                          $this->Ln(5.5);// Espace entre un tableau et le paragraphe en dessous (premier tableau exclus)
                          $paragraphe = html_entity_decode($paragraphe, ENT_HTML5, "UTF-8");
                          $this->MultiCell(0,$interligne,$paragraphe);
                          $this->Ln($dec);
                      }
                  }
      
                  $counter++;
              }
          }
      }
      }
      
    2. PDF class:

      class PDF extends TFPDF
      {
          protected $B = 0;
          protected $I = 0;
          protected $U = 0;
          protected $HREF = '';
      
          use PDF_MC_Table, PDF_SQL_Table;
      
          function Entete() {
      
          }
      
          function Footer() {
             //some code
          }
      
          //etc.
      
      }
      
    3. In the controller, I could call TableAndParagraphs() function this way:

      $pdf->TableAndParagraphs($table, $prop, $array_paragraphes, $interligne, $excludedParagraphs, $dec);
      

      Note that TFPDF is a library based on FPDF (it can be found on Internet):

      
      <?php
      /*******************************************************************************
      * tFPDF (based on FPDF 1.7)                                                    *
      *                                                                              *
      * Version:  1.24                                                               *
      * Date:     2011-09-24                                                         *
      * Author:   Ian Back <ianb@bpm1.com>                                           *
      * License:  LGPL                                                               *
      *******************************************************************************/
      
      define('tFPDF_VERSION','1.24');
      
      class tFPDF
      {
      
      var $unifontSubset;
      var $page;               // current page number
      var $n;                  // current object number
      var $offsets;            // array of object offsets
      var $buffer;             // buffer holding in-memory PDF
      var $pages;              // array containing pages
      var $state;              // current document state
      var $compress;           // compression flag
      var $k;                  // scale factor (number of points in user unit)
      var $DefOrientation;     // default orientation
      var $CurOrientation;     // current orientation
      var $StdPageSizes;       // standard page sizes
      var $DefPageSize;        // default page size
      var $CurPageSize;        // current page size
      var $PageSizes;          // used for pages with non default sizes or orientations
      var $wPt, $hPt;          // dimensions of current page in points
      var $w, $h;              // dimensions of current page in user unit
      var $lMargin;            // left margin
      var $tMargin;            // top margin
      var $rMargin;            // right margin
      var $bMargin;            // page break margin
      var $cMargin;            // cell margin
      var $x, $y;              // current position in user unit
      var $lasth;              // height of last printed cell
      var $LineWidth;          // line width in user unit
      var $fontpath;           // path containing fonts
      var $CoreFonts;          // array of core font names
      var $fonts;              // array of used fonts
      var $FontFiles;          // array of font files
      var $diffs;              // array of encoding differences
      var $FontFamily;         // current font family
      var $FontStyle;          // current font style
      var $underline;          // underlining flag
      var $CurrentFont;        // current font info
      var $FontSizePt;         // current font size in points
      var $FontSize;           // current font size in user unit
      var $DrawColor;          // commands for drawing color
      var $FillColor;          // commands for filling color
      var $TextColor;          // commands for text color
      var $ColorFlag;          // indicates whether fill and text colors are different
      var $ws;                 // word spacing
      var $images;             // array of used images
      var $PageLinks;          // array of links in pages
      var $links;              // array of internal links
      var $AutoPageBreak;      // automatic page breaking
      var $PageBreakTrigger;   // threshold used to trigger page breaks
      var $InHeader;           // flag set when processing header
      var $InFooter;           // flag set when processing footer
      var $ZoomMode;           // zoom display mode
      var $LayoutMode;         // layout display mode
      var $title;              // title
      var $subject;            // subject
      var $author;             // author
      var $keywords;           // keywords
      var $creator;            // creator
      var $AliasNbPages;       // alias for total number of pages
      var $PDFVersion;         // PDF version number
      
      /*******************************************************************************
      *                                                                              *
      *                               Public methods                                 *
      *                                                                              *
      *******************************************************************************/
      
      
      function __construct($orientation='P', $unit='mm', $size='A4')
      {
          // Some checks
          $this->_dochecks();
          // Initialization of properties
          $this->page = 0;
          $this->n = 2;
          $this->buffer = '';
          $this->pages = array();
          $this->PageSizes = array();
          $this->state = 0;
          $this->fonts = array();
          $this->FontFiles = array();
          $this->diffs = array();
          $this->images = array();
          $this->links = array();
          $this->InHeader = false;
          $this->InFooter = false;
          $this->lasth = 0;
          $this->FontFamily = '';
          $this->FontStyle = '';
          $this->FontSizePt = 12;
          $this->underline = false;
          $this->DrawColor = '0 G';
          $this->FillColor = '0 g';
          $this->TextColor = '0 g';
          $this->ColorFlag = false;
          $this->ws = 0;
          // Font path
          if(defined('FPDF_FONTPATH'))
          {
              $this->fontpath = FPDF_FONTPATH;
              if(substr($this->fontpath,-1)!='/' && substr($this->fontpath,-1)!='\\')
                  $this->fontpath .= '/';
          }
          elseif(is_dir(dirname(__FILE__).'/font'))
              $this->fontpath = dirname(__FILE__).'/font/';
          else
              $this->fontpath = '';
          // Core fonts
          $this->CoreFonts = array('courier', 'helvetica', 'times', 'symbol', 'zapfdingbats');
          // Scale factor
          if($unit=='pt')
              $this->k = 1;
          elseif($unit=='mm')
              $this->k = 72/25.4;
          elseif($unit=='cm')
              $this->k = 72/2.54;
          elseif($unit=='in')
              $this->k = 72;
          else
              $this->Error('Incorrect unit: '.$unit);
          // Page sizes
          $this->StdPageSizes = array('a3'=>array(841.89,1190.55), 'a4'=>array(595.28,841.89), 'a5'=>array(420.94,595.28),
              'letter'=>array(612,792), 'legal'=>array(612,1008));
          $size = $this->_getpagesize($size);
          $this->DefPageSize = $size;
          $this->CurPageSize = $size;
          // Page orientation
          $orientation = mb_strtolower($orientation); // 20160707 ajout mb_
          if($orientation=='p' || $orientation=='portrait')
          {
              $this->DefOrientation = 'P';
              $this->w = $size[0];
              $this->h = $size[1];
          }
          elseif($orientation=='l' || $orientation=='landscape')
          {
              $this->DefOrientation = 'L';
              $this->w = $size[1];
              $this->h = $size[0];
          }
          else
              $this->Error('Incorrect orientation: '.$orientation);
          $this->CurOrientation = $this->DefOrientation;
          $this->wPt = $this->w*$this->k;
          $this->hPt = $this->h*$this->k;
          // Page margins (1 cm)
          $margin = 28.35/$this->k;
          $this->SetMargins($margin,$margin);
          // Interior cell margin (1 mm)
          $this->cMargin = $margin/10;
          // Line width (0.2 mm)
          $this->LineWidth = .567/$this->k;
          // Automatic page break
          $this->SetAutoPageBreak(true,2*$margin);
          // Default display mode
          $this->SetDisplayMode('default');
          // Enable compression
          $this->SetCompression(true);
          // Set default PDF version number
          $this->PDFVersion = '1.3';
      }
      
      //etc.
      
      }