TCPDF with FPDI templates and THEAD - pdf

I have a html table with THEAD output with writeHTML which should be displayed on every page at the top of the table. It works but when I use a template loaded by FPDI the head is white and disappears on the second page and further. I can mark the head field with the mouse but the appear white. The border only appears as a little point on the left.
I already tried to add $this->setPageMark() to the addPage method. But its still the same issue.
public function AddPage($orientation = '', $format = ''){
parent::AddPage($orientation, $format);
if($this->template != null){
$this->useTemplate($this->template);
$this->setPageMark();
}
}

you need to enable page breaks at the beginning which is causing the issue you are having;
this is a sample code snippet ;
require_once('tcpdf/tcpdf.php'); //main code
require_once('tcpdf/fpdi.php'); //read existing pdf and sends to fpdf
$pdf = new FPDI();
$pdf->setPrintHeader(false); //no header
$pdf->setPrintFooter(false);//no footer
$pdf->SetAutoPageBreak(FALSE, 0); // set auto page breaks
//loop starts here
{
$pdf->setSourceFile($page_background); //set page
$templateId = $pdf->importPage(1); //we only need the first page
$pdf->useTemplate($templateId); //use the imported page
//your write html code and any other tcpdf related code comes here
}
$pdf->Output(outcome.pdf, 'I'); //use F instead of I to show generated pdf.

Related

Header in a XWPFDocument is only on the last page when adding section breaks

I am trying to create a word document using Apache POI. This document includes images, and I need to flip the page with the image to be landscape oriented, while keeping the rest of the document portrait oriented. However, I also need to use a header (and a footer, but I assume it is gonna work the same way as headers do).
The code I am using:
val document = XWPFDocument()
// the header I need to be on every page
document.createHeader(HeaderFooterType.DEFAULT).createParagraph().createRun().setText("Header")
// some text before the image
var par = document.createParagraph()
var run = par.createRun()
run.setText("I am text")
// add the image, flip the page with the image onto landscape
par = document.createParagraph()
val pageSize = par.ctp.addNewPPr().addNewSectPr().addNewPgSz() // this creates new section, so I can get the pageSize
pageSize.orient = STPageOrientation.LANDSCAPE
pageSize.h = BigInteger.valueOf(595 * 20) // unit used TWIPS (Twentieth of an Imperial Point)
pageSize.w = BigInteger.valueOf(842 * 20)
run = par.createRun()
val decodedByteArray = Base64.getDecoder().decode(PLACEHOLDER_IMAGE.substringAfter(','))
run.addPicture(
ByteArrayInputStream(decodedByteArray),
XWPFDocument.PICTURE_TYPE_PNG,
"",
pixelToEMU(400),
pixelToEMU(150)
)
// some text after the image
par = document.createParagraph()
run = par.createRun()
run.setText("Me too")
val out = FileOutputStream("Output.docx")
document.write(out)
out.close()
document.close()
The resulting document however has the header only after the last section break. I am aware, that every section has its' own header/footer, and that you can set the header to be the same as the previous, but the header I need seems to be always the last header, and I have no idea how to make it stick to the front of the document, where it can be used by the following sections.
Image of the resulting document
So my question is: How can I make the header appear on every page, while keeping the page formatting as is? If there is a way to make the individual pages, with the images, flip orientation without inserting section breaks, that would be a solution aswell.
In my attempts to solve this, I've been able to put data only into the header in the last section, but never have I managed to actually get my hands on the headers in the previous sections, or on the default header. Notice, that the header in the code I'm creating is set as default, but the real default header is empty and I haven't been able to access it.
NOTE: This is not the actual project, here I've only isolated the problem into a much simpler code without giving any real thought to coding style, etc.
The problem is that sections not only have separate page settings but have separate header/footer settings too.
XWPFDocumnet.createHeader creates a header which reference gets stored in document body section properties. If you create a paragraph having own section properties - a section break paragraph - then the section properties in this section break paragraph also needs a reference to a header, else the section above that section break paragraph has no header.
Best solution I can think of is to always take a copy of the document body section properties to be the section properties of additional section break paragraphs. Then only change what needs to be changed. So the copy contains needed references to headers and/or footeres already.
The following complete example shows that. The method createSectionbreak always takes a copy of the document body section properties, except there are none. Then it creates new section properties for the section break paragraph. The method setPageSizeLandscape then changes the page size.
The code is Java code. Me not using Kotlin. But the principle shold be clear also from that.
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.wp.usermodel.HeaderFooterType;
public class CreateWordSectionsPageSizeHeader {
static org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr getDocumentBodySectPr(XWPFDocument document) {
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1 ctDocument = document.getDocument();
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody ctBody = ctDocument.getBody();
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr ctSectPrDocumentBody = ctBody.getSectPr();
return ctSectPrDocumentBody;
}
static XWPFParagraph createSectionbreak(XWPFDocument document) {
XWPFParagraph sectionBreakParagraph = document.createParagraph();
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr ctSectPrDocumentBody = getDocumentBodySectPr(document);
if (ctSectPrDocumentBody != null) {
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr ctSectPrNewSect = (org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr)ctSectPrDocumentBody.copy();
sectionBreakParagraph.getCTP().addNewPPr().setSectPr(ctSectPrNewSect);
} else {
sectionBreakParagraph.getCTP().addNewPPr().addNewSectPr();
}
return sectionBreakParagraph;
}
static void setPageSizeLandscape(XWPFParagraph sectionBreakParagraph) {
if (sectionBreakParagraph.getCTP().getPPr() == null) return;
if (sectionBreakParagraph.getCTP().getPPr().getSectPr() == null) return;
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr ctSectPr = sectionBreakParagraph.getCTP().getPPr().getSectPr();
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageSz ctPageSz = ctSectPr.getPgSz();
if (ctPageSz == null) ctPageSz = ctSectPr.addNewPgSz();
ctPageSz.setOrient​(org.openxmlformats.schemas.wordprocessingml.x2006.main.STPageOrientation.LANDSCAPE);
// paper format letter
ctPageSz.setH(java.math.BigInteger.valueOf(12240)); //12240 Twips = 12240/20 = 612 pt = 612/72 = 8.5"
ctPageSz.setW(java.math.BigInteger.valueOf(15840)); //15840 Twips = 15840/20 = 792 pt = 792/72 = 11"
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument();
XWPFParagraph paragraph;
XWPFRun run;
// create header start
XWPFHeader header = document.createHeader(HeaderFooterType.DEFAULT);
paragraph = header.getParagraphArray(0);
if (paragraph == null) paragraph = header.createParagraph();
paragraph.setAlignment(ParagraphAlignment.LEFT);
run = paragraph.createRun();
run.setText("Header");
// create header end
// create body content
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Text in section 1");
// create section break
paragraph = createSectionbreak(document);
setPageSizeLandscape(paragraph);
// create section break end
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Text in section 2");
// create body content end
FileOutputStream out = new FileOutputStream("./CreateWordSectionsPageSizeHeader.docx");
document.write(out);
out.close();
document.close();
}
}

Gecko Engine in ABCPDF not finding tags

Has anyone tried to implement tags using the ABCPDF Gecko engine? I have it working fine on the MSHTML engine (Internet Explorer) as soon as I use Gecko, which is rendering my HTML better, it can't find the tags specified in the HTML.
I'm using style="abcpdf-tag-visible: true;" to specify a tag which works using the default engine.
The following code produces a blank document.
[Test]
public void Tags_With_Gecko()
{
Doc theDoc = new Doc();
theDoc.Rect.Inset(100, 100);
theDoc.Rect.Top = 700;
theDoc.HtmlOptions.Engine = EngineType.Gecko;
// Tag elements with style 'abcpdf-tag-visible: true'
theDoc.HtmlOptions.ForGecko.AddTags = true;
int id = theDoc.AddImageHtml("<FONT id=\"p1\" style=\"abcpdf-tag-visible: true; font-size: 72pt\">Gallia est omnis divisa in partes tres.</FONT>");
// Frame location of the tagged element
XRect[] tagRects = theDoc.HtmlOptions.ForGecko.GetTagRects(id);
foreach (XRect theRect in tagRects)
{
theDoc.Rect.String = theRect.ToString();
theDoc.FrameRect();
}
// Output tag ID
string[] tagIds = theDoc.HtmlOptions.ForGecko.GetTagIDs(id);
theDoc.Rect.String = theDoc.MediaBox.String;
theDoc.Rect.Inset(20, 20);
theDoc.FontSize = 64;
theDoc.Color.String = "255 0 0";
theDoc.AddText("Tag ID \"" + tagIds[0] + "\":");
// Save the document
const string testFilename = #"C:\pdf\HtmlOptionsGetTagRects.pdf";
if (File.Exists(testFilename))
File.Delete(testFilename);
theDoc.Save(testFilename);
theDoc.Clear();
Process.Start(testFilename);
}
Almost identical code for the default engine produces it correctly.
I've been talking to WebSuperGoo support. Found out the documentation isn't consistent/complete.
http://www.websupergoo.com/helppdfnet/source/5-abcpdf/xhtmloptions/2-properties/addtags.htm
In Gecko, your tag has to have a visible impact on the page for it to be picked up. In my case, I had a tag that displayed a non-breaking space, and thus it wasn't found.
From their example, changing the style to the following got it to be findable:
style="abcpdf-tag-visible: true; border: 1px solid transparent"
Note the Border settings is what makes this work apparently.
Again, this fixes their demo and thus should fix Dillorscroft's example.
I have to futz a bit more to fix my problem, as I am trying to allocate blank spaces on the page (for a table of contents) so they can be updated after the html is rendered and I know where the first content page will start.

DOMPDF: page_script(): Check current page content?

I am using dompdf to generate reports which sometimes has a front page, and sometimes has some attachments. The main content has a header and a footer, but the front page and the attachments (the last 3 to 5 pages of the pdf) should not contain header and footer. I'm placing the header and footer with a inline php page_script(), like this:
<script type="text/php">
if (isset($pdf) ) {
$pdf->page_script('
if ( $PAGE_COUNT > 10 && $PAGE_NUM == 1) {
//front page footer
}else{
//other pages' header and footer
}
');
}
</script>
The whole report is built by a database engine which outputs it all as a temporary html.txt-file which is then read into DOMPDF.
Now, to recognize the front page I just have to check if the page number is = 1. If any attachments are added (which are comprised of 1000px-height jpg images, each on their own page)
Does anyone have an idea for how to identify these "attachment"-pages and get DOMPDF to not render a header and footer on those pages? Or is there any way I could check within the page_script()-script whether the current page contains only an image (or perhaps an image with a specific class or identifier)?
Thanks for any help,
David
Detecting the current page contents may be possible, but I'd have to research exactly what you can do at this level. An easier method would be if you could inject some inline script in your generated document. After the main content and before the attachments you could add something like $GLOBALS['attachments'] = true; and then add a check on the status of this variable to your conditional.
<script type="text/php">
if (isset($pdf) ) {
$pdf->page_script('
if ( $PAGE_COUNT > 10 && $PAGE_NUM == 1) {
//front page footer
}elseif ($GLOBALS['attachments']) {
//attachments actions
}else{
//other pages' header and footer
}
');
}
</script>
Of course, don't forget to initialize the variable to false at the top of the document.
(from https://groups.google.com/d/topic/dompdf/mDsYi8Efnhc/discussion)

iText Pdf Header Removal for particular page

I'm generating a PDF with iText, in that I'm displaying a header and footer.
Now i want to remove header for a particular page.
For eg: If I'm generating a 50 pages pdf, for the final 50th I don't want to show header,
how could this be achieved?
Here's my code where I'm generating footer (header part removed).
public class HeaderAndFooter extends PdfPageEventHelper {
public void onEndPage (PdfWriter writer, Document document) {
Rectangle rect = writer.getBoxSize("art");
switch(writer.getPageNumber() % 2) {
case 0:
case 1:
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_CENTER, new Phrase(String.format("%d", writer.getPageNumber())),
300f, 62f, 0);
break;
}
}
}
Any suggestions? Thanks in advance.
You can use a 2-pass approach:
1st pass : generate the PDF file without header
2nd pass : stamp the header on all but the last page
Have a look at this example taken from the iText book. You'll just have to adapt the second pass by only going through the N-1 first pages:
int n = reader.getNumberOfPages() - 1;
instead of
int n = reader.getNumberOfPages();
I was also in need to do the same. I want to share how I resolved this issue.
The Idea is, for the automatic generation of header footer, we set page event on PDFWriter like:
HeaderAndFooter event= new HeaderAndFooter(); //HeaderAndFooter is the implementation of PdfPageEventHelper class
writer.setPageEvent(event);// writer is the instance of PDFWriter
So, before the content of the last page, We can remove the event:
event=null;
writer.setPageEvent(event);
It works for me without any error or exception.

Rally Cardboard render : Add item to card header

I want to add a value from a custom user attribute to the header of the cards in the default cardboard Kanban app. I added the following to the render function :
.....
var idDiv = document.createElement("div");
dojo.addClass(idDiv, "leftCardHeader");
header.appendChild(idDiv);
// MY NEW CODE
if(item.Domain && item.Domain.length > 0) {
var domainDiv = document.createElement("div");
domainDiv.appendChild(document.createTextNode(
" Domain: " + item.Domain));
header.appendChild(domainDiv);
}
// END MY NEW CODE
var ownerImg = document.createElement("img");
dojo.addClass(ownerImg, "cardOwner");
var ownerName = document.createElement("div");
dojo.addClass(ownerName, "cardOwnerName");
header.appendChild(ownerImg);
header.appendChild(ownerName);
....
This adds the text value to the card header but in doing so it pushes the owner name and image down a row in alignment. I have looked at the CSS but don't see any formating that is sting length dependent but I am still relatively new to this area. I tried changing the font size in the CSS but that didn't change anything adding the above code always pushes the owner name and owner image down a line.
Any help on what I might be doing wrong or if there is a cleaner way to dothis is appreciated.
You are appending a div, which is a block element- that is why you are getting the new line. You could either add a style of float:left to this element so it lines up next to the id or you could put the div in the card body instead- you may find it looks better there (especially on narrow width cards).