Class: TnPDF::Table

Inherits:
Object
  • Object
show all
Defined in:
lib/tn_pdf/table.rb,
lib/tn_pdf/table_column.rb

Overview

A representation Report‘s table. It’s an abstraction above a Prawn table that that ‘defaultizes’ a commonly used structure - a table that is a #collection of elements displayed as #rows, on which each of the #columns is a property of an object.

Through Column, it also provides many configurable column ‘types’, such as currency and float, to ease the pain of formatting the table on a consistent manner.

Above that, it also provides a very useful feature that Prawn misses: column spanning (although currently only on footers).

Table footers

Table footers are special rows that are often used to make a summary of the table data.

The main differences between a footer row and a ordinary row are:

Column spanning

Normal row’s cells can’t span across multiple columns, while a footer cell can.

Calculation

In a normal row, the cells’ values are automatically calculated using the provided method, while in a footer row the displayed value should be directly passed.

Scope

A footer row acts in the scope of the whole collection, while a normal row represents a single object.

Format

Footer rows can be formatted in a differente manner, through the use of the table_footer_* properties on Configuration

Defined Under Namespace

Classes: Column

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document) ⇒ Table

Returns a new instance of Table.



38
39
40
41
42
43
# File 'lib/tn_pdf/table.rb', line 38

def initialize(document)
  Configuration.table_properties_names.each do |property|
    send("#{property}=", Configuration["table_#{property}"])
  end
  @document = document
end

Instance Attribute Details

#collectionArray

The collection of objects to be represented by the table.

Returns:

  • (Array)

Raises:

  • (ArgumentError)

    If the passed value isn’t an Array



48
49
50
# File 'lib/tn_pdf/table.rb', line 48

def collection
  @collection
end

#columns(type = :all) ⇒ Array (readonly)

The columns already set on this table. Despite of being first provided as Arrays, the members of this collection are instances of Column.

Returns:

  • (Array)


61
62
63
# File 'lib/tn_pdf/table.rb', line 61

def columns
  @columns
end

Instance Method Details

#add_column(column) ⇒ Object

Adds a column to the table. The argument should be a Column, or an argument that TnPDF::Table::Column#initialize accepts.



74
75
76
77
78
79
80
81
# File 'lib/tn_pdf/table.rb', line 74

def add_column(column)
  unless column.kind_of? Column
    column = Column.new(column)
  end
  column.index = columns.count
  column.max_width = document_width
  columns << column
end

Adds a footer row to the table.

The argument to this method should be an Array (or a block that returns an Array) in which each member is a cell in the format:

[content, colspan, style]

where:

content

Is the content of the cell. May be a label, a sum of some values from the collection etc.

colspan

A number representing how many columns of the table this cell is going to span across. Be warned that the sum of all the colspans on a given footer row should always match the number of columns in the table, or an exception will be raised.

style

The formatting style of the cell. Refer to Column#style for details.

Examples:

# On a table that has 2 columns
table.add_footer [
  ["Total", 1, :text],
  [12345,   1, :number]
]
# On a table that has 3 columns
table.add_footer do |collection|
  calculation = collection.map(&:value).sum
  [
    ["Calculation", 1, :text],
    [calculation,   2, :number]
  ]
end


168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/tn_pdf/table.rb', line 168

def add_footer(row=nil, &block)
  unless block_given? or row.kind_of? Array
    raise ArgumentError, "No block or array was passed"
  end

  row = block.call(collection) if block_given?

  # [content, colspan, style]
  row = row.map do |field|
    field[2] ||= :text
    content = Column.format_value(field[0],
                                  Column.style_for(field[2]))

    OpenStruct.new(:content => content,
                   :colspan => field[1],
                   :style   => Column.prawn_style_for(field[2]) )
  end

  row.inject(0) do |first_column, field|
    final_column = first_column+field.colspan-1
    field.colspan_range = (first_column..final_column)
    final_column+1
  end

  total_colspan = row.map(&:colspan).inject(:+)
  unless total_colspan == columns.length
    raise ArgumentError,
      "Total colspan value '#{total_colspan}' differs from the "+
      "table's columns number '#{columns.length}'"
  end

  footer_rows << row
end

#column_widths(type = :all) ⇒ Object



208
209
210
211
# File 'lib/tn_pdf/table.rb', line 208

def column_widths(type = :all)
  selected_columns = columns(type)
  selected_columns.sort_by(&:index).map(&:width)
end

#remove_column(column) ⇒ Object



83
84
85
86
87
88
89
90
91
# File 'lib/tn_pdf/table.rb', line 83

def remove_column(column)
  if column.kind_of? Column
    columns.delete(column)
  elsif column.kind_of? Fixnum
    columns.delete_at(column)
  else
    raise ArgumentError, "Unrecognized argument '#{column.inspect}'"
  end
end

#render(max_height) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/tn_pdf/table.rb', line 108

def render(max_height)
  x_pos = x_pos_on(document, document_width)

  initialize_generated_widths
  total_width = self.column_widths.sum

  document.bounding_box([x_pos, document.cursor],
                        :width => total_width,
                        :height => max_height) do

    table_data  = [[header_table]]
    table_data += minitables
    table_data += footer_tables

    document.text *([text_before].flatten)
    document.font_size self.font_size

    document.table(table_data, :column_widths => [total_width],
                               :width => total_width) do |table|

      table.header = self.multipage_headers
      stylize_table(table)
    end

    document.text *([text_after].flatten)
  end
end

#reset_columnsObject



93
94
95
# File 'lib/tn_pdf/table.rb', line 93

def reset_columns
  @columns = []
end

#row_color(row_number) ⇒ Object



202
203
204
205
206
# File 'lib/tn_pdf/table.rb', line 202

def row_color(row_number)
  row_number % 2 == 0 ?
    self.even_row_color:
    self.odd_row_color
end

#rowsArray

The already computed rows of the table. Needs #columns and #collection to be already set to return something meaningful.

Returns:

  • (Array)

    An array containing the rows to be rendered.



100
101
102
103
104
105
106
# File 'lib/tn_pdf/table.rb', line 100

def rows
  collection.map do |object|
    columns.map do |column|
      column.value_for(object)
    end
  end
end