Formularz generujący PDF'a

0

Hejka!

Widziałem w pracy jak szef się męczy przy pisaniu w wordzie każdego PDF'a z wyceną prac osobno i chciałem mu trochę pomóc.
Amatorsko lubiłem kodować, edytować style czy skrypty ale niestety okazało się, że to zadanie mnie przerasta lekko. Utknąłem.

Mianowicie zamysł jest taki ->
Interaktywny formularz z 5-cioma polami ( Liczba kolejna, Nr. Artykułu, Typ, Opis oraz Ilość ). Szef wpisuje w kola tekstowe dane, dodatkowo posiada przyciski "dodaj wers", "usuń wers", "generuj PDF".
O tyle o ile poradziłem sobie ładnie ze stroną główną interaktywnej tabelki o tyle kompletnie nie wiem jak się zabrać za generowanie PDF'a z danych które mam.

Stwierdziłem, że chcę to zrobić w PHPie (Udostępnię szefowi linka do strony gdzie to wrzucę), wiem, że pewnie jakiś python albo builder programu byłby łatwiejszy.
Czy jest ktoś w stanie mi pomóc? Podpowiedzieć, rozpocząć dalszy etap za mnie?

Chciałbym aby po kliknięciu "Generuj" nowy skrypt w php pobierał ilość wersów tabeli i tworzył odpowiadającą tabelę w nowym pliku PDF, to znaczy, żeby dane się przepisały do PDF'a.
Jak zrobię 4 wersy i wypełnię danymi żeby pobrało i zrobiło tak samo w PDF'ie.

Nie wiem którego rozszerzenia do tworzenia PDF'a użyć ani jak się za to zabrać. Dalej myślę, że jestem w stanie sam ogarnąć całego PDF,a do porządku.

Dziękuję za każdą pomoc i pozdrawiam.

Skrypt głównej strony który już mam:

> <form action="wynik.php" method="get">
> 	<p>
> 		<input style="height:50px;width:100px;font-size:20px;" type="button" value="Dodaj" onclick="addRowToTable();" />
> 		<input style="height:50px;width:100px;font-size:20px;" type="button" value="Usuń" onclick="removeRowFromTable();" />
> 		<input style="height:50px;width:100px;font-size:20px;" type="button" value="Generuj" onclick="validateRow(this.form);" />
> 	</p>
> 	<p>
> 		<input type="checkbox" id="chkValidate" /> Sprawdzanie
> 		<input type="checkbox" id="chkValidateOnKeyPress" checked="checked" /> Gdzie wpisuje
> 		<span id="spanOutput" style="margin-left:3px;border:1px solid #000;padding:3px;"> </span>
> 	</p>
> <table border="1" id="tabela" style="font-size:30px">
>   <tr>
> 	<td>
> 		Np.
> 	</td>
> 	<td>
> 		Artykuł
> 	</td>
> 	<td>
> 		Typ
> 	</td>
> 	<td>
> 		Opis
> 	</td>
> 	<td>
> 		Ilość
> 	</td>
>   </tr>
>   <tr>
>     <td>
> 		1
> 	</td>
>     <td>
> 		<input type="text" name="txt1Row1" id="txt1Row1" size="15" onkeypress="keyPressTest(event, this);" />
> 	</td>
>     <td>
> 		<input type="text" name="txt2Row1" id="txt2Row1" size="40" onkeypress="keyPressTest(event, this);" />
>     </td>
> 	<td>
> 		<input type="text" name="txt3Row1" id="txt3Row1" size="70" onkeypress="keyPressTest(event, this);" />
>     </td>
> 	<td>
> 		<input type="number" name="txt4Row1" id="txt4Row1" size="15" onkeypress="keyPressTest(event, this);" />
>     </td>
>   </tr>
> </table>
> </form>
> 
> <script>
> function addRowToTable()
> {
>   var tbl = document.getElementById('tabela');
>   var lastRow = tbl.rows.length;
>   var iteration = lastRow;
>   var row = tbl.insertRow(lastRow);
>   
>   // Pierwsza
>   var cellLeft = row.insertCell(0);
>   var textNode = document.createTextNode(iteration);
>   cellLeft.appendChild(textNode);
>   cellLeft.id = 'liczba' + iteration;
>   
>   // Druga
>   var cellRight = row.insertCell(1);
>   var el = document.createElement('input');
>   el.type = 'text';
>   el.name = 'txt1Row' + iteration;
>   el.id = 'txt1Row' + iteration;
>   el.size = 15;
>   
>   // Trzecia
>   var cellRight1 = row.insertCell(1);
>   var el1 = document.createElement('input');
>   el1.type = 'text';
>   el1.name = 'txt2Row' + iteration;
>   el1.id = 'txt2Row' + iteration;
>   el1.size = 40;
>   
>   // Czwarta
>   var cellRight2 = row.insertCell(1);
>   var el2 = document.createElement('input');
>   el2.type = 'text';
>   el2.name = 'txt3Row' + iteration;
>   el2.id = 'txt3Row' + iteration;
>   el2.size = 70;
>   
>   // Piata
>   var cellRight3 = row.insertCell(1);
>   var el3 = document.createElement('input');
>   el3.type = 'number';
>   el3.name = 'txt4Row' + iteration;
>   el3.id = 'txt4Row' + iteration;
>   el3.size = 15;
>   
>   el.onkeypress = keyPressTest;
>   cellRight3.appendChild(el);
>   cellRight2.appendChild(el1);
>   cellRight1.appendChild(el2);
>   cellRight.appendChild(el3);
> }
> function keyPressTest(e, obj)
> {
>   var validateChkb = document.getElementById('chkValidateOnKeyPress');
>   if (validateChkb.checked) {
>     var displayObj = document.getElementById('spanOutput');
>     var key;
>     if(window.event) {
>       key = window.event.keyCode; 
>     }
>     else if(e.which) {
>       key = e.which;
>     }
>     var objId;
>     if (obj != null) {
>       objId = obj.id;
>     } else {
>       objId = this.id;
>     }
>     displayObj.innerHTML = objId + ' : ' + String.fromCharCode(key);
>   }
> }
> function removeRowFromTable()
> {
>   var tbl = document.getElementById('tabela');
>   var lastRow = tbl.rows.length;
>   if (lastRow > 2) tbl.deleteRow(lastRow - 1);
> }
> function openInNewWindow(frm)
> {
>   var aWindow = window.open('', 'TableAddRowNewWindow',
>    'scrollbars=yes,menubar=yes,resizable=yes,toolbar=no,width=400,height=400'); 
>   frm.target = 'TableAddRowNewWindow';
>   frm.submit();
> }
> function validateRow(frm)
> {
>   var chkb = document.getElementById('chkValidate');
>   if (chkb.checked) {
>     var tbl = document.getElementById('tabela');
>     var lastRow = tbl.rows.length - 1;
>     var i;
>     for (i=1; i<=lastRow; i++) {
>       var aRow = document.getElementById('txtRow' + i);
>       if (aRow.value.length <= 0) {
>         alert('Row ' + i + ' is empty');
>         return;
>       }
>     }
>   }
>   openInNewWindow(frm);
> }
> </script>
2

Na telefonie siedzę, więc może gdzieś przeoczyłem, więc zapytam - gdzie masz funkcję tworzącą pdf? I w jaki sposób go chcesz stworzyć? jeśli nie masz jeszcze koncepcji to jest chyba jakaś libka do tego. Jeśli szef chce najpierw do worda sobie, to możesz przez format rtf najłatwiej.

5

odnośnie rozszerzeń do PDF toużywałam biblioteki FPDF, był jakiś problem chyba z polskimi fontami ale się dał rozwiązać

0

Przy rtf też jest problem ze znakami polskimi.

4

Polecam TCPDF: https://github.com/tecnickcom/TCPDF
Polskie znaki chyba dało się stosować w czcioncedejavu : https://dejavu-fonts.github.io/
Polecam dokumentację tej biblioteki, ale jak coś to to może pomóc:
https://stackoverflow.com/questions/46904859/adding-new-fonts-in-tcpdf

No i przykład z biblioteki jak stworzyć taki pilk:
https://tcpdf.org/examples/example_048/

3

Ja polecam mPDF: https://mpdf.github.io/
Polskie znaki działają, a stylizuje się wygląd arkuszem CSS.
Tylko zwróć uwagę na wersję. Nieco inaczej wygląda składnia w PHP7, a PHP5.

0

Wybrałem bibliotekę mPDF bo wydawała mi się najłatwiejsza do ogarnięcia.
Niestety nadal nie mam pojęcia w jaki sposób pobrać dane z indexu już do PDFa i je ładnie poukładać w tabeli tak żeby to miało sens ;/
Czy ktoś jest w stanie pomóc? Kompletnie nie wiem jak. Zrobiłem w drugim pliku przykładową tabelę jak to sobie wyobrażam ale nie potrafię oskryptować tak żeby to miało ręce i nogi.

Index.php

<center>
<h1> Kosztorys prac firmy MarDach </h1>

<form action="pdf.php" method="get">
	<p>
		<input style="height:50px;width:100px;font-size:20px;" type="button" value="Dodaj" onclick="addRowToTable();" />
		<input style="height:50px;width:100px;font-size:20px;" type="button" value="Usuń" onclick="removeRowFromTable();" />
		<input style="height:50px;width:100px;font-size:20px;" type="button" value="Generuj" onclick="validateRow(this.form);" />
	</p>
	<p>
		<input type="checkbox" id="chkValidate" /> Sprawdzanie
		<input type="checkbox" id="chkValidateOnKeyPress" checked="checked" /> Gdzie wpisuje
		<span id="spanOutput" style="margin-left:3px;border:1px solid #000;padding:3px;"> </span>
	</p>
<table border="1" id="tabela" style="font-size:30px">
  <tr>
	<td>
		Np.
	</td>
	<td>
		Artykuł
	</td>
	<td>
		Typ
	</td>
	<td>
		Opis
	</td>
	<td>
		Ilość
	</td>
  </tr>
  <tr>
    <td>
		1
	</td>
    <td>
		<input type="text" name="txt1Row1" id="txt1Row1" size="15" onkeypress="keyPressTest(event, this);" />
	</td>
    <td>
		<input type="text" name="txt2Row1" id="txt2Row1" size="40" onkeypress="keyPressTest(event, this);" />
    </td>
	<td>
		<input type="text" name="txt3Row1" id="txt3Row1" size="70" onkeypress="keyPressTest(event, this);" />
    </td>
	<td>
		<input type="number" name="txt4Row1" id="txt4Row1" size="15" onkeypress="keyPressTest(event, this);" />
    </td>
  </tr>
</table>
<br><br>
<h1>Wartość podatku netto<h1>
<input type="number" name="podatek" id="podatek" size="10" onkeypress="keyPressTest(event, this);" />%
</form>
</center>
<script>
function addRowToTable()
{
  var tbl = document.getElementById('tabela');
  var lastRow = tbl.rows.length;
  var iteration = lastRow;
  var row = tbl.insertRow(lastRow);
  
  // Pierwsza
  var cellLeft = row.insertCell(0);
  var textNode = document.createTextNode(iteration);
  cellLeft.appendChild(textNode);
  cellLeft.id = 'liczba' + iteration;
  
  // Druga
  var cellRight = row.insertCell(1);
  var el = document.createElement('input');
  el.type = 'text';
  el.name = 'txt1Row' + iteration;
  el.id = 'txt1Row' + iteration;
  el.size = 15;
  
  // Trzecia
  var cellRight1 = row.insertCell(1);
  var el1 = document.createElement('input');
  el1.type = 'text';
  el1.name = 'txt2Row' + iteration;
  el1.id = 'txt2Row' + iteration;
  el1.size = 40;
  
  // Czwarta
  var cellRight2 = row.insertCell(1);
  var el2 = document.createElement('input');
  el2.type = 'text';
  el2.name = 'txt3Row' + iteration;
  el2.id = 'txt3Row' + iteration;
  el2.size = 70;
  
  // Piata
  var cellRight3 = row.insertCell(1);
  var el3 = document.createElement('input');
  el3.type = 'number';
  el3.name = 'txt4Row' + iteration;
  el3.id = 'txt4Row' + iteration;
  el3.size = 15;
  
  el.onkeypress = keyPressTest;
  cellRight3.appendChild(el);
  cellRight2.appendChild(el1);
  cellRight1.appendChild(el2);
  cellRight.appendChild(el3);
}
function keyPressTest(e, obj)
{
  var validateChkb = document.getElementById('chkValidateOnKeyPress');
  if (validateChkb.checked) {
    var displayObj = document.getElementById('spanOutput');
    var key;
    if(window.event) {
      key = window.event.keyCode; 
    }
    else if(e.which) {
      key = e.which;
    }
    var objId;
    if (obj != null) {
      objId = obj.id;
    } else {
      objId = this.id;
    }
    displayObj.innerHTML = objId + ' : ' + String.fromCharCode(key);
  }
}
function removeRowFromTable()
{
  var tbl = document.getElementById('tabela');
  var lastRow = tbl.rows.length;
  if (lastRow > 2) tbl.deleteRow(lastRow - 1);
}
function openInNewWindow(frm)
{
  var aWindow = window.open('', 'TableAddRowNewWindow',
   'scrollbars=yes,menubar=yes,resizable=yes,toolbar=no,width=400,height=400'); 
  frm.target = 'TableAddRowNewWindow';
  frm.submit();
}
function validateRow(frm)
{
  var chkb = document.getElementById('chkValidate');
  if (chkb.checked) {
    var tbl = document.getElementById('tabela');
    var lastRow = tbl.rows.length - 1;
    var i;
    for (i=1; i<=lastRow; i++) {
      var aRow = document.getElementById('txtRow' + i);
      if (aRow.value.length <= 0) {
        alert('Row ' + i + ' is empty');
        return;
      }
    }
  }
  openInNewWindow(frm);
}
</script>

pdf.php

<?php

require_once __DIR__ . '/vendor/autoload.php';
$mpdf = new \Mpdf\Mpdf(['tempDir' => __DIR__ . '/temp']);

/* Tworzenie tabeli i całej zawartości PDFa */
$html = '
<head>
    <title>Kupa dupa</title>
    <link href="style.css" rel="stylesheet" />
</head>
<body>
<div id="góra" style="margin-bottom:20px;margin-top:20px;">
    <img style="width:50%;margin-bottom:10px;" src="/md/img/logo.jpg"/>
    <img style="width:50%;" src="/md/img/belka.png"/>
</div>

<div id="tabela" style="margin-left:15%">
    <table class="table">
    <tbody>
        <tr style="border-bottom:1px solid black">
            <td><strong>NP.</strong></td>
            <td><strong>ARTYKUŁ</strong></td>
            <td><strong>TYP</strong></td>
            <td><strong>OPIS</strong></td>
            <td><strong>ILOŚĆ</strong></td>
        </tr>
        <tr>
            <td style="border-right:1px solid black">1</td>
            <td>111</td>
            <td>PANEL</td>
            <td>PANEL FOTOWOLTAICZNY</td>
            <td>111</td>
        </tr>
        <tr>
            <td style="border-right:1px solid black">1</td>
            <td>222</td>
            <td>Śrópka</td>
            <td>Śruba M12</td>
            <td>222</td>
        </tr>
    </tbody>
    </table>
</div>

<div id="kosztorys" style="margin-top:2%;margin-left:15%">
    <h1 style="margin-left:-20%;font-size:25px;"> Kosztorys prac firmy MarDach </h1>
    <table class="table">
    <tbody>
        <tr>
            <td style="border-right:1px solid black"><strong>Kwota netto</strong></td>
            <td><strong>Kwota brutto 8%</strong></td>
        </tr>
        <tr>
            <td style="border-right:1px solid black">netto</td>
            <td>brutto</td>
        </tr>
    </tbody>
    </table>
<br><br>
    <div style="margin-left:25%;font-size:10px;">
        <h1>Kosztorys wydał</h1>
        .................................................................
    </div>
</div>
</body>
';

/* Tutaj liczymy wersy i zbieramy z nich dane */
$txt = 1;
$row = 1;
$a = $_GET['txt' . $txt . 'Row' . $row . ''];
$b = 1;
$pole = 'pole';

if (!empty($a)){
    echo 'dupa c;';
}
else {
    $pole+$b = $a;

    $b + 1; 
    $txt + 1;
    $row + 1;
};

$php .= $pole.'1';

$mpdf->WriteHTML($html);
$mpdf->WriteHTML($php);
$mpdf->Output();

?>
1
  1. Bierzesz dane z formularza przesłane na przykład POSTem,
  2. Mając te dane, sklejasz w PHP kod HTML za pomocą operatora konkatenacji, czyli kropki. Po prostu za pomocą HTML ustalasz, jak ma wyglądać strona w wygenerowanym pliku PDF,
  3. Przekazujesz to do odpowiedniej metody obiektu Mpdf,
  4. Opcjonalnie dołączasz arkusz CSS.
// przykład dla wersji 8.0.9.0 
require_once("vendor/autoload.php"); 
$html = '<h1>Dane z formularza</h1>'.$_POST["dana z formularza"];
$mpdf = new \Mpdf\Mpdf();
$mpdf->WriteHTML($html, \Mpdf\HTMLParserMode::HTML_BODY);
$mpdf->Output('plik.pdf', 'I');

https://mpdf.github.io/getting-started/creating-your-first-file.html

0
kosmonauta80 napisał(a):
  1. Bierzesz dane z formularza przesłane na przykład POSTem,
  2. Mając te dane, sklejasz w PHP kod HTML za pomocą operatora konkatenacji, czyli kropki. Po prostu za pomocą HTML ustalasz, jak ma wyglądać strona w wygenerowanym pliku PDF,
  3. Przekazujesz to do odpowiedniej metody obiektu Mpdf,
  4. Opcjonalnie dołączasz arkusz CSS.
// przykład dla wersji 8.0.9.0 
require_once("vendor/autoload.php"); 
$html = '<h1>Dane z formularza</h1>'.$_POST["dana z formularza"];
$mpdf = new \Mpdf\Mpdf();
$mpdf->WriteHTML($html, \Mpdf\HTMLParserMode::HTML_BODY);
$mpdf->Output('plik.pdf', 'I');

https://mpdf.github.io/getting-started/creating-your-first-file.html

Nie chce być niemiły czy zarozumiały ale tyle to wiem, i wydaje mi się, że mam już ogarnięte.
Mam formularz w PDF zrobiony poprzez HTLMa oraz CSS do niego.

Problem pojawia się na etapie pobrania danych z pól formularza.
W pierwszym formularzu posiadam przycisk który dodaje wersy do tabeli lub je usuwa.
Jak sprawdzić ile wersów ma tabela i co za tym idzie pobrać odpowiednią ilość danych?
Następnie jak je wklepać w uporządkowany sposób w tabelę?

1

Zakładając, że kolejne wiersze tabeli mają id o takiej nazwie: "pozycja_1", "pozycja_2"..."pozycja_n" możesz to zrobić pętlą do-while.

https://www.php.net/manual/en/control-structures.do.while.php

$i = 0;
do 
{
    $element = 'pozycja_'.$i;
    echo $_POST[$element];
    $i++;
} while ((isset($_POST['pozycja'.$i])));

Kod pisany na szybko, możliwe błędy w składni. Ale taki jest mój pomysł.

0

Jakbyś nie poradził sobie w php, to w książce „Python. Automatyzacja zadań. Jak efektywnie pracować z danymi, arkuszami Excela, raportami i e-mailami” masz opisane jak to zrobić w pythonie. A przynajmniej tak wynika ze spisu treści. Książkę będę miał za jakieś 3 dni pewnie, to Ci mogę screena zrobić jak do tego czasu nie ogarniesz w PHP. Ewentualnie mogę Ci opisać jak sobie generowałem szablony rtf w php.

1

@kosmonauta80: dzięki, spróbuję według Twojego pomysłu też.
@PaulGilbert: chyba tylko w ostateczności przerzucę się na coś innego. Chciałbym spróbować dokończyć to co już zacząłem i mam:/ Niemniej jednak nie wykluczam takiego "rozwiązania".

EDIT.
Panowie, poradziłem sobie :) Pobiera odpowiednią ilość wersów oraz wszystkie dane z nich po czym zrzuca ładnie do tabelki, wszystko w swoje miejsce. Udostępnię fragmenty który sprawił mi najwięcej trudności, może kiedyś komuś się przyda.

Wygląda to tak i działa wyśmienicie:

for($row = 1;isset($_GET['txt1Row' . $row . '']);$row++) {
    $srodek .= '
    <tr>
        <td style="border-right:1px solid black">' . $row . '</td>
        <td>' . $_GET['txt1Row' . $row . ''] .'</td>
        <td>' . $_GET['txt2Row' . $row . ''] .'</td>
        <td>' . $_GET['txt3Row' . $row . ''] .'</td>
        <td>' . $_GET['txt4Row' . $row . ''] .'</td>
    </tr>
    ';
};
$mpdf->WriteHTML($srodek);

Dziękuję wszystkim którzy chcieli pomóc i tym którzy pomogli.
W szczególności Panu @kosmonauta80 który polecił i wybrał bibliotekę :)

Panowie, poradziłem sobie z pętlą która pobierze wszystkie dane i je ładnie ułoży. Pytanie teraz w jaki sposób wrzucić ją do zmiennej tak żeby mPDF ją przetworzył i wykonał co trzeba. Z tego co widzę kod php nie jest akceptowalny jeśli chodzi o zawartość dla mPDFa.

Moja pętla wygląda tak:

Zmienna dla mPDF wygląda tak:

W jaki sposób wrzucić jedno do drugiego aby zostało to poprawnie zinterpretowane?
Przerzucenie całego kodu z pętlą do zmiennej nie działa.

3

@Szymek_: Życie Ci nie miłe? Przecież to XSS jak się patrzy. Uzyj htmlEntities(). Należy tego używac zawsze jak łączysz plain tekst (np taki z $_GET[]) z HTML'em.

echo '<tr>
      <td style="border-right:1px solid black">' . $row . '</td>
      <td>' . htmlEntities($_GET['txt1Row' . $row]) .'</td>
      <td>' . htmlEntities($_GET['txt2Row' . $row]) .'</td>
      <td>' . htmlEntities($_GET['txt3Row' . $row]) .'</td>
      <td>' . htmlEntities($_GET['txt4Row' . $row]) .'</td>
  </tr>';

Albo ewentualnie użyj silnika template'ów.

0
Szymek_ napisał(a):

Hejka!

Widziałem w pracy jak szef się męczy przy pisaniu w wordzie każdego PDF'a z wyceną prac osobno i chciałem mu trochę pomóc.
Amatorsko lubiłem kodować, edytować style czy skrypty ale niestety okazało się, że to zadanie mnie przerasta lekko. Utknąłem.

Dlaczego nie użyjesz do tego szablonów dokumentów lub makr?

1 użytkowników online, w tym zalogowanych: 0, gości: 1