4

I am generating a document with data that flows onto each subsequent page, each page has a standard header. However, when I use repeat(:all) to put the header on each page, I find that on every page but the first page, the next content is not being moved down by the size of the header banner I have put on the page.

My code for generating the banner:

class SmartsoftPdf < Prawn::Document
  BOX_MARGIN = 30
  RHYTHM = 10
  INNER_MARGIN = 30

  # Colors
  #
  BLACK      = "000000"
  LIGHT_GRAY = "F2F2F2"
  GRAY       = "DDDDDD"
  DARK_GRAY  = "333333"
  BROWN      = "A4441C"
  ORANGE     = "F28157"
  LIGHT_GOLD = "FBFBBE"
  DARK_GOLD  = "EBE389"
  BLUE       = "08C"
  GREEN      = "00ff00"
  RED        = "ff0000"


  def show_header(text,date)
    header_box do
      image "#{Rails.root}/app/assets/images/smart_records_logo_h60.png", :height => 40
      draw_text text,
        :at => [80,25], :size => 12, :style => :bold, :color => BLUE
      draw_text "Date: #{ausDate(date)}", 
        :at => [bounds.right - 100,bounds.top - 15], :size => 10 if date
    end
  end

  def header_box(&block)
    bounding_box([-bounds.absolute_left, cursor + BOX_MARGIN + 8],
                 :width  => bounds.absolute_left + bounds.absolute_right,
                 :height => BOX_MARGIN*2) do

      fill_color LIGHT_GRAY
      fill_rectangle([bounds.left, bounds.top],
                      bounds.right,
                      bounds.top - bounds.bottom)
      fill_color BLACK
      move_down(RHYTHM)

      indent(BOX_MARGIN, &block)
    end

    stroke_color GRAY
    stroke_horizontal_line(-BOX_MARGIN, bounds.width + BOX_MARGIN, :at => cursor)
    stroke_color BLACK

    move_down(RHYTHM*4)
  end
end

Then within the pdf generation itself I do:

repeat(:all) do
  show_header("Custom Report",DateTime.now())
end

However, when I start putting content onto the pages, I expect when the content overflows onto the next page that the content will show up after the header. I'm finding that the header overlaps the content instead.

Here is an image which illustrates the problem: https://i.stack.imgur.com/zfbJ2.png

Am I building the header box incorrectly? Do I need to do something additional to make it so that the content which spills into the next page gets pushed down the appropriate amount?

Bramski
  • 179
  • 1
  • 10

1 Answers1

3

Okay. I have solved this myself. Most recent version of Prawn has a better way to handle this case. When you use repeat(:all) the page is reopened AFTER document creation and your content creation items are then added. This doesn't push the page down. The correct way to add this header to every page is to use the "canvas" method which allows you to operate out of the bounds of the page margin. Use canvas to draw a box at the top of the page, and set the top_margin of the page to push all content below the banner.

canvas do
      bounding_box([bounds.left,bounds.top],
                   :width  => bounds.absolute_left + bounds.absolute_right,
                   :height => BOX_MARGIN*2) do

        fill_color LIGHT_GRAY
        fill_rectangle([bounds.left, bounds.top],
                        bounds.right,
                        bounds.top - bounds.bottom)
        fill_color BLACK
        move_down(RHYTHM)

        indent(BOX_MARGIN, &block)
      end

      stroke_color GRAY
      stroke_horizontal_line(-BOX_MARGIN, bounds.width + BOX_MARGIN, :at => cursor)
      stroke_color BLACK
 end

at document creation...

 def initialize(options = {})
    super(:page_layout => :landscape,:top_margin => HEIGHT_OF_BANNER)
 end
Bramski
  • 179
  • 1
  • 10
  • 2
    For people who don't know what is HEIGHT_OF_BANNER, it's a constant defined by you(the height of your header). Not some magic number comes with prawn. It could be 300, 350, whatever you want. – yujingz Jan 08 '14 at 18:46