How to add internal PDF links inside a table using Prawn and Prawn table

Published 10 July 2015 under ruby, prawn, pdf, software

On a recent project we needed to generate a PDF using Prawn. The PDF has links from a list of contents into a table. The normal way (when not using a table) for adding internal links is to do the following:

Prawn::Document.generate("linked.pdf", page_layout: :landscape) do
  text '<link anchor="hello">Click me</link>', inline_format: true
  start_new_page
  add_dest "hello", dest_xyz(bounds.absolute_left, y)
  text "You've been linked here"
end

The important bits are using <link anchor="hello"> which sets up the link text and then we tell it where to link to using add_dest.

We generate our table using the following:

require 'prawn'
require 'prawn/table'

Prawn::Document.generate("linked.pdf", page_layout: :landscape) do
  text '<link anchor="hello30">Click me</link>', inline_format: true
  start_new_page

  data = (1..50).map do |i|
    ["hello#{i}", "some info about hello#{i}"]
  end

  table data
end

Here we link to hello30 which will be somewhere in the middle of the table. The trouble is that we generate our data before it's being laid out so it's not immediately obvious where to make our call to add_dest.

The answer is to use before_rendering_page:

require 'prawn'
require 'prawn/table'

Prawn::Document.generate("linked.pdf", page_layout: :landscape) do
  text '<link anchor="hello30">Click me</link>', inline_format: true
  start_new_page

  data = (1..50).map do |i|
    ["hello#{i}", "some info about hello#{i}"]
  end

  offset = 0
  table data do |t|
    t.before_rendering_page do |cells|
      cells.each do |cell|
        if cell.content == "hello30"
          add_dest(cell.content, dest_xyz(bounds.absolute_left, y + cell.y - offset))
        end
      end
      offset = cells.last.y
    end
  end
end

Comments

blog comments powered by Disqus