Hi guys, I've been building a fairly straightforward PDF document of an invoice, primarily structuring it around the excellent writeHTML feature in tcpdf. That mirrors the basic layout of my document really well, so I have basically three separate tables jammed together so they look all like one.
There's a main header, which hold some address information, then then another table that contains the main detail section (which may break over multiple pages depending on how many lines). From that second table, I put the row header with the column titles in it in a thead, and this successfully makes that repeat on new pages.
Finally, I have a single row in a separate table that prints some summary information.
I've been pulling my hair out for some time now because I keep hitting these border conditions where, if I get close enough to the bottom of the first page, I get a triggered second page with only the header & footer! The final summary row is actually printed on the first page, but I get an effectively blank second page.
I've tried playing with the SetAutoPageBreak settings, the second parameter, but all that seems to do is let me fudge it one way or the other for specific cases, but then I can just break that with some other variation of the data.
At first I thought it might be my custom header & footers, but even once I remove those and revert to the default ones, and don't override any of the settings (margins, AutoPageBreak settings, etc.), this behavior persists.
Does anyone have any suggestions? If need be, I can post the code, but I'd have to take some time to simplify it, I think.
I've even just done a pretty good simplification of this and my conclusion is basically that the code that is deciding whether to break to a new page is seeing some sort of "ghost" content at the end of my data that doesn't really require a page break, yet it's going ahead with that anyway.
And there are no trailing s or anything like that that I can see. My HTML code just ends with a closing and everything else about it looks normal to me.
I'm pretty stuck at this point and would appreciate any help.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for the suggestion Simon. I had actually experimented with that a bit already, and I've done some more, in my more simplified example of this problem. Short answer: it doesn't seem to make any difference in my situation.
I think my real issue is the trailing one-row table at the very end providing the summary.
I suppose I could try to do something like move that summary to the footer, so it prints on all pages, but I'd rather leave it as it is, only printing at the very end after all detail rows are outputted.
If I try to merge this summary table into the main detail table, then I may end up with the summary row being alone on the last page, but with the detail thead row repeated in front of it, which is wrong, of course.
I'm will to try a hack even, and just try to detect after the writeHTML call is complete whether the final page is blank in some way. To this end, I've experimented with $pdf->GetY(), and oddly, I find that in my border conditions a) where we have 1 correctly full page and b) where we have no content on page 2, but a blank page 2, the final GetY is:
a) 188.514805
b) 188.515027
(these are mm, I think, for a landscape A4 page) which indicates to me that tcpdf knows it has not rolled to the second page yet (with actual content) but it still has inserted the page. I think that's probably a bug.
Anyone agree? Should I bother trying to submit the simplest example of this I can come up with for a possible fix?
Any suggestions for a hacky workaround in the meantime? Anything better than trying to detect some fine difference in the final GetY as I'm suggesting above?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I actually just noticed something else a little weird, that might be a reliable hack to use, related to making the second writeHTML parm true or false:
It seems like in my border/error condition, where I've got the unwanted blank page, if I check GetY w/ that parm true and then false, GetY stays exactly the same.
However, it appears that w/ one less row (where things are good) or one more row (where we correctly have a second page), the final GetY does change when the parameter is true vs. false.
So, even though that'd require me to do writeHTML twice, it does seem to be a condition that's detectable (and probably has something to with the cause of the bug).
I may try that then.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I actually just noticed something else a little weird, that might be a reliable hack to use, related to making the second
writeHTML parm true or false:
I made an invoice program quite the same as yours; when part #2
(items list w/ prices, etc) is written, I launch a transaction
and write the recap.
If GetY() is low after this it means recap triggered a new page,
if not, recap fits on this page.
Then I rollback the transaction.
In the 1st case, I print some empty lines to make sure the recap
will be fully printed on the last page, then I re-position X,Y
to the right coords, print the recap and also print vertical lines
to fill the empty space between items list header and recap.
In the 2nd case, I do the same, except for the fist empty lines.
This obviously depends on a recap height manual measurement, which
is not a very good solution, but I spent more than a month with
the python reportlab shit failing, when it only took me 10 days
to get what I wanted with tcpdf (BTW, thanks to its creator:)
--
Sniper'z: It must be crappy to write an horror novel
Sniper'z: First, you're afraid of the empty page
Sniper'z: Then, you're afraid of of the full page
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ah yes, so others have been known to do hacks similar to mine to get the desired results in a situation such as this.
So, I have partial success at least to report on the last suggestion I'd made. I did this, in short:
// save copy with just one blank page, to revert to
$pdfCopy = clone $pdf;
$pdf->writeHTML($html, true);
$yWithLn = $pdf->GetY();
// throw out original result since we have $yWithLn now
$pdf = $pdfCopy;
$pdf->writeHTML($html, false); // note second writeHTML uses 'false'
$yWithoutLn = $pdf->GetY();
// if two Ys are equal, we probably have a trailing blank page, so
// delete it
if ($yWithLn == $yWithoutLn)
$pdf->deletePage($pdf->getNumPages());
so far, at least, this seems to achieve my goal, even with custom headers & footers turned on.
Hope this can help someone else in a similar situation.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi guys, I've been building a fairly straightforward PDF document of an invoice, primarily structuring it around the excellent writeHTML feature in tcpdf. That mirrors the basic layout of my document really well, so I have basically three separate tables jammed together so they look all like one.
There's a main header, which hold some address information, then then another table that contains the main detail section (which may break over multiple pages depending on how many lines). From that second table, I put the row header with the column titles in it in a thead, and this successfully makes that repeat on new pages.
Finally, I have a single row in a separate table that prints some summary information.
I've been pulling my hair out for some time now because I keep hitting these border conditions where, if I get close enough to the bottom of the first page, I get a triggered second page with only the header & footer! The final summary row is actually printed on the first page, but I get an effectively blank second page.
I've tried playing with the SetAutoPageBreak settings, the second parameter, but all that seems to do is let me fudge it one way or the other for specific cases, but then I can just break that with some other variation of the data.
At first I thought it might be my custom header & footers, but even once I remove those and revert to the default ones, and don't override any of the settings (margins, AutoPageBreak settings, etc.), this behavior persists.
Does anyone have any suggestions? If need be, I can post the code, but I'd have to take some time to simplify it, I think.
I've even just done a pretty good simplification of this and my conclusion is basically that the code that is deciding whether to break to a new page is seeing some sort of "ghost" content at the end of my data that doesn't really require a page break, yet it's going ahead with that anyway.
And there are no trailing
s or anything like that that I can see. My HTML code just ends with a closing and everything else about it looks normal to me.
I'm pretty stuck at this point and would appreciate any help.
By default writeHTML adds a new line following the HTML.
See: http://www.tcpdf.org/doc/code/classTCPDF.html#ac3fdf25fcd36f1dce04f92187c621407
You should do writeHTML($html, FALSE) to avoid the new line.
Thanks for the suggestion Simon. I had actually experimented with that a bit already, and I've done some more, in my more simplified example of this problem. Short answer: it doesn't seem to make any difference in my situation.
I think my real issue is the trailing one-row table at the very end providing the summary.
I suppose I could try to do something like move that summary to the footer, so it prints on all pages, but I'd rather leave it as it is, only printing at the very end after all detail rows are outputted.
If I try to merge this summary table into the main detail table, then I may end up with the summary row being alone on the last page, but with the detail thead row repeated in front of it, which is wrong, of course.
I'm will to try a hack even, and just try to detect after the writeHTML call is complete whether the final page is blank in some way. To this end, I've experimented with $pdf->GetY(), and oddly, I find that in my border conditions a) where we have 1 correctly full page and b) where we have no content on page 2, but a blank page 2, the final GetY is:
a) 188.514805
b) 188.515027
(these are mm, I think, for a landscape A4 page) which indicates to me that tcpdf knows it has not rolled to the second page yet (with actual content) but it still has inserted the page. I think that's probably a bug.
Anyone agree? Should I bother trying to submit the simplest example of this I can come up with for a possible fix?
Any suggestions for a hacky workaround in the meantime? Anything better than trying to detect some fine difference in the final GetY as I'm suggesting above?
I actually just noticed something else a little weird, that might be a reliable hack to use, related to making the second writeHTML parm true or false:
It seems like in my border/error condition, where I've got the unwanted blank page, if I check GetY w/ that parm true and then false, GetY stays exactly the same.
However, it appears that w/ one less row (where things are good) or one more row (where we correctly have a second page), the final GetY does change when the parameter is true vs. false.
So, even though that'd require me to do writeHTML twice, it does seem to be a condition that's detectable (and probably has something to with the cause of the bug).
I may try that then.
On Tue, 25 Mar 2014 18:08:58 +0000
"jll" ice4x800@users.sf.net wrote:
I made an invoice program quite the same as yours; when part #2
(items list w/ prices, etc) is written, I launch a transaction
and write the recap.
If GetY() is low after this it means recap triggered a new page,
if not, recap fits on this page.
Then I rollback the transaction.
In the 1st case, I print some empty lines to make sure the recap
will be fully printed on the last page, then I re-position X,Y
to the right coords, print the recap and also print vertical lines
to fill the empty space between items list header and recap.
In the 2nd case, I do the same, except for the fist empty lines.
This obviously depends on a recap height manual measurement, which
is not a very good solution, but I spent more than a month with
the python reportlab shit failing, when it only took me 10 days
to get what I wanted with tcpdf (BTW, thanks to its creator:)
--
Sniper'z: It must be crappy to write an horror novel
Sniper'z: First, you're afraid of the empty page
Sniper'z: Then, you're afraid of of the full page
Ah yes, so others have been known to do hacks similar to mine to get the desired results in a situation such as this.
So, I have partial success at least to report on the last suggestion I'd made. I did this, in short:
so far, at least, this seems to achieve my goal, even with custom headers & footers turned on.
Hope this can help someone else in a similar situation.
The blank page is not really a real new page because when you add a page, you're still on the white page. So this fixed the problem :
$this->pdf->AddPage('P', 'A4');
$this->pdf->deletePage($this->pdf->getNumPages());