FPDF: generowanie zaproszeń

Autor: Arkadiusz Tobiasz 18 kwietnia 2010

Jakiś czas temu obiecałem pokazać Wam skrypt, który na podstawie formularza generuje odpowiedniego PDFa. Od obietnicy minął rok, więc postanowiłem w końcu dotrzymać danego słowa. Pokażę Wam jak na podstawie danych wprowadzonych do formularza wygenerować zaproszenie na jakąś imprezę.

Rozpocznijmy od formularza, z którego dane po wysłaniu będą stanowiły podstawę do wygenerowania PDFa z zaproszeniem. Skrypt nazwiemy stworz_zaproszenie.php i będzie wyglądać następująco:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<html>
<head>
<title>FPDF - stwórz własne zaproszenie!</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-2">
</head>
<body>
<form action="zaproszenie.php" method="post"><div>
<input name="nazwa_firmy" />Podaj nazwę firmy<br />
<input name="nazwa_imprezy" />Podaj nazwę imprezy<br /><br />

<input name="data" />Data imprezy<br />
<input name="godzina" />Godzina imprezy<br /><br />

<input name="adres" />Adres imprezy<br />
<input name="miasto" />Miasto imprezy<br /><br />

<p>Dodatkowe informacje</p>
<textarea name="informacje" cols="50" rows="10"></textarea>
<br /><br /><br />
<input type="submit" value="Wy¶lij formularz" />
<input type="reset" value="Wyczy¶ć dane" />
</div></form>
</body>
</html>

Myślę, że powyższy kod nie wymaga komentarza. Dane z formularza wysyłane są do skryptu o nazwie zaproszenie.php. Zaczynamy standardowo od załadowania biblioteki FPDF, dodania strony w formacie A5 oraz polskich czcionek (o tym wszystkim możesz przeczytać tutaj):

1
2
3
4
5
6
7
8
9
10
11
<?php
include("fpdf/fpdf.php");

$pdf=new FPDF();
$pdf->Open();
$pdf->AddPage('P', 'A5');

$pdf->AddFont('arial_ce','','arial_ce.php');
$pdf->AddFont('arial_ce','I','arial_ce_i.php');
$pdf->AddFont('arial_ce','B','arial_ce_b.php');
$pdf->AddFont('arial_ce','BI','arial_ce_bi.php');

Teraz będę chciał wypełnić naszą stronę tłem. W tym celu wybrałem sobie obrazek, który nazwałem background.jpg. Tło ustawiamy z wykorzystaniem metody Image():

1
$pdf->Image('background.jpg', 0, 0, 148, 210);

Pierwszym argumentem jest ścieżka do pliku, kolejne dwa to pozycja od której ma obrazek być wyświetlany, ja przyjąłem, że będzie do lewy górny róg. Ostatnie dwa argumenty tej metody to szerokość i wysokość. Pamiętaj, że szerokość i wysokość jest podawana w milimetrach, a nie pikselach! Teraz będziemy chcieli wyświetlać tekst na naszym obrazku. Na początku ustawmy odpowiednią czcionkę oraz kursor, czyli miejsce od którego będzie wyświetlany tekst:

1
2
$pdf -> SetFont('arial_ce', 'B',  20);
$pdf -> SetXY(10, 30);

Ustawiliśmy pogrubioną czcionkę Arial o rozmiarze 20px, a kursor centymetr od lewej krawędzi i 3 cm od górnej. Na samym początku będziemy chcieli wyświetlić nazwę firmy. Jednak zanim użyjemy metody MultiCell() musimy nasze wysłane dane przekonwertować z ISO-8859-2 na Windows-1250, bowiem w tym formacie jest zapisana nasza polska czcionka:

1
2
$nazwa_firmy = iconv('iso-8859-2','windows-1250//TRANSLIT', $_POST['nazwa_firmy']);
$pdf->MultiCell(100,8, $nazwa_firmy, 0, 'L', 0);

Jak widzisz pobieramy dane z formularza i wyświetlamy w komórce o wymiarach 10 x 0,8 cm. Następnie ustawiamy statyczny tekst:

1
2
3
4
5
$pdf -> SetFont('arial_ce', 'BI',  20);
$x = $pdf->GetX();
$y = $pdf->GetY();
$pdf->SetXY($x, $y+6);
$pdf->MultiCell(100,5, 'Serdecznie zaprasza na', 0, 'L', 0);

Czcionkę zmieniamy na pochyłą. Mankamentem tej biblioteki jest, że za każdym razem, gdy ustawiamy kursor, to wprowadzone parametry są odnoszone od początku strony, czyli punktu 0,0, a nie od miejsca, w którym się ostatnio znalazł. W tym celu wykorzystujemy metody GetX() oraz GetY(), które zwracają nam wartości aktualnie ustawionych współrzędnych. Przypisujemy je do zmiennych i tak ustawiamy kursor za pomocą metody SetXY(). W powyższym kodzie kursor przesunęliśmy o 6 mm w dół.

1
2
3
4
5
6
7
$pdf -> SetFont('arial_ce', 'BI',  35);
$pdf -> SetTextColor(255, 0, 0);
$x = $pdf->GetX();
$y = $pdf->GetY();
$pdf->SetXY($x, $y+15);
$nazwa_imprezy = iconv('iso-8859-2','windows-1250//TRANSLIT', $_POST['nazwa_imprezy']);
$pdf->MultiCell(100,15, $nazwa_imprezy,0,  'L',0);

Dalej wyświetlamy nazwę imprezy. Znów zmieniamy czcionkę oraz kolor czcionki wykorzystując metodę SetTextColor(). Niestety kolory musimy podać w RGB.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$pdf -> SetFont('arial_ce', 'B',  15);
$pdf -> SetTextColor(0, 0, 0);
$x = $pdf->GetX();
$y = $pdf->GetY();
$pdf->SetXY($x, $y+15);
$data = iconv('iso-8859-2','windows-1250//TRANSLIT', $_POST['data']);
$pdf->MultiCell(100,7, $data, 0, 'L', 0);
$pdf -> SetFont('arial_ce', '',  15);
$godzina = iconv('iso-8859-2','windows-1250//TRANSLIT', $_POST['godzina']);
$pdf->MultiCell(100,7, $godzina, 0, 'L', 0);

$x = $pdf->GetX();
$y = $pdf->GetY();
$pdf->SetXY($x, $y+5);
$adres = iconv('iso-8859-2','windows-1250//TRANSLIT', $_POST['adres']);
$miasto = iconv('iso-8859-2','windows-1250//TRANSLIT', $_POST['miasto']);
$pdf->MultiCell(100,7, $adres, 0, 'L', 0);
$pdf->MultiCell(100,7, $miasto, 0, 'L', 0);

$x = $pdf->GetX();
$y = $pdf->GetY();
$pdf->SetXY($x, $y+5);
$pdf -> SetFont('arial_ce', 'B',  15);
$pdf->MultiCell(100,7, 'Dodatkowe informacje:',0, 'L', 0);
$pdf -> SetFont('arial_ce', '',  15);
$informacje = iconv('iso-8859-2','windows-1250//TRANSLIT', $_POST['informacje']);
$pdf->MultiCell(100,7, $informacje, 0, 'L', 0);

W pozostałej części wyświetlamy po kolei dane otrzymane z wysłanego formularza. Ostatecznie chcemy wygenerować plik PDF, co też czynimy:

1
2
3
$pdf->Output();

?>

Oczywiście to tylko prosty przykład pokazujący część z możliwości biblioteki FPDF. Polecam manual, w którym znajdziecie opis wszystkich metod oraz parametrów do nich. Tradycyjnie również podaję link do działającego dema.

komentarzy 18

  1. Kaos napisał(a):

    Pytanie nowicjusza: Czy da się przerobć ten skrypt tak, żeby generował plik np.jpg, a tekst umieszczać w konkretnych miejscach na obrazku-tle?

    • bato3 napisał(a):

      Niespecjalnie…
      Zainteresuj się GD2: imagefttext() i pamiętaj o imagecreatetruecolor() zamiast: imagecreatecolor().

  2. Daxxx napisał(a):

    Wszystko ładnie działa tylko jest mały problem, to co wpisuje w formularz generuje się z polskimi znakami w PDF-ie, ale jeśli użyje polskich znaków w „stałych” tekstach w pliku zaproszenie.php nie to już nie mam polskich znaków np. brak litery ę.
    zmieniam powiedzmy linijkę:
    $pdf->MultiCell(100,5, ‚Serdecznie zaprasza na’, 0, ‚L’, 0);
    na:
    $pdf->MultiCell(100,5, ‚Imię’, 0, ‚L’, 0); i zamiast ę mam e.
    Jak to zrobić żeby „stałe” teksty miały polskie znaki ??

  3. Daxxx napisał(a):

    Problem rozwiązany, wystarczy zamiast polskich znaków wstawić ich odpowiedniki…
    ł ³
    Ł £
    ą ¹
    ę ê
    ó ó
    ś œ
    ć æ
    Ś Œ
    ż ¿
    Ż ¯
    ź Ÿ

    • bato3 napisał(a):

      Robisz to źle 🙂
      PDF jest zależny od kodowania znaków, a kodowanie pliku jest różne od kodowania użytego dla czcionki.
      Jest kilka rozwiązań, ty użyłeś najgorszego…
      1. Wygenerować czcionki w kodowaniu iso-2. (Możesz też użyć utf8, ale wtedy używasz UFPDF*)
      2. używasz icnv/mb_convert_encoding dla każdego stringa przekazywanego do FPDF.
      3. robisz cały plik w kodowaniu czcionki.
      4. Twoje rozwiązanie 🙂

      * UFPDF zawiera błąd, odnajdź metody: _textstring i _escapetext i zamień return […] na:
      return $this->escape($s);

  4. pawel napisał(a):

    Świetny blog, świetne wpisy, dużo przydatnych skryptów. Tematyka idealna dla mnie. Tak dalej! Będę Cię odwiedzał.

  5. pawel napisał(a):

    Właśnie przetestowałem twój skrypt. Wszystko fajnie działa, ale… wielkość generowanego pliku to 600 kb.. jest to bardzo dużo, za dużo. Wiem, że jest sposób na użycie kompresji – wiesz może jak to zrobić?

    Pozdrawiam,
    Paweł

    • Arkadiusz Tobiasz napisał(a):

      niestety to minus tej biblioteki, możesz spróbować z TCPDF

    • bato3 napisał(a):

      FPDF w standardzie kompresuje (gzip – deflate).
      Lwią część rozmiaru to czcionki i obrazki. Czyli:
      – jeżeli nie używasz fonta – nie osadzaj go
      – przeskaluj obrazek – aby był wstawiany 1:1
      – zmień rozdzielczość obrazka, jeżeli do wyświetlania to 72DPI, do druku – z jaką rozdielczośćią drukuje twoja drukara?

  6. ptama napisał(a):

    Witam! Chciałabym zapytać, jak jest generowany pdf z wypełnioną deklaracją wyboru lekarza na stronie http://deklaracja.biogenes.pl/
    Czy mam mieć skan deklaracji, zapisany jako obrazek i zastosować go jako tło? Jak liczyć odległości, gdzie ma być wpis w pdf – mierzyć linijką czy można prościej?

    • Arkadiusz Tobiasz napisał(a):

      Tak jak piszesz najlepiej jako tło, a następnie używać metody Cell określając współrzędne X i Y w pikselach od początku kartki

      • bato3 napisał(a):

        Kłamiesz 🙂 Z dokumentacji:

        FPDF([string orientation [, string unit [, mixed size]]])

        Milimetry są dozwolone. Mierzyć linijką, a lepiej suwmiarką.

        Zamiast jpg możesz też użyć PDF’a, która zezwala na pisanie/rysowanie po stronach: „FPDI”

        • Arkadiusz Tobiasz napisał(a):

          Nie zarzucałbym kłamstwa, a przeczytał ze zrozumieniem. W konstruktorze możesz podać wymiary PDF’a w milimetrach, ale aby użyć tła w dokumencie. W tym celu najlepiej użyć metody Image, aby umieścić obrazek i na niego nakładać tekst ustalając jego współrzędne (metoda SetXY lub Text), które należy podać w pikselach.

  7. Robert napisał(a):

    Witam,

    a gdzie jest zawarte zapytanie INSERT przy jednoczesnym generowaniu pliku pdf Panie Tobiaszu?

    • Arkadiusz Tobiasz napisał(a):

      a w jakim celu? przedstawiłem jedynie skrypt umożliwiający generowanie zaproszeń, bez możliwości zapisu ich do bazy danych.

      • Tomek napisał(a):

        Witam
        właśnie borykam się z polskimi znakami w generowanych dokumentach PDF niestety nie sprawdza mi się powyższa metoda dalej mam krzaki zamiast liter
        zastanawia że w Twoim formularzu również nie ma polskich znaków
        pozdrawiam

  8. Marcin napisał(a):

    Czy jest możliwość aby taki PDF był wysyłany na podany w formularzu adres email, a nie generowany/zapisywany lokalnie?
    pozdrawiam

    • Arkadiusz Tobiasz napisał(a):

      Tak jest taka możliwość

      zamiast

      1
      $pdfdoc = $pdf->Output();

      dać

      1
      $pdfdoc = $pdf->Output('', 'S');

      a następnie zakodować pdf

      1
      $attachment = chunk_split(base64_encode($pdfdoc));

      i dodać do wiadomości e-mail, przy użyciu np. funkcji mail()

Odpowiedz

 

Arkadiusz Tobiasz student Akademii Ekonomicznej im. Karola Adamieckiego w Katowicach na specjalnościach informatyka ekonomiczna oraz rachunkowość. Więcej...

jQuery Validation i funkcja remote

Jakiś czas temu zwrócił się do mnie użytkownik z problemem. Chodzi o to, że korzysta on z pluginu walidacji jQuery, […]

Zend Framework: integracja z Uploadify

W tym wpisie postaram się przedstawić Wam w jaki sposób zintegrować skrypt Uploadify z Zend Frameworkiem. Dzięki temu będziemy mogli […]

Javascript: Czasowe wyświetlanie reklamy

Czasami chcemy, aby na pewnym elemencie naszej strony wyświetlała się reklama przez jakiś czas, a następnie zniknęła. W tym wpisie […]

Linux: backup wszystkich baz danych MySQL

Swego czasu pisałem o tym jak z poziomu konsoli można szybko i przyjemnie zrobić backup bazy MySQL. Wszystko jest ładnie […]