This topic is locked
[SOLVED]

Print and Forms Management in PDF

10/24/2019 5:27:49 AM
PHPRunner Tips and Tricks
fhumanes author

Many Public Administrations and many important companies, have old systems to facilitate that in their portals, citizens or their own staff, initiate a process through the data filled in in a request in PDF format.
Important sums of money have been paid to Adobe, to make the same PDF’s documents the required data entry forms and their validation.
These platforms, very expensive, have ceased to be operational because the device most used by the Citizens has ceased to be the PC and the use of the mobile phone has been extended.
However, PDF documents are used to receive applications and to issue resolutions, since they incorporate electronic signatures very efficiently and international and national laws and regulations, admit them as reliable documents, if their signatures are issued by Recognized Entities .
Thus, the proposal is to keep PDF documents, but not to use them for (forms) to capture your data.
To fully understand the proposed technical solution I suggest that you previously read the article that explains how to obtain the location points of the fields in the PDF document.
Advantages of using PDF forms:

  • For both the Citizen and the Employees, what is changed is the photocopy of the form to another image, which is used to fill in the data by hand or through the browser. It has no adaptation costs.


Disadvantages of using PDF forms:

  • Platforms for using PDF documents as forms are very expensive and very expensive to develop form validations.
  • To use in small screen devices (mainly mobile) is not a suitable solution.


The PHPRunner solution is a very powerful tool for making forms, it can be used on PCs and mobile devices, with the same development and the validations and controls that the forms require can be implemented very quickly. On the contrary, the PDF documents that it provides are simple and do not conform to the forms that are used in the companies, which on the other hand, must continue to offer the PDF for those users who wish to fill them with a pen. To enhance PHPRunner I have incorporated the use of FREE libraries of SETASIGN


Although the example is a single application, for Administrations that require a large number of Printings and a constant update of them, the solution architecture would not be this. The forms would be independent applications, although they would share codes, data and infrastructure among them, thus facilitating the continuous updating of these forms.


The example consists:

  • Print List
  • Steps (blocks) for completing the form. The PHPRunner STEP functionality is not used, because it has problems reporting errors.
  • Fields of the form and their translation to points X, Y and page of the PDF template.



"This is not a solution, but it is an example for you to build YOUR SOLUTION"
The data model used is:


The most relevant PHP codes are:


print_pdf.php



<?php

/*

// Variables of SESSION
$_SESSION['S_forms_id'] = $data['idforms'];

$_SESSION['S_forms_code'] = $data['Code'];

$_SESSION['S_forms_name'] = $data['Name'];

$_SESSION['S_forms_table'] = $data['Table'];

$_SESSION['S_company_id'] = $data['companies_company_id'];

$_SESSION['S_dept_id'] = $data['departments_dept_id'];

$_SESSION['S_forms_query'] = $data['Query'];

$_SESSION['S_forms_template_pdf'] = $data['TemplatePDF'];

$_SESSION['S_forms_template_pages'] = $data['TemplatePages'];

$_SESSION['S_forms_template_point_x'] = $data['TemplatePointX'];

$_SESSION['S_forms_template_point_y'] = $data['TemplatePointY'];
$_SESSION['S_forms_petition_id']

*/

// Recover Config variables

$Numeric_symbol_of_thousands = $_SESSION['config'][array_search('Numeric_symbol_of_thousands', array_column($_SESSION['config'], 'name'))][value];

$Numeric_decimal_symbol = $_SESSION['config'][array_search('Numeric_decimal_symbol', array_column($_SESSION['config'], 'name'))][value];

$Date_format = $_SESSION['config'][array_search('Date_format', array_column($_SESSION['config'], 'name'))][value];

$Date_and_time_format = $_SESSION['config'][array_search('Date_and_time_format', array_column($_SESSION['config'], 'name'))][value];

$Time_format = $_SESSION['config'][array_search('Time_format', array_column($_SESSION['config'], 'name'))][value];

$Long_Date_Format = $_SESSION['config'][array_search('Long_Date_Format', array_column($_SESSION['config'], 'name'))][value];

$date_default_timezone_set = $_SESSION['config'][array_search('date_default_timezone_set', array_column($_SESSION['config'], 'name'))][value];

$setlocale_LC_TIME = $_SESSION['config'][array_search('setlocale_LC_TIME', array_column($_SESSION['config'], 'name'))][value];
date_default_timezone_set($date_default_timezone_set);

setlocale(LC_TIME, $setlocale_LC_TIME);
$l_sql = $_SESSION['S_forms_query'];

$Petition_id = $_SESSION['S_forms_petition_id'];

$forms_id = $_SESSION['S_forms_id'];
// Read info of record of forms

global $conn;

$sql_1 = str_replace("#key", $Petition_id, $l_sql);

$resql_1 = db_query($sql_1,$conn);

$data=$resql_1->fetch_all(MYSQLI_ASSOC);
// get information about uploaded files

$fileArray = my_json_decode($_SESSION['S_forms_template_pdf']);

// set the source file

$template_pdf = $fileArray[0]["name"];

$TotalPagesTemplate = $_SESSION['S_forms_template_pages'];
require_once __DIR__ . '/../../ComponentCode/fpdi_2_2/autoload.php';

use setasign\Fpdi\Fpdi;

// initiate FPDI

$pdf = new Fpdi();

// add a page

$pdf->AddPage();

// set the source file

$pdf->setSourceFile($template_pdf);

// import page 1

$tplIdx = $pdf->importPage(1);

// use the imported page and place it at position 10,10 with a width of 100 mm

$pdf->useTemplate($tplIdx);
// Obtain measures from the page for the transformation of the Points

$pdf->SetXY(1, 1);

// $pdf->SetFont('Arial','',10); // Font, type and size

// $pdf->SetTextColor(0, 96, 175); // Color in R, G, B

$w = $pdf->GetPageWidth();

$h = $pdf->GetPageHeight();

$wPt = $_SESSION['S_forms_template_point_x']; // Measures in points of the page

$hPt = $_SESSION['S_forms_template_point_y']; // Measures in points of the page

$coef_x = $wPt/$w; // X axis transformation coefficient

$coef_y = $hPt/$h; // Y axis transformation coefficient
$sql_1 = "

SELECT * FROM form_fields WHERE forms_idforms = $forms_id AND NumberPageTemplate <> 0 order by NumberPageTemplate, idform_fields

";

// All Field => forms_idforms, Name, Type, Length, IsNumber, IsDecimal, NumberDecimal, Font, FontSize, FontStyle, FontColor, Align, NumberPageTemplate, PointX, PointY, RightMargin, Description

$resql_1 = db_query($sql_1,$conn);

$fields=$resql_1->fetch_all(MYSQLI_ASSOC);

// Loop to complete values

for ($i = 0; $i < count($fields); $i++) {

// Align

switch ($fields[$i][Align]) {

case 1:

$fields[$i][Align] = 'R' ;

break;

case 2:

$fields[$i][Align] = 'C' ;

break;

default:

$fields[$i][Align] = 'L' ;

break;

}

// FontStyle

switch ($fields[$i][FontStyle]) {

case 1:

$fields[$i][FontStyle] = 'B' ;

break;

case 2:

$fields[$i][FontStyle] = 'I' ;

break;

case 3:

$fields[$i][FontStyle] = 'U' ;

break;

default:

$fields[$i][FontStyle] = '' ;

break;

}

}

// Loop to control template pages

for ($page = 1; $page <= $TotalPagesTemplate; $page++) {

foreach ($fields as $field) {

// Fields = forms_idforms, Name, Type, Length, IsNumber, IsDecimal, NumberDecimal, Font, FontSize, FontStyle, FontColor, Align, NumberPageTemplate, PointX, PointY, RightMargin, Description

if ( $field['NumberPageTemplate'] == $page ) { // Field is of page of Tamplate

$pdf->SetXY($field['PointX']/$coef_x, $field['PointY']/$coef_y); // Positioning on the page

$pdf->SetMargins($field['PointX']/$coef_x,5,$field['RightMargin']/$coef_x);

$pdf->SetFont($field['Font'],$field['FontStyle'],$field['FontSize']); // Font, type and size

$FontColor = explode(",",$field['FontColor']);

$pdf->SetTextColor($FontColor[0],$FontColor[1],$FontColor[2]); // Color in R, G, B



$Name = $field['Name'];

$Value = $data[0][$Name];

$Value = iconv("UTF-8", "ISO-8859-1//TRANSLIT", $Value); // Convert UTf8

// FontStyle

switch ($field[Type]) {

case 0: // Char

$pdf->Cell(0,0,$Value,0,1,$field[Align]);

break;

case 1: // Num

$Value = number_format($Value, $field[NumberDecimal],$Numeric_decimal_symbol,$Numeric_symbol_of_thousands);

$pdf->Cell(0,0,$Value,0,1,$field[Align]);

break;

case 2: // Integer

$pdf->Cell(0,0,$Value,0,1,$field[Align]);

break;

case 3: // Date

// $date = date_create($Value);

// $Value = date_format($date, $Date_format);

$Value = strftime($Date_format, strtotime($Value));

$pdf->Cell(0,0,$Value,0,1,$field[Align]);

break;

case 4: // Time

// $date = date_create($Value);

// $Value = date_format($date, $Time_format);

$Value = strftime($Time_format, strtotime($Value));

$pdf->Cell(0,0,$Value,0,1,$field[Align]);

break;

case 5: // DateTime

// $date = date_create($Value);

// $Value = date_format($date, $Date_and_time_format);

$Value = strftime($Date_and_time_format, strtotime($Value));

$pdf->Cell(0,0,$Value,0,1,$field[Align]);

break;

case 6: // Date Long

// $date = date_create($Value);

// $Value = date_format($date, $Long_Date_Format);

$Value = strftime($Long_Date_Format, strtotime($Value));

$pdf->Cell(0,0,$Value,0,1,$field[Align]);

break;

case 7: // Boolean

$pdf->SetFont('ZapfDingbats',$field['FontStyle'],$field['FontSize']); // Font, type and size

If ($Value == 1) {$Value = '4';} else {$Value = '';} // 'l' Punto negro

$pdf->Cell(0,0,$Value,0,1,$field[Align]);

break;

case 8: // Memo

$pdf->Write(5, $Value);

break;

default:

$pdf->Cell(0,0,$Value,0,1,$field[Align]);

}
}
}

if ($page <> $TotalPagesTemplate) {

// adding the second page of the template

$tplIdx2 = $pdf->importPage($page+1);

$s = $pdf->getTemplatesize($tplIdx2);

$pdf->AddPage('', $s);

$pdf->useImportedPage($tplIdx2);

}

}

$pdf->Output('I','forms.pdf');

/*

// -------------------- foot to save the new PDF document ------------------

$temp_file = tempnam(sys_get_temp_dir(), 'PDF');

$pdf->Output('F',$temp_file);
// ------------------ Operation with file result -------------------------------------------

$documento = file_get_contents($temp_file);

unlink($temp_file); // delete file tmp

header("Content-Disposition: attachment; filename= forms.pdf");

header('Content-Type: application/pdf');

echo $documento;

*/
?>



capture_sql_fields.php



<?php

$data = $button->getCurrentRecord();
// From the form selection

$l_idforms = $data['idforms'];

$l_code = $data['Code'];

$l_name = $data['Name'];

$l_table = $data['Table'];

$l_sql = $data['Query'];
global $conn;

// Delete fields of Query

$sql_1 = "delete FROM form_fields WHERE forms_idforms = $l_idforms";

$resql_1 = db_query($sql_1,$conn);

// Select fields of Query

$sql_1 = str_replace("#key", "1", $l_sql);

$resql_1 = db_query($sql_1,$conn);

$data2=$resql_1->fetch_all(MYSQLI_ASSOC);

//

$fields = array_keys($data2[0]);

foreach ($fields as $field) {

// Insert fields of query

$sql_1 = "

Insert into form_fields

(forms_idforms, Name)

values ($l_idforms,'$field')";

$resql_1 = db_query($sql_1,$conn);

}

?>


I used a form from a Public Administration in Madrid, to make it a real case.


It has 2 pages. In the second it also has fields.
DEMO. You have this URL https://fhumanes.com/forms/, if you wish to try it (it is in Spanish and English). Passwords «admin / admin»
I also leave the project (PHPRunner 10.2), the data model and an example of the Database. I leave the file that goes in the "FILES" directory and that is the PDF template of the example.
For any questions or queries, I leave my email account [email="fernandohumanes@gmail.com"]fernandohumanes@gmail.com[/email]

W
wpl 10/25/2019

Fernando,
very interesting approach! Kudos. I just had a look into the PHRunner project with the files you supplied (DB-dump, forms.phpr, etc). However, in the "Pages" section of PHPRunner (10.2), none of the pages is checked for all of the tables of the project, though the "Query" section for all tables works just fine. Any advice to solve this?
Thanks and regards

fhumanes author 10/25/2019

Hello:

Sorry, my English is not very good and I have not been able to understand what you are asking me.

You may ask me why the views of the steps do not have access authorization. I have solved this in the "GetTablePermissions" event with the code:



$ permissions = 'SE';

return $ permissions;



To be productive in PHPRunner I make the code of a Step and then copy the view for the following Steps. If you observe, the codes of the Steps are the same and what varies are the Fields and their Validations.

Regards,
P.S. I prefer that the consultations be by email because it is the way that I find out that there is a question since the forum does not notify if there are dependent questions.

fhumanes author 10/25/2019



Fernando,
very interesting approach! Kudos. I just had a look into the PHRunner project with the files you supplied (DB-dump, forms.phpr, etc). However, in the "Pages" section of PHPRunner (10.2), none of the pages is checked for all of the tables of the project, though the "Query" section for all tables works just fine. Any advice to solve this?
Thanks and regards


Thank you.
There was an error in the ZIP of the PHPRunner project that I don't understand how it happened.
I think I have already corrected it.
Regards,
Fernando

lefty 11/1/2019



Thank you.
There was an error in the ZIP of the PHPRunner project that I don't understand how it happened.
I think I have already corrected it.
Regards,
Fernando


Thanks for the info , Just wondering where you store your plugins? When I put them in the source folder to be used on any project they do not come out in the output in the plugin folder. Thanks in advance.

fhumanes author 11/3/2019

Hello:
I guess I wonder where libraries PHP and/or Javascript is installed.
Before I left them in the PHPRunner project, usually under a directory on the part of "custom file". Now, how are you PHP libraries are usually very heavy (many megabytes) usually leave out the project, usually in a "ComponentCode" directory in order to make the simplest to PHPRunner work and have less time duplicate these libraries.
Regards,

fhumanes author 4/13/2020

Hello:
I beg you, that if by mistake, you destroy the test set that is in the DEMO, you indicate it to me by email in order to replace it.
For colleagues who are going to consult this example, it is of no use if they cannot do a simple test of it.
Thank you,
Fernando