diff --git a/lib/prawn/table.rb b/lib/prawn/table.rb index 718fe698..f4511e0a 100644 --- a/lib/prawn/table.rb +++ b/lib/prawn/table.rb @@ -69,6 +69,10 @@ module Errors # numbering (for styling and other row-specific options) always indexes # based on your data array. Whether or not you have a header, row(n) always # refers to the nth element (starting from 0) of the +data+ array. + # +headers+:: + # If set to a multidimensional array of data, the defined header will be + # repeated on every page. + # +header+ must also be set to +true+ for this to function. # +column_widths+:: # Sets widths for individual columns. Manually setting widths can give # better results than letting Prawn guess at them, as Prawn's algorithm @@ -142,10 +146,15 @@ def initialize(data, document, options={}, &block) @pdf = document @cells = make_cells(data, table_opts.delete(:cell_style) || {}) @header = false + @headers = nil table_opts.each do |k, v| send("#{k}=", v) if respond_to?("#{k}=") end + unless @headers.nil? + @headers = make_cells(@headers, table_opts.delete(:cell_style) || {}) + end + if block block.arity < 1 ? instance_eval(&block) : block[self] end @@ -229,6 +238,12 @@ def height # attr_writer :header + # If set to a valid multidimensional array of data the data specified here + # will be used on each page as the header. +header+ must be set to +true+ + # for this to function. + # + attr_accessor :headers + # Accepts an Array of alternating row colors to stripe the table. # attr_writer :row_colors @@ -506,7 +521,11 @@ def fits_on_page?(needed_height, use_reference_bounds = false) def header_rows header_rows = Cells.new number_of_header_rows.times do |r| - row(r).each { |cell| header_rows[cell.row, cell.column] = cell.dup } + if @headers.nil? + row(r).each { |cell| header_rows[cell.row, cell.column] = cell.dup } + else + headers.row(r).each { |cell| header_rows[cell.row, cell.column] = cell.dup } + end end header_rows end @@ -656,6 +675,7 @@ def natural_width def set_column_widths column_widths.each_with_index do |w, col_num| column(col_num).width = w + headers.column(col_num).width = w if !headers.nil? && !headers.column(col_num).nil? end end @@ -663,7 +683,10 @@ def set_column_widths # row is the same height. # def set_row_heights - row_heights.each_with_index { |h, row_num| row(row_num).height = h } + row_heights.each_with_index do |h, row_num| + row(row_num).height = h + headers.row(row_num).height = h if !headers.nil? && !headers.row(row_num).nil? + end end # Set each cell's position based on the widths and heights of cells @@ -673,13 +696,19 @@ def position_cells # Calculate x- and y-positions as running sums of widths / heights. x_positions = column_widths.inject([0]) { |ary, x| ary << (ary.last + x); ary }[0..-2] - x_positions.each_with_index { |x, i| column(i).x = x } + x_positions.each_with_index do |x, i| + column(i).x = x + headers.column(i).x = x unless headers.nil? || headers.column(i).nil? + end # y-positions assume an infinitely long canvas starting at zero -- this # is corrected for in Table#draw, and page breaks are properly inserted. y_positions = row_heights.inject([0]) { |ary, y| ary << (ary.last - y); ary}[0..-2] - y_positions.each_with_index { |y, i| row(i).y = y } + y_positions.each_with_index do |y, i| + row(i).y = y + headers.row(i).y = y unless headers.nil? || headers.row(i).nil? + end end # Sets up a bounding box to position the table according to the specified diff --git a/prawn-table.gemspec b/prawn-table.gemspec index 31b20573..f0aaffd8 100644 --- a/prawn-table.gemspec +++ b/prawn-table.gemspec @@ -28,6 +28,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency('prawn-dev', '~> 0.3.0') spec.add_development_dependency('prawn-manual_builder', ">= 0.2.0") spec.add_development_dependency('pdf-reader', '~>1.2') + spec.add_development_dependency('matrix') spec.homepage = "https://github.com/prawnpdf/prawn-table" spec.description = < true, :headers => repeating_headers) + output = PDF::Inspector::Text.analyze(@pdf.render) + expect(@pdf.page_count).to eq 2 + expect(output.strings).to eq first_page_headers.flatten + data.flatten[0..-3] + repeating_headers.flatten + + data.flatten[-2..-1] + end + it "draws headers at the correct position" do data = [["header"]] + [["foo"]] * 40