I am using TCPDF to generate a PDF and I get the following error when i use transaction:
TCPDF ERROR: Empty font family
I have the following code snippet(with transaction for pagebreak):
$titleDesc = $sPDFQuestion;
$pageNum = $this->pdf->PageNo();
$this->pdf->startTransaction();
$this->pdf->Bookmark($sPDFQuestion, 1, 0);
$this->pdf->titleintopdf($pdfTitle, $sPDFQuestion);
if($pageNum != $this->pdf->PageNo()){
$this->pdf->rollbackTransaction(false);
$this->pdf->AddPage('P', 'A4');
$this->pdf->Bookmark($sPDFQuestion, 1, 0);
$this->pdf->titleintopdf($pdfTitle, $sPDFQuestion);
}
else {
$this->pdf->commitTransaction();
}
This is the function titleintopdf():
public function titleintopdf($title, $description = '')
{
if (!empty($title)) {
$title = $this->delete_html($title);
$oldsize = $this->FontSizePt;
$this->SetFontSize($oldsize + 4);
$this->Line(5, $this->y, ($this->w - 5), $this->y);
$this->ln(3);
$this->MultiCell('', '', $title, '', 'C', 0);
$this->MultiCell('', '', "Number:".$this->PageNo(), '', 'C', 0);
if (!empty($description) && isset($description)) {
$description = $this->delete_html($description);
$this->ln(7);
$this->SetFontSize($oldsize + 2);
$this->MultiCell('', '', $description, '', 'C', 0);
$this->ln(2);
} else {
$this->ln(4);
}
$this->MultiCell('', '', "Number:".$this->PageNo(), '', 'C', 0);
$this->Line(5, $this->y, ($this->w - 5), $this->y);
$this->ln(5);
$this->SetFontSize($oldsize);
}
}
When I don't rollback the transaction and I just commit it instead, everything works fine. I don't have a clue, why this error occurs. Do you know what the problem could be?
Greets!
The error lies in
$this->pdf->rollbackTransaction(false);
'false' means here to not restore $this->pdf to its original state, but to return the original state as a TCPDF object, so correct would be either:
$this->pdf = $this->pdf->rollbackTransaction(false);
or
$this->pdf->rollbackTransaction(true);
The error "TCPDF ERROR: Empty font family" is just a follow-up error of $this->pdf not being valid anymore.
Related
I use PHPgraphlib for many years and like that it generates a reliable image instead of some fancy Javascript-stuff. Now since update to PHP7, it renders a log-error on line 926 of the original code:
PHP Warning: count(): Parameter must be an array or object that implements Countable in ./phpgraphlib.php on line 926, referrer ...
From line 926:
protected function displayErrors()
{
if (count($this->error) > 0) {
$lineHeight = 12;
$errorColor = imagecolorallocate($this->image, 0, 0, 0);
$errorBackColor = imagecolorallocate($this->image, 255, 204, 0);
imagefilledrectangle($this->image, 0, 0, $this->width - 1, 2 * $lineHeight, $errorBackColor);
imagestring($this->image, 3, 2, 0, "!!----- PHPGraphLib Error -----!!", $errorColor);
foreach($this->error as $key => $errorText) {
imagefilledrectangle($this->image, 0, ($key * $lineHeight) + $lineHeight, $this->width - 1, ($key * $lineHeight) + 2 * $lineHeight, $errorBackColor);
imagestring($this->image, 2, 2, ($key * $lineHeight) + $lineHeight, "[". ($key + 1) . "] ". $errorText, $errorColor);
}
$errorOutlineColor = imagecolorallocate($this->image, 255, 0, 0);
imagerectangle($this->image, 0, 0, $this->width-1,($key * $lineHeight) + 2 * $lineHeight, $errorOutlineColor);
}
}
I tried to uncomment it, but it throws another error on line 271
//display errors
$this->displayErrors();
I do quite a bit with PHP and MySQL, but this exceeds my amateuer know-how. Any help welcome! Aside this error, phpgraphlib keeps working like a charm. And I use the error, as I couldn't find anything searching for this error on phpgraphlib. References to where answered sure welcome.
Thanks a million!
As commented by #aynber - adding =[] to protected $error; in line 137 did the trick. New line reads
protected $error = [];
I am using the TCPDF library to build a PDF to display results of a survey. I have the option to create a custom header to be added to the survey, that can be anything from an image to just text, which can be any size/length.
My problem is on an autobreak the Y position of the following page gets reset and runs with the header.
I am able to change the first page by capturing the current Y position and setting it after the "AddPage()" function. My issue is on the autopagebreaks that occur, I can't find anyway to check if this occurred and trigger something to happen.
I found the "checkpagebreak" but this doesn't work for when the pagebreak occurs during a multicell block of text. I checked the "custom header" example TCPDF has but it appears it uses a static sized header margin, I need to find a way to make that value dynamic.
I am using the following code
// **************************************************************************************
// Process Selection
// **************************************************************************************
function RunReport()
{
// Make all global variables available here
foreach($GLOBALS as $arraykey=>$arrayvalue)
{
if ($arraykey != "GLOBALS")
{
global $$arraykey;
}
}
require_once('tcpdf/tcpdf.php');
class PDF extends tcpdf
{
function Header()
{
//This is pulled from a database but is filled in only to show the current data I am working with***
// $this->S1LDESC = "<center>Test Application<br><img src=\"link/to/image\" width='208'; height='80'></img></center>";
if(trim($this->S1LDESC) <> "")
{
$this->SetFont('Times','',11);
$this->Cell(0, .5, "" , 0,1,'C', 0);
$newX = $this->GetX();
$newY = $this->GetY();
$this->writeHTMLCell(0, .5, $newX, $newY, trim($this->S1LDESC) , 0,1,0, true, 'C', true);
}
$this->SetFont('Times','B',11);
$this->Cell(0, .5, "" , 0,1,'C', 0);
$this->Cell(0, .5, trim($this->S1DESC), 0, 1, 'C', 0, '', 0, false, 'M', 'M');
$this->HeadY = $this->GetY();
$this->SetY($this->GetY() + 5);
}
}
$pdf = new PDF("P", PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
$pdf->SelComp = $SelComp;
$pdf->SelSchool = $SelSchool;
// set auto page breaks
$pdf->SetAutoPageBreak(true, PDF_MARGIN_BOTTOM);
$pdf->setFontSubsetting(false);
$pdf->SetPrintHeader(true);
$pdf->SetPrintFooter(false);
$pdf->AddPage();
//$pdf->SetY($pdf->HeadY);
$selstring = "SQL To Grab DATA";
if (!($result = db2_exec($db2conn, $selstring, array('CURSOR' => DB2_SCROLLABLE))))
{
echo($selstring."<BR>");
db2_close($db2conn);
die("<b>Error RunReport ". db2_stmt_error().":" . db2_stmt_errormsg()."</b><br>" . $selstring2);
}
while($row = db2_fetch_assoc($result))
{
// make the file field names available in HTML
foreach(array_keys($row) as $key)
{
$escapedField = $key;
$$escapedField = $row[$key];
}
$pdf->SetFont('Times','B',11);
if($HldGroup <> $S2GROUP)
{
$HldGroup = $S2GROUP;
if(trim($S5GROUP) <> "*None")
{
//Write Group data
$pdf->MultiCell(0, 5, trim($S5GROUP), 0, 'L', 0, 1, '', '', true);
if(trim($S5GRPDESC) <> "")
{
$pdf->MultiCell(0, 5, trim($S5GRPDESC), 0, 'L', 0, 1, '', '', true);
}
}
}
if($S2QUESTTYP <> "HD")
{
$pdf->Cell(5, 0, "", 0,0,'C', 0);
$pdf->MultiCell(0, 5, trim($S2QUESTION), 0, 'L', 0, 1, '', '', true);
$pdf->SetFont('Times','',11);
if($S2QUESTTYP <> "ND")
{
$pdf->MultiCell(0, 5, trim($S2QUESTION), 0, 'L', 0, 1, '', '', true);
}
else
{
}
$pdf->MultiCell(0, 5, "", 0, 'L', 0, 1, '', '', true);
}
}
//Print file with Student name and report name???
$pdf->Output("$SurvName.pdf", 'I');
}
This results in the following:
Page 1:
Page 2:
I am extracting data from MySQL database using php and exporting it as PDF. The columns are not getting filled due to the PDF page size. How do I push the unfilled columns to next line? So that first line has 4 columns and next line has another 4 columns, so on..
<?php
//include connection file
include_once "connection.php";
include_once 'fpdf/fpdf.php';
class PDF extends FPDF {
// Page header
function Header() {
}
// Page footer
function Footer() {
// Position at 1.5 cm from bottom
$this->SetY(-15);
// Arial italic 8
$this->SetFont('Arial', 'I', 8);
// Page number
$this->Cell(0, 10, 'Page '.$this->PageNo().'/{nb}', 0, 0, 'C');
}
}
$db = new dbObj();
$connString = $db->getConnstring();
$id = $_GET['id'];
$query = $connString->prepare("SELECT ID, Name, Wrongs, Rights, Percentage, Age FROM Datas WHERE ID=?");
$query->bind_param('s', $id);
$query->execute();
$result = $query->get_result();
$display_heading = array('ID' => 'ID', 'Name' => 'Name', 'Wrongs' => 'Wrongs', 'Rights' => 'Rights', 'Percentage' => 'Percentage', 'Age' => 'Age');
//$result = mysqli_query($connString, "SELECT ID, Name, Wrongs, Rights, Percentage, Age FROM Datas") or die("database error:". mysqli_error($connString));
$header = mysqli_query($connString, "SHOW columns FROM Datas");
$pdf = new PDF();
//header
$pdf->AddPage();
//foter page
$pdf->AliasNbPages();
$pdf->SetFont('Arial', 'B', 12);
foreach ($header as $heading) {
$pdf->Cell(45, 12, $display_heading[$heading['Field']], 1);
}
foreach ($result as $row) {
$pdf->Ln();
foreach ($row as $column) {
$pdf->Cell(45, 12, $column, 1);
}
}
$pdf->Output();
I have a html form which sends the answers onto a pdf document. Everything is working fine but I would like the questions to be on the pdf document as well.
currently it looks like this on the pdf:
Jurgen
Yes
No
4
No
I would like it to be:
Name: Jurgen
Do you own a vehicle? Yes
etc
(SOLVED)
my current code for the fpdf file:
<?php
class PDF extends FPDF
{
// Page header
function Header()
{
// Logo
$this->Image('images/logo.png', 10, 6, 30);
$this->SetFont('Arial', 'B', 15);
$this->Cell(50);
$this->Cell(90, 10, 'Document Title', 'C');
// Line break
$this->Ln(20);
}
// Page footer
function Footer()
{
$this->SetY(-15);
$this->SetFont('Arial', 'I', 8);
$this->Cell(0, 10, 'Page ' . $this->PageNo() . '/{nb}', 0, 0, 'C');
}
}
?>
<?php
//set the question values
$questions = array(
'name' => "Name: ",
'date' => "Date: ",
'first' => "First Day of Leave: ",
'last' => "Last Day of Leave: ",
'days' => "Number of Days Taken: ",
'email' => "Managers Email: ",
'sig' => "Signed: ",
);
//set the question answers
$date = $_POST['date'];
$first = $_POST['first'];
$last = $_POST['last'];
$days = $_POST['days'];
$email = $_POST['email'];
$sig = $_POST['sig'];
$name = $_POST['name'];
//set the question names
$questionName = $questions['name'];
$questionDate = $questions['date'];
$questionFirst = $questions['first'];
$questionLast = $questions['last'];
$questionDays = $questions['days'];
$questionEmail = $questions['email'];
$questionSig = $questions['sig'];
//Create the PDF
require('fpdf.php');
$pdf = new FPDF();
$pdf->AddPage();
$pdf->SetFont('Arial','B',16);
//insert questions and answers
$pdf->MultiCell(150,10,sprintf("%s %s", $questionDate, $date));
$pdf->Ln();
$pdf->MultiCell(150,10,sprintf("%s %s", $questionName, $name));
$pdf->Ln();
$pdf->MultiCell(150,10,sprintf("%s %s", $questionFirst, $first));
$pdf->Ln();
$pdf->MultiCell(150,10,sprintf("%s %s", $questionLast, $last));
$pdf->Ln();
$pdf->MultiCell(150,10,sprintf("%s %s", $questionDays, $days));
$pdf->Ln();
$pdf->MultiCell(150,10,sprintf("%s %s", $questionEmail, $email));
$pdf->Ln();
$pdf->MultiCell(50,10,sprintf("%s %s", $questionSig, $sig));
//display pdf
$pdf->Output();
I am still learning about FPDF since their documentation isn't the best. If I have made some mistakes please let me know. Thank you
To do so you can have your question in an associative array where the key matches with name attribute in your html form.
form.html
<form action="your_post.php" method="POST">
<!-- Your first question about age -->
<label>
What's your name?
<input name="name" type="text" />
</label>
<!-- Your second question -->
<label>
How old are you ?
<input name="yo" type="text" />
</label>
<input type="submit" />
</form>
your_post.php
<?php
$questions = array(
'name' => "What's your name?",
'yo' => 'How old are you?'
);
//Get you question and answer about name
$name = $_POST['name'];
$questionName = $questions['name'];
//You can of course use a foreach through $_POST to get every question
require('fpdf.php');
$pdf = new FPDF();
$pdf->AddPage();
$pdf->SetFont('Arial','B',16);
//Here concatenate $questionName and $name
$pdf->MultiCell(40,10,sprintf("%s %s", $questionName, $name));
$pdf->Output();
i can't help you with that explicit question, but i had to write a script a few days ago, which also creates a pdf.
I found a very nice tool to do this, which i decided to use instead of fpdf. It directly converts html code to a pdf. (you can also link css into it) maybe this can be also interesting for you.
https://github.com/spipu/html2pdf
This should do
<?php
$pdf = new PDF();
$pdf->Cell(20, 10, 'Name : ' . $name . '');
$pdf->Ln();
$pdf->cell(20, 10, 'Do you own a vehicle? : ' . $question1);
$pdf->Ln();
$pdf->Output();
?>
adding header, the problem you facing now
<?php
class PDF extends FPDF
{
// Page header
function Header()
{
// Logo
$this->Image('images/logo.png', 10, 6, 30);
$this->SetFont('Arial', 'B', 15);
$this->Cell(50);
$this->Cell(90, 10, 'Document Title', 'C');
// Line break
$this->Ln(20);
}
// Page footer
function Footer()
{
$this->SetY(-15);
$this->SetFont('Arial', 'I', 8);
$this->Cell(0, 10, 'Page ' . $this->PageNo() . '/{nb}', 0, 0, 'C');
}
}
?>
Update this is how your final code should look
<?php
//set the question values
$questions = array(
'name' => "Name: ",
'date' => "Date: ",
'first' => "First Day of Leave: ",
'last' => "Last Day of Leave: ",
'days' => "Number of Days Taken: ",
'email' => "Managers Email: ",
'sig' => "Signed: "
);
//set the question answers
$date = $_POST['date'];
$first = $_POST['first'];
$last = $_POST['last'];
$days = $_POST['days'];
$email = $_POST['email'];
$sig = $_POST['sig'];
$name = $_POST['name'];
//set the question names
$questionName = $questions['name'];
$questionDate = $questions['date'];
$questionFirst = $questions['first'];
$questionLast = $questions['last'];
$questionDays = $questions['days'];
$questionEmail = $questions['email'];
$questionSig = $questions['sig'];
//Create the PDF
require('fpdf.php');
class PDF extends FPDF
{
// Page header
function Header()
{
// Logo
$this->Image('images/logo.png', 10, 6, 30);
$this->SetFont('Arial', 'B', 15);
$this->Cell(50);
$this->Cell(90, 10, 'Document Title', 'C');
// Line break
$this->Ln(20);
}
// Page footer
function Footer()
{
$this->SetY(-15);
$this->SetFont('Arial', 'I', 8);
$this->Cell(0, 10, 'Page ' . $this->PageNo() . '/{nb}', 0, 0, 'C');
}
}
$pdf = new FPDF();
$pdf->AddPage();
$pdf->SetFont('Arial', 'B', 16);
//insert questions and answers
$pdf->MultiCell(150, 10, sprintf("%s %s", $questionDate, $date));
$pdf->Ln();
$pdf->MultiCell(150, 10, sprintf("%s %s", $questionName, $name));
$pdf->Ln();
$pdf->MultiCell(150, 10, sprintf("%s %s", $questionFirst, $first));
$pdf->Ln();
$pdf->MultiCell(150, 10, sprintf("%s %s", $questionLast, $last));
$pdf->Ln();
$pdf->MultiCell(150, 10, sprintf("%s %s", $questionDays, $days));
$pdf->Ln();
$pdf->MultiCell(150, 10, sprintf("%s %s", $questionEmail, $email));
$pdf->Ln();
$pdf->MultiCell(50, 10, sprintf("%s %s", $questionSig, $sig));
//display pdf
$pdf->Output();
I tried using $pdf-getAliasNumPage() and it shows the page number if it is rendered in PDF.
But when I experimented on a basic PHP and printed it, it returns only "{:pnp:}".
I used to have an if condition if the page is already changed so that I can reset a value = 0 again, but the condition was always false due to the returned value of getAliasNumPage() is equal to "{:pnp:}".
Is there any way I can find the page number as an integer? What TCPDF function is that?
I only declared AddPage() once because I don't need it.
Already used $pdf->getPage(); only returns 0.
Thanks!
$this->payroll_id = $request->getParameter('payroll_id');
$this->class = new PsPayroll();
$config = sfTCPDFPluginConfigHandler::loadConfig();
$pdf = new reportPDF(LANDSCAPE, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
$month = $this->class->mlFetchPayroll();
$month->execute(array($this->payroll_id));
$catch = "";
while ($print_month = $month->fetch()){
$catch = $print_month[8];
}
$pdf->SetCreator(Aaron);
$pdf->setMonth($catch);
$pdf->SetAuthor('');
$pdf->SetTitle('Payroll Report');
$pdf->SetSubject('');
$pdf->SetKeywords('');
$pdf->SetHeaderData('logo.png', '25', '', $catch);
$pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
$pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP + 4, PDF_MARGIN_RIGHT);
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER + 15);
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
$pdf->setFontSubsetting(true);
$pdf->SetFont('freesans', '', 9.5, '', true);
$html .= '<table class = "table hover">
<thead>
<tr>
<th>Employee Information</th>
<th>Monthly Salary</th>
<th>Earnings</th>
<th>Deductions</th>
<th>Net Pay Signature</th>
</tr>
</thead>
<tbody>';
$pager = 1;
$prepare = $this->class->mlFetchPayroll();
$prepare->execute(array($this->payroll_id));
while ($myrow = $prepare->fetch()){
$total_net_pay = 0;
$total_earning = 0;
$total_deduction = 0;
$html .= '<br><tr nobr="true"><td>' . $myrow[2] . '<br>'. $myrow[3] . '<br>' . $myrow[4] . '</td><td>' . number_format($myrow[5], 2) . '</td><td>';
$earning_array = $this->class->mlFetchEarningPayslip($myrow[10]);
foreach ($earning_array as $k => $valk){
$net_pay += $valk;
$total_earning += $valk;
$html .= '<table><tr><td>' . $k . '</td><td>' . number_format($valk, 2) . '</td></tr></table>';
}
$html .= "</td><td>";
$deduction_array = $this->class->mlFetchDeductionPayslip($myrow[10]);
foreach ($deduction_array as $i => $val){
$net_pay -= $val;
$total_deduction += $val;
$html .= '<table><tr><td>' . $i . '</td><td>'. number_format($val, 2) . '</td></tr></table>';
}
$html .= '</td><td>';
$array_date = $this->class->mlDivideMonth($myrow[8]);
$k = 0;
foreach ($array_date as $value){
$breakdown = 0.00;
$k++;
$monthly_salary = $myrow[5];
$monthly_salary += $total_earning - $this->class->mlFetchPERA($myrow[10]);
$monthly_salary -= $total_deduction;
$break_down = $monthly_salary/ 4;
$html .= '<table><tr><td align="right">';
if ($breakdown < 0)
$html .= 0;
else if ($k == 2){
$a = round($break_down, 2);
$b = $a + $this->class->mlFetchPERA($myrow[10]);
$c = number_format($b, 2);
$html .= $c;
}
else{
$a = round($break_down, 2);
$b = number_format($a, 2);
$html .= $b;
}
$html .= ' </td><td>............... </td><td>' . $value . '</td></tr></table>';
}
$html .= '</td></tr>';
$pager = $pdf->getAliasNumPage();
if ($pager == 1){
$html .= 'This is first page ' . $pdf->getAliasNumPage();
}
else{
$pager = $pdf->getAliasNumPage();
$html .= "This is page " . $pdf->getAliasNumPage();
}
// $html .= 'sample '. $pager;
}
$html .= '</tbody></table>';
$pdf->AddPage();
$pdf->writeHTML($html, true, false, false, true, 'Aaron');
$pdf->Output('payroll_'.$catch.'.pdf', 'I');
throw new sfStopException();
both PageNo() and getPage() will return the current page number.
$this->PageNo();
$this->getPage();
The correct function is PageNo()
http://www.tcpdf.org/doc/code/classTCPDF.html#a9ad828b184f08828f570a7e52316ba79
TCPDF::PageNo()
Returns the current page number.
Returns
int page number
Edit.
OK, now (I think) I understand what you want to do, you add only 1 page and use auto page breaks, you also don't want to automatically number the pages in the footer. In that case you should use getAliasNumPage() and getAliasNbPages(). Define the following variable (edit the text as you will):
$PgNo= "This is the page " . $pdf->getAliasNumPage() . " of " . $pdf->getAliasNbPages();
Put it anywhere in the php document (it is important to put it after defining the fonts) and then just use the variable $PgNo (or however you will call it) wherever you need. You have to define it only once and it will later on get the values automatically depending on which page in the pdf document it is located.
The result of $this->getAliasNumPage() is NOT a number . It's... {:pnp:}
You can check this:
$text = "My Footer - Página ".$this->getAliasNumPage().'/'.$this->getAliasNbPages();
$this->Cell(0, 10, $text, 0, false, 'C', 0, '', 0, false, 'T', 'M');
And you will see the number.
But if you perform
echo $text;
you'll see the string doesn't have the number but only {:pnp:}
This came from the fact at this time (so when it executes the Footer function), the PDF is not yet created. So TCPDF can't know the number of pages. So it can't give you this value.
What can you do? in order to get a different footer eg on some pages, you must count the page number. So, declare a global $var at beginning of the Footer() function. Before the Footer() function, set $var to 0 and then, inside Footer() just $var++.
For the last page, just use this:
class mypdf extends tcpdf
{
// Declare for use in all function
protected $last_page = false;
// Will be called at the end
public function Close()
{
$this->last_page = true;
parent::Close();
}
public function Footer()
{
if ($this->last_page)
{
// Here you can display the footer for the last page
}
}
}
Edit: I forgot one option. If you want to know the full number of pages before the display or (eg) if you want to know the size of a PDF bloc to see if it fits a page and so on, you can use the rollbackTransaction();
First, you perform all operations (AddPages, MultiCell, and so on) which will give you the capability of the reading size of the result and all other values.
Then you perform a $pdf = $pdf -> rollbackTransaction(); which will "undo" everything and then you run all your functions again, using this time all the value you get from the "first run".