Dokument pdf jaki miał być wygenerowany przez mój skrypt to rodzaj katalogu. W związku z tym dane miały być prezentowane w postaci tabelki. Aby narysować tabelę w TCPDF najlepiej jest wykorzystać metody Cell() i MultiCell() (przykłady użycia Cell() i MultiCell()), które służą do rysowania prostokątnych pól tekstowych z możliwością dodawnia obramowania i tła
Czego potrzebował klient
Pól biedy jeśli z góry wiemy jaka będzie zawartość poszczególnych komórek tabeli. Wtedy można precyzyjnie zaplanować wysokość i szerokość i o nic się nie martwić. Gorzej jeśli treść ma być dynamiczna. W projekcie, który realizowałam, operator miał możliwość decydowania o szerokości każdej kolumny tabeli, o wielkości czcionki w każdej kolumnie. Zaś treść pochodziła z wczytanego pliku. Zatem wszystko musiało być obliczane dynamicznie.
Przygotowanie danych
Aby sprostać zadaniu i ułatwić sobie pracę należy odpowiednio przygotować dane. Po pierwsze będzie potrzebna tablica n-elementowa, nazwijmy ją $arrCellWidth, która będzie zawierała dane dotyczące szerokości każdej z n kolumn.
Po drugie będzie potrzebna tablica o wymiarach mxn, nazwijmy ją $arrCellText. W każdym z m wierszy znajduje się n-elementowa tablica stringów, które mają się znaleźć w poszczególnych komórkach.
Użycie metody Cell()
Zakładając, że zawartość każdej z komórek to bardzo krótkie łańcuchy znaków (np liczby, czy symbole), można się zadowolić wspomnianą już metodą Cell(). Zatem do dzieła. Aby wygenerować tabeli z danych przygotowanych tak jak opisałam wcześniej wystarczy taki kod:
foreach($arrCellText as $intRowN => $arrRow) { foreach($arrRow as $intCellN => $strText){ $intCellW = $arrCellWidth[$intCellN]; $this->Cell($intCellW, 10, $strText, 1, 0, 'C'); } $this->Ln(); }
Efekt może być bardzo przyzwoity, ale jeśli długość tekstu i szerokość komórki nie będą współgrały może wyglądać tak:
Użycie metody MultiCell()
Jeśli więc jest ryzyko, że jednak teksty nie będą się mieścić w komórkach, lepiej jest wykorzystać metodę MultiCell(). Wtedy tekst ładnie się zawinie w komórce, a komórka rozciągnie się do takiej wysokości, żeby zawartość komórki ładnie się prezentowała.
foreach($arrCellText as $intRowN => $arrRow) { foreach($arrRow as $intCellN => $strText){ $intCellW = $arrCellWidth[$intCellN]; $this->MultiCell($intCellW, 10, $strText, 1, 'C', 0, 0); } $this->Ln(); }
No i właśnie w tym rozciąganiu, które z jednej strony nam służy jest problem, bo wtedy pojedynczy wiersz może wyglądać tak (dane identycznie jak w poprzednim przykładzie):
Co gorsza, jeśli narysujemy kilka wierszy, to możemy uzyskać naprawdę opłakane efekty:
Dzieje się tak dlatego, że przechodząc do nowej linii za pomoca metody Ln() trafiamy z początkiem linii tam gdzie kończyła się ostatnia komórka. Jeśli zatem była ona niższe niż inne to wiersze będa si nakładać.
Wyznaczanie wysokości wiersza
Najlepiej więc byłoby obliczyć jaką wysokość powinien mieć cały wiersz, aby wszystkie komórki ładnie się prezentowały. W tym celu należy użyć metody getNumLines(), za pomocą której możemy obliczyć na ile linii złamie się dany tekst w komórce o zadanej szerokości. Trzeba więc najpierw przeczesać całą linię, żeby zobaczyć która komórka będzie najwyższa, a następnie wyrównać pozostałe komórki do niej. Proste, prawda?
foreach($arrCellText as $intRowN => $arrRow) { $intMaxH = 0; foreach($arrRow as $intCellN => $strText){ $intCellW = $arrCellWidth[$intCellN]; $intLineNumb = $this->getNumLines($strText, $intCellW, false, true, '', 1); $intCurrH = $intLineNumb * $this->FontSize * $this->cell_height_ratio; $intCurrH += ($this->cell_padding['T'] + $this->cell_padding['B']); $intMaxH = max($intCurrH, $intMaxH); } foreach($arrRow as $intCellN => $strText){ $intCellW = $arrCellWidth[$intCellN]; $this->MultiCell($intCellW, $intMaxH, $strText, 1, 'C', 0, 0); } $this->Ln(); }
Działanie opisanego powyżej kodu można obejrzeć w tym DEMO
Przydatny wpis. Już kiedyś też zmagałam się z tym problemem, ale nie natrafiłam wtedy na żaden artykuł po polsku.