How to create a multipage PDF in Rails representing one table of data (including column headers on each new page)? I've looked at many examples with wicked-pdf, pdfkit, and prawn but haven't seen anything that specifically addresses the overflow into subsequent pages and the need to repeat the headers with each new page. Thanks for the help.
-
1what about creating a header function (like a partial or something).. then after n records writed place a page break... http://stackoverflow.com/questions/5806943/rails-wickedpdf-page-breaks , i did something like this once but in classic asp.... btw this is a dumb approach and use it as last resource.. – Orlando May 28 '12 at 19:14
-
This may not be a bad approach if the content of each row is predictably one line per record. – ob1 Jun 06 '12 at 17:28
-
yeah it worked right when i did it because i knew the exact size of each row (don't know if this is your case).. so.. after 40 records do a page break, if no more records, put the "footer" of the document.. .. it was simple but im sure there's a more efficient way to do it – Orlando Jun 06 '12 at 17:35
3 Answers
I use Prawn to generate my pdfs, and can get the effect you desire like this:
def render_photo_table(pdf)
ps = self.photos.map do |photo|
[photo.filename, photo.image_height, photo.image_width]
end
ps.insert(0, ['Filename', 'Height', 'Width'])
pdf.table(ps) do |table|
table.header = true
end
end
This yields a header (set in array position 0) at the top of each page.

- 1,503
- 10
- 10
Had trouble with this too, but found a fairly easy way(after much headaches) to do this.
Place a floated placemark div above the items so you can get starting coordinates (I call it ID item_top).
Then render the page with top level divs of data, with class 'unbreakable
'.
Also include a class to force a page break:
.page-breaker {
display: block;
clear: both;
page-break-after: always;
}
Then after rendering
<script>
// Very top of items
var current_top = $('#item_top').offset().top;
// Check distance from top of page to bottom of item
// If greater than page size put page break and headers before
// Reset top of page to top of item.
$('.unbreakable_section').each(function(index) {
var item_bottom = $(this).offset().top + $(this).outerHeight(true);
if ((item_bottom - current_top) > 1250) {
$(this).before("<div class='page-breaker'></div>");
$(this).before("Headings Div here");
current_top = $(this).offset().top - 48; // item - header height
}
});
</script>
This will measure the vertical space since the last page break and start a new page and place a header above it, if the space exceeds the page height. (1250 is approximate which was close enough for me - I have a footer on the page as well so height may vary depending on your setup).
Tested on a 100 page document works as expected.

- 2,387
- 1
- 25
- 31
We wrote our in-house jquery code for this.
If you have pages like:
<div class="mypage">
<div class="mypage_footer"></div>
</div>
And outside you have:
<div class="mybox">
<table><tbody><tr><td>omg</td></tr></tbody></table>
</div>
<div class="mybox">
<table><tbody><tr><td>lol</td></tr></tbody></table>
</div>
Assuming you have a fixed page height (preferably A4 size), you can use jquery to:
- Compute remaining space inside mypage by subtracting the $(element).height() of the page's children from the height of mypage
- While there is remaining space, pick a mybox from outside the page and place it inside the page
- If there is no more space, create a copy of the first page and repeat.

- 11,090
- 5
- 65
- 85
-
Interesting approach. Did you see any limit to the number of pages you could handle this way? Can you share the actual function? – ob1 Jun 04 '12 at 16:11
-
Yes, in fact after 50 or so pages, the wkhtmltopdf zoom parameter loses its accurracy and millimetric sliding starts to happen. I will ask if I can share the code. – nurettin Jun 05 '12 at 08:49
-