Prawn中的页眉和页脚PDF

时间:2010-04-22 22:41:12

标签: ruby-on-rails prawn prawnto

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

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

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

关注代码的一部分:

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

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

谢谢!

7 个答案:

答案 0 :(得分:33)

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

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

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

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

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

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

答案 1 :(得分:21)

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

您还可以使用页脚的 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

但是,在我的情况下,我还需要格式化/样式并右对齐页码以匹配公司样式指南。我使用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 :(得分:15)

与最新版本的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

答案 3 :(得分:9)

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

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

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

example result

希望有人帮助

答案 4 :(得分:4)

START EDIT

这适用于prawn&gt; = 0.12

结束编辑

这是我使用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

答案 5 :(得分:0)

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

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

来源的示例显示了如何

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

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

答案 6 :(得分:0)

这是使用 org.apache.kafka.connect.errors.DataException: StreamExample_1 at io.confluent.connect.avro.AvroConverter.toConnectData(AvroConverter.java:96) at org.apache.kafka.connect.runtime.WorkerSinkTask.convertMessages(WorkerSinkTask.java:454) at org.apache.kafka.connect.runtime.WorkerSinkTask.poll(WorkerSinkTask.java:287) at org.apache.kafka.connect.runtime.WorkerSinkTask.iteration(WorkerSinkTask.java:198) at org.apache.kafka.connect.runtime.WorkerSinkTask.execute(WorkerSinkTask.java:166) at org.apache.kafka.connect.runtime.WorkerTask.doRun(WorkerTask.java:170) at org.apache.kafka.connect.runtime.WorkerTask.run(WorkerTask.java:214) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: org.apache.kafka.common.errors.SerializationException: Error deserializing Avro message for id 101 Caused by: java.net.ConnectException: Connection refused (Connection refused) at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at java.net.Socket.connect(Socket.java:538) at sun.net.NetworkClient.doConnect(NetworkClient.java:180) at sun.net.www.http.HttpClient.openServer(HttpClient.java:463) at sun.net.www.http.HttpClient.openServer(HttpClient.java:558) at sun.net.www.http.HttpClient.<init>(HttpClient.java:242) at sun.net.www.http.HttpClient.New(HttpClient.java:339) at sun.net.www.http.HttpClient.New(HttpClient.java:357) at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1220) at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1156) at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1050) at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:984) at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1564) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) at io.confluent.kafka.schemaregistry.client.rest.RestService.sendHttpRequest(RestService.java:174) at io.confluent.kafka.schemaregistry.client.rest.RestService.httpRequest(RestService.java:218) at io.confluent.kafka.schemaregistry.client.rest.RestService.getId(RestService.java:394) at io.confluent.kafka.schemaregistry.client.rest.RestService.getId(RestService.java:387) at io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient.getSchemaByIdFromRegistry(CachedSchemaRegistryClient.java:65) at io.confluent.kafka.schemaregistry.client.CachedSchemaRegistryClient.getBySubjectAndId(CachedSchemaRegistryClient.java:138) at io.confluent.kafka.serializers.AbstractKafkaAvroDeserializer.deserialize(AbstractKafkaAvroDeserializer.java:122) at io.confluent.kafka.serializers.AbstractKafkaAvroDeserializer.deserializeWithSchemaAndVersion(AbstractKafkaAvroDeserializer.java:194) at io.confluent.connect.avro.AvroConverter$Deserializer.deserialize(AvroConverter.java:121) at io.confluent.connect.avro.AvroConverter.toConnectData(AvroConverter.java:84) at org.apache.kafka.connect.runtime.WorkerSinkTask.convertMessages(WorkerSinkTask.java:454) at org.apache.kafka.connect.runtime.WorkerSinkTask.poll(WorkerSinkTask.java:287) at org.apache.kafka.connect.runtime.WorkerSinkTask.iteration(WorkerSinkTask.java:198) at org.apache.kafka.connect.runtime.WorkerSinkTask.execute(WorkerSinkTask.java:166) at org.apache.kafka.connect.runtime.WorkerTask.doRun(WorkerTask.java:170) at org.apache.kafka.connect.runtime.WorkerTask.run(WorkerTask.java:214) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) [2018-03-12 08:59:25,070] ERROR WorkerSinkTask{id=hdfs-sink-0} Task is being killed and will not recover until manually restarted (org.apache.kafka.connect.runtime.WorkerTask:173) [2018-03-12 08:59:25,070] INFO Shutting down Hive executor service. (io.confluent.connect.hdfs.DataWriter:471) [2018-03-12 08:59:25,070] INFO Awaiting termination. (io.confluent.connect.hdfs.DataWriter:476) 创建自定义页脚内容时的问题...它仍然在边距范围内呈现。

我正在寻找能够将内容写在边距区域bounding_box一起的内容。(因为页脚通常设置在底部边距区域内)...并且它似乎没有。

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

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 会将此页脚文本呈现给每个页面。