-
Acum ceva vreme am primit un task sa realizez o forma de prezentare a unei oferte de produse. Nu trebuia sa fie un catalog, trebuia pur si simplu sa fie o lista de produse. Clientul m-a lasat sa decid eu intre xls si pdf. Nu am stat pe ganduri si am ales pdf dar… era problema ce sa folosesc. De dragul portabilitatii am zis sa nu folosesc modulul php_pdflib ca sa nu apara probleme daca incerc sa refac aplicatia cu alta ocazie.
Dar Google ca de obicei mi-a dat si solutia: fpdf! Fpdf este o clasa php, total independenta realizata in php4. Trebuie sa recunosc ca mi-a luat cateva ore pana am ajuns sa realizez fisierul dar sunt foarte multimit de rezultat si chiar daca a durat putin mai mult decat estimasem initial o data ce m-am prins ce am de facut a iesit totul bine.
In principiu cam tot ce este nevoie este in manual.
Foarte multimit de rezultat am vrut sa trec la pasul 2, factura in format pdf.
Ca si in html eram obisnuit ca atunci cand informatia este tabelara sa o formatez ca atare, dar in fpdf nu exista tabele proprizise, exista celulele separate printr-un rand nou. Iar o alta problema este legata de formatarea tabelara, celulele nu se redimensioneaza dupa continut ca in html.
Prima problema este simplu de rezolvat, put si simplu se apeleaza metoda Ln() cand se doreste trecerea pe un nou rand, dar pentru ca celulele nu sunt chiar celule se pot intersecta destul de usor folosind latimea celulei:
1require('fpdf.php'); 2 3// instantiaza clasa 4$pdf=new FPDF(); 5 6// seteaza fontul 7$pdf->SetFont('Arial','',5); 8 9//adauga o noua pagina 10$pdf->AddPage(); 11 12// primele doua celule, primii 2 parametrii sunt latimea si inaltimea 13$pdf->Cell(20, 10, "celula 1", 1, 0, "C"); 14$pdf->Cell(20, 10, "celula 2", 1, 0, "C"); 15 16// un nou rand pentru a trece pe randul urmator 17$pdf->Ln(); 18 19// celula a treia cu latimea cat primele doua celule, echivalentul lui 20// "rowspan" din html 21$pdf->Cell(40, 10, "celula 3", 1, 0, "C"); 22 23// afisarea rezultatului 24$pdf->Output();
Rezultatul arata cam asa:
Pana aici totul pare ok, eu in momentul asta priveam plin de optimism la pasul urmator din factura, afisarea campurilor facturii. Aici a aparut problema, campurile nu se redimensioneaza si arata cel putin bizar. De exemplu doua celule arata cam asta:
1$pdf->Cell(20, 10, "Lorem ipsum dolor sit amet", 1, 0, "L"); 2$pdf->Cell(20, 10, "celula 2", 1, 0, "C");
Iar in momentul asta mi-a cazut lumea in cap, mai ales ca imi aduceam aminte de o proforma primita in posta unde era aceasi problema. Solutia nu este foarte dificila dar a durat destul de mult “scotocit” ca sa o gasesc: in afara de metoda Cell() mai exista si metoda MultiCell() care suporta redimensionarea, chiar intr-un mod relativ elegant. Problema este ca aceste doua elemente trebuie combinate in fpdf pentru a genera un tabel de proforma:
1// latimea primei celule 2$w1 = 20; 3 4// latimea cele de a doua celule 5$w2 = 20; 6 7// aflam coordonatele curente a le cursorului 8$y1 = $pdf->GetY(); 9$x1 = $pdf->GetX(); 10 11// celula multiCell care se redimensioneaza automat pe inaltime 12$pdf->MultiCell($w1, 10, "Lorem ipsum dolor sit amet", 1, "L"); 13 14// aflam coordonatele cursorului dupa ce a fost afisata prima celula 15$y2 = $pdf->GetY(); 16 17// aflam inaltimea primei celule 18$hCell = $y2 - $y1; 19 20// setam coordonatele cursorului la noua locatie calculata 21$pdf->SetXY($x1+$w1, $pdf->GetY() - $hCell); 22 23//afisam a doua celula 24$pdf->Cell($w2, $hCell, "celula 2", 1, 0, "C");
Rezultatul este:
Pana aici deja zambetul incepea sa revina. Ultimul pas este pozitionarea primei celule, celula cu numar de ordine in fata celor doua celule. In exemplul urmator latimile celule au fost decalate cu 1. Practic trebuie sa mutam cursorul la dreapta cu latimea primei celule, sa afisam celula care se va lati si sa calculam inaltimea ei. Dupa ce am calculat inaltimea celulei redimensionata putem sa potitionam cursorul din nou in pozitia initiala sa afisam prima celula, dupa care sa multam cursorul dupa a doua celula si sa continuam cu celelalte celule asa cum se inampla in mod normal. Exemplu:
1// latimea primei celule 2$w1 = 10; 3 4// latimea cele de a doua celule 5$w2 = 20; 6 7// latimea cele de a treia celula 8$w3 = 20; 9 10// aflam coordonatele curente a le pointerului 11$y1 = $pdf->GetY(); 12$x1 = $pdf->GetX(); 13 14$pdf->SetXY($x1+$w1, $pdf->GetY()); 15 16// celula multiCell care se redimensioneaza automat pe inaltime 17$pdf->MultiCell($w2, 10, "Lorem ipsum dolor sit amet", 1, "L"); 18 19// aflam coordonatele pointerului dupa ce a fost afisata prima celula 20$y2 = $pdf->GetY(); 21 22// aflam inaltimea celulei de tip MultiCell 23$hCell = $y2 - $y1; 24 25// setam coordonatele la pozitia initiala pentru a afisa prima celula 26$pdf->SetXY($x1, $y1); 27 28// afisam prima celula 29$pdf->Cell($w1, $hCell, "celula 1", 1, 0, "C"); 30 31// setam coordonatele pointerului la noua locatie calculata 32$pdf->SetXY($x1+$w1+$w2, $y1); 33 34//afisam a treia celula 35$pdf->Cell($w3, $hCell, "celula 3", 1, 0, "C"); 36 37// un nou rand pentru a trece pe randul urmator 38$pdf->Ln();
Rezultatul este:
De aici problema este rezolvata. De aici nu este decat o problema de a multiplica randul in functie de cate inregistrari se afla in factura. Daca folositi fpdf nu uitati sa treceti prin manual, este foarte simplu si concis.