Adding Headers, Footers, and Page Numbers to HTML Page Converted to PDF iText 7

10,818

You want page headers and footers, but looking at your CSS, I don't see you defining page headers or footers anywhere (<thead> and <tfoot> are for tables, not for pages). You want to add "Page X of Y" to every page, but I don't see you define that content anywhere.

Please read Chapter 2 of the tutorial on converting HTML to PDF. In one of the examples, you'll see:

@page {
    @bottom-right {
        content: "Page " counter(page) " of " counter(pages);
    }
}

This defines a footer at the bottom-right of each page, with as content "Page X of Y" where X will be the current pages and Y the total number of pages.

Read more about the @page rule and you'll discover that you can also define an @bottom-left, @bottom-center, @top-left, and so on.

Also be aware of the fact that you use @media print which means that whatever is in-between those brackets will only be looked at by iText if you define the right media query. See Chapter 3 of the tutorial.

FINAL UPDATE:

I took the following example from the tutorial: C03E02_Print

public static void main(String[] args) throws IOException {
    File file = new File(TARGET);
    file.mkdirs();
    new Kmcnet().createPdf(BASEURI, SRC, DEST);
}

public void createPdf(String baseUri, String src, String dest) throws IOException { 
    ConverterProperties properties = new ConverterProperties();
    properties.setBaseUri(baseUri);
    MediaDeviceDescription mediaDeviceDescription = new MediaDeviceDescription(MediaType.PRINT);
    properties.setMediaDeviceDescription(mediaDeviceDescription);
    HtmlConverter.convertToPdf(new FileInputStream(src), new FileOutputStream(dest), properties);
}

I took the sxsw.html page, and I changed the sxsw_print.css like this:

@page {
    @top-left {
        content: "HEADER";
    }
    @top-center {
        content: "READ THE TUTORIAL";
    }
    @top-right {
        content: "kmcnet";
    }
    @bottom-left {
        content: "FOOTER";
    }
    @bottom-center {
        content: "Page " counter(page) " of " counter(pages);
    }
    @bottom-right {
        content: "The end";
    }
}

I ran the code and this was the result:

enter image description here

The OP, kmcnet, claims that there is no "Page X of Y" on the pages, but if you look closely, you can see "Page 1 of 2" and "Page 2 of 2" in the middle at the bottom of the pages on the screen shot. Furthermore, kmcnet claims that it's impossible to add customer names in the header or footer, but if you look at the screen shot, you clearly see "kmcnet" in the upper right corner of the pages.

Then I took the movies2.html file, and I changed the inline CSS like this:

<style>
@media print {
    @page {
        @top-left {
            content: "HEADER";
        }
        @top-center {
            content: "READ THE TUTORIAL";
        }
        @top-right {
            content: "kmcnet";
        }
        @bottom-left {
            content: "FOOTER";
        }
        @bottom-center {
            content: "Page " counter(page) " of " counter(pages);
        }
        @bottom-right {
            content: "The end";
        }
    }
}
</style>

I ran the C03E02_Print example on that HTML, and the result showed similar headers and footers:

enter image description here

The original question was:

What I want to accomplish next is to add headers and footers as well as Page x of y.

I think that my answer and the tutorial explained adequately how to do this. Unfortunately, the OP persists in saying that my answer doesn't work, nor what is written in the tutorial.

I will make the question as off-topic, more specifically as a problem that can't be reproduced:

enter image description here

Share:
10,818

Related videos on Youtube

kmcnet
Author by

kmcnet

Updated on June 04, 2022

Comments

  • kmcnet
    kmcnet about 2 years

    Hello everyone and thanks for your help in advance. I am learning iText 7 and am creating an application that pulls a webpage from a URL and converts it to PDF. I've got the very basic pieces working, i.e. grabbing the page, converting it to PDF, and writing it to disk. What I want to accomplish next is to add headers and footers as well as Page x of y. I've tried:

            @media print {
            @page {
                size: 8.5in 5.5in portrait;
                margin-left: 0.5cm;
                margin-right: 0.5cm;
                margin-bottom: .5cm;
                padding-bottom: 3.5cm;
                background: #FFF;
            }
    
            thead { display: table-header-group; }
            tfoot { display: table-footer-group; }
        }
    

    which seems to place the header and footer on each page, although the last page of the document has the footer placed after where the last element appears (not ideal). Since I'm grabbing a page, I'm not really sure how to add the page number and count. So my question is how to tackle this, i.e. should I just stick with the media query, or should I generate the PDF, the loop through using some type of handler to insert the headers and footers (or should I do this upon creation of the initial document). I now there are some tutorials on paging, but not combined with converting a webpage, so I am confused (maybe needlessly) about how to proceed. Any help would be appreciated.

    I tried:

            @media print {
            @page {
                size: 8.5in 5.5in portrait;
                margin-left: 0.5cm;
                margin-right: 0.5cm;
                margin-bottom: .5cm;
                padding-bottom: 3.5cm;
                background: #FFF;
    
            @bottom-right {
            content: "Page " counter(page) " of " counter(pages);
            }   
            }
    
            thead { display: table-header-group; }
            tfoot { display: table-footer-group; }
        }
    

    but the page number does not display, either on the HTML or converted PDF. I needed to use:thead { display: table-header-group; } tfoot { display: table-footer-group; } to force the header and footer to display on each page. Obviously I'm not handling this correctly, but don't know what to try next.

    `

    enter code here

    • Bruno Lowagie
      Bruno Lowagie about 6 years
      I have updated my answer. I strongly suggest that you read the tutorial. The @page part of your CSS will only be looked at by iText if you define a new MediaDeviceDescription(MediaType.PRINT)! Did you do that?
    • Juke
      Juke almost 5 years
      @BrunoLowagie in order to make at-page work should we define this new MediaDeviceDescription(MediaType.PRINT) after we convert as HTML to PDF?
    • Juke
      Juke almost 5 years
      @BrunoLowagie I am using this css ol.anchorLink a::after { content: leader('.') target-counter(attr(href), page); } to display the pagenumbers right after the link in the Table of contents do we have any thing to be configured in mediaDeviceDescription ?
  • kmcnet
    kmcnet about 6 years
    The <thead> and <tfoot> were used to force the header and footer to display on each page. I nested
  • Bruno Lowagie
    Bruno Lowagie about 6 years
    Er... OK but the t in <thead> and <tfoot> refers to a <table>, doesn't it? See w3schools.com/tags/tag_thead.asp Why would you use table-related tags to add headers and footers to a page?
  • Bruno Lowagie
    Bruno Lowagie about 6 years
    @kmcnet I have the impression that you consider reading the tutorial a waste of time. Because of that you waste your time and mine. Please read the tutorial. You'll save time!
  • kmcnet
    kmcnet about 6 years
    Sorry you feel that way. I did read the tutorial. However, I am also trying to add header and footer text to each page. I have done prior research: forums.asp.net/t/2139996.aspx?Printable+Page and this "fix" is found in many articles. So you're assumption I didn't read the tutorial wastes both our time as well. I obviously don't understand how to get this working.
  • Bruno Lowagie
    Bruno Lowagie about 6 years
    The page you refer to has the @bottom-left, @bottom-center, @top-left,... stuff I explained. However, you're overlooking the difference between the @media screen and @media print difference. Please don't use a "fix" you don't understand. If you find a "fix", examine it and learn about the consequences and effects. Now that you know that, it should be easy to solve your problem.
  • kmcnet
    kmcnet about 6 years
    Thanks for the response. I appreciate the help and am really trying to understand. I removed all of the previous css and replaced it with : <style type="text/css"> @@page { @@bottom-right { content: "Page " counter(page) " of " counter(pages); } } </style>
  • kmcnet
    kmcnet about 6 years
    Thanks for the response. I appreciate the help and am really trying to understand. I removed all of the previous css and replaced it with : <style type="text/css"> @@page { @@bottom-right { content: "Page " counter(page) " of " counter(pages); } } </style> which worked when creating the PDF from iText, but does not display either on the page or when the page is printed from the browser. In order to not use a fix I don't understand, why? I understand why it doesn't display on the page, but why not in the print?
  • Bruno Lowagie
    Bruno Lowagie about 6 years
    Please read the tutorial more closely. By default, iText will use the default CSS. That's the CSS when your remove the @media print (and that's why the headers/footers work in that case). Sometimes you want to keep the @media print because you want the headers/footers also to work when you print the HTML page. In that case, you need to create a new MediaDeviceDescription(MediaType.PRINT); and add that as a media query for the ConverterProperties. It's all explained in the tutorial. I shouldn't have to repeat all of this. It's how media queries work in general.
  • kmcnet
    kmcnet about 6 years
    Bruno. First of all, thanks for the help. I don't mean to frustrate you. I think I understand the @page rule and it works fine with my iText implementation. However, if you read my post carefully, I need to dynamically add a header and footer to each page in addition to the page number (for example the customer name and address in the footer). This was the reason for the <thead> and <tfoot> hack in the first place. I'm not seeing anything in the tutorials addressing this. Am I missing it?
  • Bruno Lowagie
    Bruno Lowagie about 6 years
    I give up. The tutorial has all the info you need. For simple things: use the @page rule correctly. For difficult things that aren't even possible in HTML (such as a header/footer that isn't the same for each page, but that shows different customer names, use a custom IEventHandler as described in the section Adding a background and a custom header or footer in chapter 4 of the tutorial.
  • Bruno Lowagie
    Bruno Lowagie about 6 years
    The fact that no one else even tries to help you should be sufficient reason for you to assume that you are being unreasonable. There's an expression: "you can take the horse to the water, but you can't make it drink." That expression applies to you: you have received all the help you required to solve your problem. If you don't accept that help, but on the contrary "talk back" to the one person willing to help you, your problem won't be solved.
  • kmcnet
    kmcnet about 6 years
    Let me rephrase my pervious comment. I am aware of the article developers.itextpdf.com/content/itext-7-examples/… regarding headers and footers, but that is not using css or pages created from HTML. So I would like to generate the PDF from a webpage, but add headers and footers. Perhaps I'm trying to combine too many things.
  • Bruno Lowagie
    Bruno Lowagie about 6 years
    You have never made it clear what you expect from those headers and footers. Show us something that works when you print an HTML page, but that doesn't work if you convert that HTML to PDF using the MediaType.PRINT converter property.
  • kmcnet
    kmcnet about 6 years
    Bruno. I have been nothing but respectful in my posts and take issue with your "talk back" comment as if I am some recalcitrant child. The fact I continue to post should be ample indication to YOU I am not following your documentation. While you feel I am wasting your time, you are also wasting mine. Hackneyed adages about horses serves no purpose to this discussion and leads me to consider references to ancestrally related equine derivatives that are likely applicable to you. You made this an unnecessary personal attack, not me. I will only post more, if you actually want to help,
  • Bruno Lowagie
    Bruno Lowagie about 6 years
    Feel free to down-vote my answer if you're not happy. I down-voted your question, and I cast a vote to close it because you're reporting a problem that can't be reproduced. I've updated my answer with two working examples, taken from the tutorial. I have just compiled and executed those example, and I testify that the screen shots are genuine. Maybe you don't see any headers, footers, or Page X of Y, but I do, and I'm pretty sure that other Stack Overflow readers also do.
  • kmcnet
    kmcnet about 6 years
    Bruno. As is typical through this post, you have spent more time pointing to your documentation rather than actually reading and answering the question. You are oblivious to the questions I'm asking. I have posted several times the need for the header and footer to be created dynamically, not statically as in your example. Clearly, I am trying to accomplish too much with HTML, which was part of my initial question. I'll look at the IEventHandler, but I'm confused/concerned as how that will work with rendering a webpage. I expect no help here, I will post if I get it working,
  • Bruno Lowagie
    Bruno Lowagie about 6 years
    Regarding the header and footer that need to be created dynamically: what do you mean by that? You never explained what that means, did you? Please study what w3.org says about the page rule and you'll discover that Example 22 on that page is the closest you get to dynamic content. If, for instance, you want to have the customer name change in the header of a printed HTML page, then your question was phrased incorrectly, because that's not an iText question at all. Please don't blame people for not understanding questions that aren't phrased correctly.
  • kmcnet
    kmcnet about 6 years
    I think I have been very clear, but will restate the requirements again with more specificity. I am working with dynamically created (MVC) pages that, when printed, will encompass between 5 to 15 letter size pages. The HTML consists of a variable assortment of html tables, list items, and paragraphs. Each page is associated with a specific customer, so the printed document should have the customer name, address, etc. on each printed page along with a page x of y. So, the pdf will differ from the webpage in that it will have a header on each printed page along with a page number.