Class: PDF::Wrapper::Table
- Inherits:
-
Object
- Object
- PDF::Wrapper::Table
- Defined in:
- lib/pdf/wrapper/table.rb
Overview
This class is used to hold all the data and options for a table that will be added to a PDF::Wrapper document. Tables are a collection of cells, each one individually rendered to the document in a location that makes it appear to be a table.
To begin working with a table, pass in a 2d array of data to display, along with optional headings, then pass the object to Wrapper#table
table = Table.new do |t|
t.headers = ["Words", "Numbers"]
t.data = [['one', 1],
['two', 2],
['three',3]]
end
pdf.table(table)
For all but the most basic tables, you will probably want to tweak at least some of the options for some of the cells. The options available are the same as those that are valid for the Wrapper#cell method, including things like font, font size, color and alignment.
Options can be specified at the table, column, row and cell level. When it comes time to render each cell, the options are merged together so that cell options override row ones, row ones override column ones and column ones override table wide ones.
By default, no options are defined at all, and the document defaults will be used.
For example:
table = Table.new(:font_size => 10) do |t|
t.headers = ["Words", "Numbers"]
t.data = [['one', 1],
['two', 2],
['three',3]]
t. 0, :color => :green
t. 2, :color => :red
t. 0, :color => :blue
t. 2, 2, :font_size => 18
t.manual_column_width 2, 40
end
pdf.table(table)
Displaying Headings
By default, the column headings will be displayed at the top of the table, and at the start of each new page the table wraps on to. Use the show_headers= option to change this behaviour. Valid values are nil for never, :once for just the at the top of the table, and :page for the default.
Complex Cells
By default, any cell content described in the data array is converted to a string and wrapped in a TextCell object. If you need to, it is possible to define your cells as cell-like objects manually to get more control.
The following two calls are equivilant:
data = [[1,2]]
pdf.table(data)
data = [[PDF::Wrapper::TextCell.new(2),PDF::Wrapper::TextCell.new(2)]]
pdf.table(data)
An alternative to a text-only cell is a cell with text and an image. These cells must be initialised with a filename and cell dimensions (width and height) as calculating automatic dimensions is difficult.
data = [
["James", PDF::Wrapper::TextImageCell.new("Healy","photo-jim.jpg",100,100)],
["Jess", PDF::Wrapper::TextImageCell.new("Healy","photo-jess.jpg",100,100)],
]
pdf.table(data)
If TextImageCell doesn’t meet your needs, you are free to define your own cell-like object and use that.
Instance Attribute Summary collapse
-
#cells ⇒ Object
readonly
Returns the value of attribute cells.
-
#show_headers ⇒ Object
Returns the value of attribute show_headers.
-
#width ⇒ Object
Returns the value of attribute width.
-
#wrapper ⇒ Object
readonly
Returns the value of attribute wrapper.
Instance Method Summary collapse
-
#cell(col_idx, row_idx) ⇒ Object
access a particular cell at location x, y.
-
#cell_options(col_idx, row_idx, opts = nil) ⇒ Object
set or retrieve options that apply to a single cell For a list of valid options, see Wrapper#cell.
-
#col_count ⇒ Object
Returns the number of columns in the table.
-
#col_options(spec, opts) ⇒ Object
set options that apply to 1 or more columns For a list of valid options, see Wrapper#cell.
-
#data=(d) ⇒ Object
Set the table data.
- #draw(wrapper, tablex, tabley) ⇒ Object
-
#each_cell(&block) ⇒ Object
iterate over each cell in the table.
-
#headers(h = nil, opts = {}) ⇒ Object
Retrieve or set the table’s optional column headers.
-
#initialize(opts = {}) {|_self| ... } ⇒ Table
constructor
A new instance of Table.
-
#manual_col_width(spec, width) ⇒ Object
Manually set the width for 1 or more columns.
-
#row_options(spec, opts) ⇒ Object
set options that apply to 1 or more rows For a list of valid options, see Wrapper#cell.
Constructor Details
#initialize(opts = {}) {|_self| ... } ⇒ Table
Returns a new instance of Table.
123 124 125 126 127 128 129 130 131 132 |
# File 'lib/pdf/wrapper/table.rb', line 123 def initialize(opts = {}) # default table options @table_options = opts @manual_col_widths = {} @show_headers = :page yield self if block_given? self end |
Instance Attribute Details
#cells ⇒ Object (readonly)
Returns the value of attribute cells.
120 121 122 |
# File 'lib/pdf/wrapper/table.rb', line 120 def cells @cells end |
#show_headers ⇒ Object
Returns the value of attribute show_headers.
121 122 123 |
# File 'lib/pdf/wrapper/table.rb', line 121 def show_headers @show_headers end |
#width ⇒ Object
Returns the value of attribute width.
121 122 123 |
# File 'lib/pdf/wrapper/table.rb', line 121 def width @width end |
#wrapper ⇒ Object (readonly)
Returns the value of attribute wrapper.
120 121 122 |
# File 'lib/pdf/wrapper/table.rb', line 120 def wrapper @wrapper end |
Instance Method Details
#cell(col_idx, row_idx) ⇒ Object
access a particular cell at location x, y
243 244 245 |
# File 'lib/pdf/wrapper/table.rb', line 243 def cell(col_idx, row_idx) @cells[row_idx][col_idx] end |
#cell_options(col_idx, row_idx, opts = nil) ⇒ Object
set or retrieve options that apply to a single cell For a list of valid options, see Wrapper#cell.
249 250 251 252 253 |
# File 'lib/pdf/wrapper/table.rb', line 249 def (col_idx, row_idx, opts = nil) raise ArgumentError, "#{col_idx},#{row_idx} is not a valid cell reference" unless @cells[row_idx] && @cells[row_idx][col_idx] @cells[row_idx][col_idx]. = @cells[row_idx][col_idx]..merge(opts) if opts @cells[row_idx][col_idx]. end |
#col_count ⇒ Object
Returns the number of columns in the table
313 314 315 |
# File 'lib/pdf/wrapper/table.rb', line 313 def col_count @cells.first.size.to_f end |
#col_options(spec, opts) ⇒ Object
set options that apply to 1 or more columns For a list of valid options, see Wrapper#cell.
spec
-
Which columns to add the options to. :odd, :even, a range, an Array of numbers or a number
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/pdf/wrapper/table.rb', line 258 def (spec, opts) each_column do |col_idx| if (spec == :even && (col_idx % 2) == 0) || (spec == :odd && (col_idx % 2) == 1) || (spec.class == Range && spec.include?(col_idx)) || (spec.class == Array && spec.include?(col_idx)) || (spec.respond_to?(:to_i) && spec.to_i == col_idx) cells_in_col(col_idx).each do |cell| cell..merge!(opts) end end end self end |
#data=(d) ⇒ Object
Set the table data.
The single argument should be a 2d array like:
[[ "one", "two"],
[ "one", "two"]]
The cells in the array can be any object with to_s() defined, or a Cell-like object (such as a TextCell or TextImageCell).
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/pdf/wrapper/table.rb', line 144 def data=(d) row_sizes = d.map { |row| row.size }.compact.uniq raise ArgumentError, "" if row_sizes.size > 1 @cells = d.collect do |row| row.collect do |data| if data.kind_of?(Wrapper::TextCell) || data.kind_of?(Wrapper::TextImageCell) data else Wrapper::TextCell.new(data.to_s) end end end each_cell { |cell| cell..merge!(@table_options)} @cells end |
#draw(wrapper, tablex, tabley) ⇒ Object
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/pdf/wrapper/table.rb', line 199 def draw(wrapper, tablex, tabley) @wrapper = wrapper calculate_dimensions # move to the start of our table (the top left) wrapper.move_to(tablex, tabley) # draw the header cells draw_table_headers if self.headers && (self.show_headers == :page || self.show_headers == :once) x, y = wrapper.current_point # loop over each row in the table self.cells.each_with_index do |row, row_idx| # calc the height of the current row h = row.first.height if y + h > wrapper.absolute_bottom_margin wrapper.start_new_page y = wrapper.margin_top # draw the header cells draw_table_headers if self.headers && (self.show_headers == :page) x, y = wrapper.current_point end # loop over each column in the current row and paint it row.each_with_index do |cell, col_idx| cell.draw(wrapper, x, y) x += cell.width wrapper.move_to(x, y) end # move to the start of the next row y += h x = tablex wrapper.move_to(x, y) end end |
#each_cell(&block) ⇒ Object
iterate over each cell in the table. Yields a cell object.
319 320 321 322 323 324 325 |
# File 'lib/pdf/wrapper/table.rb', line 319 def each_cell(&block) each_row do |row_idx| cells_in_row(row_idx).each do |cell| yield cell end end end |
#headers(h = nil, opts = {}) ⇒ Object
Retrieve or set the table’s optional column headers.
With no arguments, the currents headers will be returned
t.headers
=> ["col one", "col two"]
The first argument is an array of text to use as column headers
t.headers ["col one", "col two]
The optional second argument sets the cell options for the header cells. See PDF::Wrapper#cell for a list of possible options.
t.headers ["col one", "col two], :color => :block, :fill_color => :black
If the options hash is left unspecified, the default table options will be used.
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/pdf/wrapper/table.rb', line 180 def headers(h = nil, opts = {}) return @headers if h.nil? if @cells && @cells.first.size != h.size raise ArgumentError, "header column count does not match data column count" end @headers = h.collect do |data| if data.kind_of?(Wrapper::TextCell) || data.kind_of?(Wrapper::TextImageCell) data else Wrapper::TextCell.new(data.to_s) end end @headers.each { |cell| cell..merge!(@table_options)} @headers.each { |cell| cell..merge!(opts)} @headers end |
#manual_col_width(spec, width) ⇒ Object
Manually set the width for 1 or more columns
spec
-
Which columns to set the width for. :odd, :even, a range, an Array of numbers or a number
278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/pdf/wrapper/table.rb', line 278 def manual_col_width(spec, width) width = width.to_f each_column do |col_idx| if (spec == :even && (col_idx % 2) == 0) || (spec == :odd && (col_idx % 2) == 1) || (spec.class == Range && spec.include?(col_idx)) || (spec.class == Array && spec.include?(col_idx)) || (spec.respond_to?(:to_i) && spec.to_i == col_idx) @manual_col_widths[col_idx] = width end end self end |
#row_options(spec, opts) ⇒ Object
set options that apply to 1 or more rows For a list of valid options, see Wrapper#cell.
spec
-
Which columns to add the options to. :odd, :even, a range, an Array of numbers or a number
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
# File 'lib/pdf/wrapper/table.rb', line 296 def (spec, opts) each_row do |row_idx| if (spec == :even && (row_idx % 2) == 0) || (spec == :odd && (row_idx % 2) == 1) || (spec.class == Range && spec.include?(row_idx)) || (spec.class == Array && spec.include?(row_idx)) || (spec.respond_to?(:to_i) && spec.to_i == row_idx) cells_in_row(row_idx).each do |cell| cell..merge!(opts) end end end self end |