Prawn中的页眉和页脚PDF

时间:2022-10-12 21:13:47

I have read through all relevant posts on Prawn but found no mentioning (even in Prawn's own documentation) of headers and footers.

我已阅读了有关Prawn的所有相关帖子,但未发现(即使在Prawn自己的文档中)页眉和页脚。

However, I did see a demo on Prawnto's own website about headers and footers. I copied the entire source of that demo just to see if it works but an error of undefined method "header" is complained about. Am I to understand that Prawn took out header and footer recently in the gem or is there something else I need to do first to use header and footer?

但是,我确实在Prawnto自己的网站上看到了有关页眉和页脚的演示。我复制了该演示的整个源代码,只是为了查看它是否有效,但是抱怨未定义方法“header”的错误。我是否理解Prawn最近在宝石中取出了页眉和页脚或者我还需要先做其他什么才能使用页眉和页脚?

The demo page: http://cracklabs.com/prawnto/code/prawn_demos/source/text/flowing_text_with_header_and_footer

演示页面:http://cracklabs.com/prawnto/code/prawn_demos/source/text/flowing_text_with_header_and_footer

the part of code of concern:

关注代码的一部分:

Prawn::Document.generate("flow_with_headers_and_footers.pdf")  do

  header margin_box.top_left do 
      text "Here's My Fancy Header", :size => 25, :align => :center   
  end   

  text "hello world!"
end

And by header, just in case, I mean the snippets of words that appear usually at a corner of every page of a document. Like your account number in your bills pages.

通过标题,以防万一,我的意思是通常出现在文档每个页面一角的单词片段。就像账单页面中的账号一样。

thanks!

谢谢!

7 个解决方案

#1


19  

@GrantSayer thx for the example, but this will only let you show the current page number, not the total number of pages.

@GrantSayer thx为例,但这只会让你显示当前页码,而不是总页数。

You can also use the number_pages function for the footer:

您还可以使用页脚的number_pages函数:

Prawn::Document.generate("page_with_numbering.pdf") do
  text "Hai"
  start_new_page
  text "bai"
  start_new_page
  text "-- Hai again"
  number_pages "<page> in a total of <total>", [bounds.right - 50, 0]
end

However, in my case I also need to format/style and right align the page numbers to match company style guides. I used go_to_page(k) to create my own header and footer functions, which add the header and footer to each page after all the pages are created. This gives me both styling options and the total number of pages:

但是,在我的情况下,我还需要格式化/样式并右对齐页码以匹配公司样式指南。我使用go_to_page(k)创建自己的页眉和页脚功能,在创建所有页面后,将页眉和页脚添加到每个页面。这给了我样式选项和总页数:

Prawn::Document.generate("footer_example.pdf", :skip_page_creation => true) do
  10.times do
    start_new_page
    text "Some filler text for the page"
  end

  # footer
  page_count.times do |i|
    go_to_page(i+1)
    lazy_bounding_box([bounds.right-50, bounds.bottom + 25], :width => 50) {
      text "#{i+1} / #{page_count}"
    }.draw
  end
end

#2


32  

The sample you are refering to, from the prawnto plugin, is using an older version of prawn.

您从prawnto插件中引用的示例是使用较旧版本的prawn。

Since i also needed header and footer i looked a bit more into this. It seems that that version of prawn had header and footer methods, which were implemented using lazy bounding box. (found by checking the code on github)

由于我还需要页眉和页脚,我看起来更多。似乎那个版本的虾有头和页脚方法,这是使用惰性边界框实现的。 (通过检查github上的代码找到)

In the new prawn version you can do the same thing using repeaters.

在新的虾版本中,您可以使用中继器执行相同的操作。

Here is the full sample rewritten using the new version:

以下是使用新版本重写的完整示例:

require "#{File.dirname(__FILE__)}/../example_helper.rb"

Prawn::Document.generate("test.pdf")  do

   repeat :all do
    # header
    bounding_box [bounds.left, bounds.top], :width  => bounds.width do
        font "Helvetica"
        text "Here's My Fancy Header", :align => :center, :size => 25
        stroke_horizontal_rule
    end

    # footer
    bounding_box [bounds.left, bounds.bottom + 25], :width  => bounds.width do
        font "Helvetica"
        stroke_horizontal_rule
        move_down(5)
        text "And here's a sexy footer", :size => 16
    end
  end

  bounding_box([bounds.left, bounds.top - 50], :width  => bounds.width, :height => bounds.height - 100) do                 
   text "this is some flowing text " * 200    

   move_down(20)

   font "#{Prawn::BASEDIR}/data/fonts/DejaVuSans.ttf"
   table [["ὕαλον ϕαγεῖν",    "baaar",             "1" ],
          ["This is","a sample",          "2" ],
          ["Table",  "dont\ncha\nknow?",  "3" ],
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules\nwith an iron fist", "x" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],   
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],  
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ]],     

     :font_size          => 24, 
     :horizontal_padding => 10,
     :vertical_padding   => 3,
     :border_width       => 2,
     :position           => :center,
     :headers            => ["Column A","Column B","#"]

  end
end

you can check the documentation page of repeat for other options which allow you to exactly specify where you want the repeaters.

您可以查看repeat的文档页面,了解其他选项,以便您准确指定中继器的位置。

#3


14  

It's little bit different with latest version of Prawn you must passe an hash

与最新版本的Prawn有点不同,你必须使用哈希

Prawn::Document.generate("page_with_numbering.pdf") do
  text "Hai"
  start_new_page
  text "bai"
  start_new_page
  text "-- Hai again"
  number_pages "<page> in a total of <total>", { :start_count_at => 0, :page_filter => :all, :at => [bounds.right - 50, 0], :align => :right, :size => 14 }
end

#4


7  

If you want a footer that do not write stuff over your text, you have to create the bounding_box below the margin of the document using bounds.bottom.

如果您想要一个不在文本上写东西的页脚,则必须使用bounds.bottom在文档边缘下创建bounding_box。

require 'prawn'

file_name = 'hello.pdf'
random_table = (0..50).map{|i|[*('a'..'z')]} # generate a 2D array for example (~2 pages)

Prawn::Document::generate(file_name) do |pdf|
    pdf.table random_table
    pdf.page_count.times do |i|
        pdf.bounding_box([pdf.bounds.left, pdf.bounds.bottom], :width => pdf.bounds.width, :height => 30) {
        # for each page, count the page number and write it
        pdf.go_to_page i+1
             pdf.move_down 5 # move below the document margin
             pdf.text "#{i+1}/#{pdf.page_count}", :align => :center # write the page number and the total page count
        }
    end
end

It should look like that, you can see that the footer is outside the margin bottom :

看起来应该是这样,你可以看到页脚在边缘之外:

Prawn中的页眉和页脚PDF

Hope it help someone

希望它可以帮到某人

#5


3  

START EDIT

开始编辑

This works in prawn >= 0.12

这适用于虾> = 0.12

END EDIT

结束编辑

Here is my solution using repeat, canvas and cell. Essentially I'm drawing my bounding boxes at the absolute top and bottom of every page. I'm using cell to have better styling control over it. Hope this is going to be helpful to someone. ( I used slightly annoying colors to better illustrate how you can control styling of header and footer)

这是我使用repeat,canvas和cell的解决方案。基本上我是在每页的绝对顶部和底部绘制我的边界框。我正在使用单元格来更好地控制样式。希望这会对某人有所帮助。 (我使用稍微恼人的颜色来更好地说明如何控制页眉和页脚的样式)

 Prawn::Document.generate("headers_and_footers_with_background.pdf") do
  repeat :all do
    # header
    canvas do
      bounding_box([bounds.left, bounds.top], :width => bounds.width) do
        cell :content => 'Header',
             :background_color => 'EEEEEE',
             :width => bounds.width,
             :height => 50,
             :align => :center,
             :text_color => "001B76",
             :borders => [:bottom],
             :border_width => 2,
             :border_color => '00FF00',
             :padding => 12
      end
    end
    # footer
    canvas do
      bounding_box [bounds.left, bounds.bottom + 50], :width  => bounds.width do
        cell :content => 'Footer',
             :background_color => '333333',
             :width => bounds.width,
             :height => 50,
             :align => :center,
             :text_color => "FFFFFF",
             :borders => [:top],
             :border_width => 2,
             :border_color => 'FF0000',
             :padding => 12
      end
    end
  end
  # body
  bounding_box([bounds.left, bounds.top - 25], :width  => bounds.width, :height => bounds.height - 50) do
    100.times do
      text "Some filler text for the page"
    end
  end
end

#6


0  

The only way I've found to get a repeating item on a page is to use the Prawn::Document::LazyBoundingBox method. Basically this allows you to define a bounding box that is only rendered once you call it. So the usual pseudo-code steps are

我发现在页面上获取重复项的唯一方法是使用Prawn :: Document :: LazyBoundingBox方法。基本上,这允许您定义仅在调用它时呈现的边界框。所以通常的伪代码步骤是

1. Define lazy bounding box element assign to somevar
2. One each new page call the element.

The example from the source shows how

来自源的示例显示了如何

file = "lazy_bounding_boxes.pdf"
Prawn::Document.generate(file, :skip_page_creation => true) do
  point = [bounds.right-50, bounds.bottom + 25]
  page_counter = lazy_bounding_box(point, :width => 50) do
  text "Page: #{page_count}"
end 

10.times do
  start_new_page
  text "Some filler text for the page"  
  page_counter.draw
end

end

结束

This gives you a Page-count text output on each new page. What would be ideal is if this could be applied in the setup of a page template that is reused without the manual call to render the element. The combined with text flow it would give the traditional solution of headers and footers.

这为您提供了每个新页面上的Page-count文本输出。理想的是,如果这可以应用于页面模板的设置,而该模板在没有手动调用的情况下重复使用以呈现元素。结合文本流程,它将提供传统的页眉和页脚解决方案。

#7


0  

here's the problem when using the bounding_box for creating the custom footer contents... it is still rendering within the bounds of a margin.

这是使用bounding_box创建自定义页脚内容时的问题...它仍然在边距范围内呈现。

I was looking for something that will write the contents in the margin area together with number_pages.(because a footer usually is set in the bottom margin area)... and it seems that there were none.

我正在寻找能够在margin_pages中写入内容的东西。(因为页脚通常设置在底部边缘区域)......而且似乎没有。

so instead, I used text_box and place the coordinates outside my main bounding box like so:

所以相反,我使用text_box并将坐标放在我的主边界框之外,如下所示:

repeat :all do
      text_box "My custom footer", size: 7, align: :center, :at => [bounds.left, bounds.bottom], :height => 100, :width => bounds.width
end

take note that the repeat :all , will render this footer text to every page.

请注意,重复:all,会将此页脚文本呈现给每个页面。

#1


19  

@GrantSayer thx for the example, but this will only let you show the current page number, not the total number of pages.

@GrantSayer thx为例,但这只会让你显示当前页码,而不是总页数。

You can also use the number_pages function for the footer:

您还可以使用页脚的number_pages函数:

Prawn::Document.generate("page_with_numbering.pdf") do
  text "Hai"
  start_new_page
  text "bai"
  start_new_page
  text "-- Hai again"
  number_pages "<page> in a total of <total>", [bounds.right - 50, 0]
end

However, in my case I also need to format/style and right align the page numbers to match company style guides. I used go_to_page(k) to create my own header and footer functions, which add the header and footer to each page after all the pages are created. This gives me both styling options and the total number of pages:

但是,在我的情况下,我还需要格式化/样式并右对齐页码以匹配公司样式指南。我使用go_to_page(k)创建自己的页眉和页脚功能,在创建所有页面后,将页眉和页脚添加到每个页面。这给了我样式选项和总页数:

Prawn::Document.generate("footer_example.pdf", :skip_page_creation => true) do
  10.times do
    start_new_page
    text "Some filler text for the page"
  end

  # footer
  page_count.times do |i|
    go_to_page(i+1)
    lazy_bounding_box([bounds.right-50, bounds.bottom + 25], :width => 50) {
      text "#{i+1} / #{page_count}"
    }.draw
  end
end

#2


32  

The sample you are refering to, from the prawnto plugin, is using an older version of prawn.

您从prawnto插件中引用的示例是使用较旧版本的prawn。

Since i also needed header and footer i looked a bit more into this. It seems that that version of prawn had header and footer methods, which were implemented using lazy bounding box. (found by checking the code on github)

由于我还需要页眉和页脚,我看起来更多。似乎那个版本的虾有头和页脚方法,这是使用惰性边界框实现的。 (通过检查github上的代码找到)

In the new prawn version you can do the same thing using repeaters.

在新的虾版本中,您可以使用中继器执行相同的操作。

Here is the full sample rewritten using the new version:

以下是使用新版本重写的完整示例:

require "#{File.dirname(__FILE__)}/../example_helper.rb"

Prawn::Document.generate("test.pdf")  do

   repeat :all do
    # header
    bounding_box [bounds.left, bounds.top], :width  => bounds.width do
        font "Helvetica"
        text "Here's My Fancy Header", :align => :center, :size => 25
        stroke_horizontal_rule
    end

    # footer
    bounding_box [bounds.left, bounds.bottom + 25], :width  => bounds.width do
        font "Helvetica"
        stroke_horizontal_rule
        move_down(5)
        text "And here's a sexy footer", :size => 16
    end
  end

  bounding_box([bounds.left, bounds.top - 50], :width  => bounds.width, :height => bounds.height - 100) do                 
   text "this is some flowing text " * 200    

   move_down(20)

   font "#{Prawn::BASEDIR}/data/fonts/DejaVuSans.ttf"
   table [["ὕαλον ϕαγεῖν",    "baaar",             "1" ],
          ["This is","a sample",          "2" ],
          ["Table",  "dont\ncha\nknow?",  "3" ],
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules\nwith an iron fist", "x" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],   
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ],  
          [ "It",    "Rules",             "4" ],     
          [ "It",    "Rules",             "4" ]],     

     :font_size          => 24, 
     :horizontal_padding => 10,
     :vertical_padding   => 3,
     :border_width       => 2,
     :position           => :center,
     :headers            => ["Column A","Column B","#"]

  end
end

you can check the documentation page of repeat for other options which allow you to exactly specify where you want the repeaters.

您可以查看repeat的文档页面,了解其他选项,以便您准确指定中继器的位置。

#3


14  

It's little bit different with latest version of Prawn you must passe an hash

与最新版本的Prawn有点不同,你必须使用哈希

Prawn::Document.generate("page_with_numbering.pdf") do
  text "Hai"
  start_new_page
  text "bai"
  start_new_page
  text "-- Hai again"
  number_pages "<page> in a total of <total>", { :start_count_at => 0, :page_filter => :all, :at => [bounds.right - 50, 0], :align => :right, :size => 14 }
end

#4


7  

If you want a footer that do not write stuff over your text, you have to create the bounding_box below the margin of the document using bounds.bottom.

如果您想要一个不在文本上写东西的页脚,则必须使用bounds.bottom在文档边缘下创建bounding_box。

require 'prawn'

file_name = 'hello.pdf'
random_table = (0..50).map{|i|[*('a'..'z')]} # generate a 2D array for example (~2 pages)

Prawn::Document::generate(file_name) do |pdf|
    pdf.table random_table
    pdf.page_count.times do |i|
        pdf.bounding_box([pdf.bounds.left, pdf.bounds.bottom], :width => pdf.bounds.width, :height => 30) {
        # for each page, count the page number and write it
        pdf.go_to_page i+1
             pdf.move_down 5 # move below the document margin
             pdf.text "#{i+1}/#{pdf.page_count}", :align => :center # write the page number and the total page count
        }
    end
end

It should look like that, you can see that the footer is outside the margin bottom :

看起来应该是这样,你可以看到页脚在边缘之外:

Prawn中的页眉和页脚PDF

Hope it help someone

希望它可以帮到某人

#5


3  

START EDIT

开始编辑

This works in prawn >= 0.12

这适用于虾> = 0.12

END EDIT

结束编辑

Here is my solution using repeat, canvas and cell. Essentially I'm drawing my bounding boxes at the absolute top and bottom of every page. I'm using cell to have better styling control over it. Hope this is going to be helpful to someone. ( I used slightly annoying colors to better illustrate how you can control styling of header and footer)

这是我使用repeat,canvas和cell的解决方案。基本上我是在每页的绝对顶部和底部绘制我的边界框。我正在使用单元格来更好地控制样式。希望这会对某人有所帮助。 (我使用稍微恼人的颜色来更好地说明如何控制页眉和页脚的样式)

 Prawn::Document.generate("headers_and_footers_with_background.pdf") do
  repeat :all do
    # header
    canvas do
      bounding_box([bounds.left, bounds.top], :width => bounds.width) do
        cell :content => 'Header',
             :background_color => 'EEEEEE',
             :width => bounds.width,
             :height => 50,
             :align => :center,
             :text_color => "001B76",
             :borders => [:bottom],
             :border_width => 2,
             :border_color => '00FF00',
             :padding => 12
      end
    end
    # footer
    canvas do
      bounding_box [bounds.left, bounds.bottom + 50], :width  => bounds.width do
        cell :content => 'Footer',
             :background_color => '333333',
             :width => bounds.width,
             :height => 50,
             :align => :center,
             :text_color => "FFFFFF",
             :borders => [:top],
             :border_width => 2,
             :border_color => 'FF0000',
             :padding => 12
      end
    end
  end
  # body
  bounding_box([bounds.left, bounds.top - 25], :width  => bounds.width, :height => bounds.height - 50) do
    100.times do
      text "Some filler text for the page"
    end
  end
end

#6


0  

The only way I've found to get a repeating item on a page is to use the Prawn::Document::LazyBoundingBox method. Basically this allows you to define a bounding box that is only rendered once you call it. So the usual pseudo-code steps are

我发现在页面上获取重复项的唯一方法是使用Prawn :: Document :: LazyBoundingBox方法。基本上,这允许您定义仅在调用它时呈现的边界框。所以通常的伪代码步骤是

1. Define lazy bounding box element assign to somevar
2. One each new page call the element.

The example from the source shows how

来自源的示例显示了如何

file = "lazy_bounding_boxes.pdf"
Prawn::Document.generate(file, :skip_page_creation => true) do
  point = [bounds.right-50, bounds.bottom + 25]
  page_counter = lazy_bounding_box(point, :width => 50) do
  text "Page: #{page_count}"
end 

10.times do
  start_new_page
  text "Some filler text for the page"  
  page_counter.draw
end

end

结束

This gives you a Page-count text output on each new page. What would be ideal is if this could be applied in the setup of a page template that is reused without the manual call to render the element. The combined with text flow it would give the traditional solution of headers and footers.

这为您提供了每个新页面上的Page-count文本输出。理想的是,如果这可以应用于页面模板的设置,而该模板在没有手动调用的情况下重复使用以呈现元素。结合文本流程,它将提供传统的页眉和页脚解决方案。

#7


0  

here's the problem when using the bounding_box for creating the custom footer contents... it is still rendering within the bounds of a margin.

这是使用bounding_box创建自定义页脚内容时的问题...它仍然在边距范围内呈现。

I was looking for something that will write the contents in the margin area together with number_pages.(because a footer usually is set in the bottom margin area)... and it seems that there were none.

我正在寻找能够在margin_pages中写入内容的东西。(因为页脚通常设置在底部边缘区域)......而且似乎没有。

so instead, I used text_box and place the coordinates outside my main bounding box like so:

所以相反,我使用text_box并将坐标放在我的主边界框之外,如下所示:

repeat :all do
      text_box "My custom footer", size: 7, align: :center, :at => [bounds.left, bounds.bottom], :height => 100, :width => bounds.width
end

take note that the repeat :all , will render this footer text to every page.

请注意,重复:all,会将此页脚文本呈现给每个页面。