From 431bf2520c64ab5e948de2dd098d5dcbe6291510 Mon Sep 17 00:00:00 2001 From: Ben Ketron Date: Thu, 9 Jan 2020 12:22:21 -0700 Subject: [PATCH] Adds header_rows helper to the table model This adds support for the table row property http://officeopenxml.com/WPtableRowProperties.php header_rows takes a required integer parameter specifying the number of rows from the top of the table that should be considered header rows. The render function adds the `` table row property to each of these rows causing them to be repeated in the table after each page break. Usage: ``` docx.table [[...]] do header_rows 1 end ``` --- README.md | 11 ++++++++++- lib/caracal/core/models/table_model.rb | 9 ++++++--- lib/caracal/renderers/document_renderer.rb | 9 ++++++++- spec/lib/caracal/core/tables_spec.rb | 7 +++++++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 56f19204..32852b74 100644 --- a/README.md +++ b/README.md @@ -632,7 +632,7 @@ the simplest solution to both problems.* Release v1.4.0 deprecated the behaviour of automatically adding an empty paragraph tag after every table. If you are upgrading from an older version of the library, you will need to control such spacing in your own code. ``` -Tables can be added using the `table` method. The method accepts several optional paramters to control the layout and style of the table cells. +Tables can be added using the `table` method. The method accepts several optional parameters to control the layout and style of the table cells. The `table` command accepts data in the form of a two-dimensional arrays. This corresponds to rows and column cells within those rows. Each array item can be a string, a Hash of options, a Proc (which will be passed as a block), or a `TableCellModel`. The command will normalize all array contents into a two-dimensional array of `TableCellModel` instances. @@ -683,6 +683,15 @@ end *Note: content of cells 21 and 24 will disappear* +Table rows can be marked as header rows using the `header_rows` method which takes a number indicating how many rows from the top of the table should be marked as such. This has the effect of repeating these rows after each page break. + +```ruby +docx.table [['Header 1', 'Header 2'],['Cell 1', 'Cell 2']] do + header_rows 1 +end +``` + + ### Table Cells If your table contains more complex data (multiple paragraphs, images, lists, etc.), you will probably want to instantiate your `TableCellModel` instances directly. With the exception of page breaks, table cells can contain anything the document can contain, including another table. diff --git a/lib/caracal/core/models/table_model.rb b/lib/caracal/core/models/table_model.rb index 2f41a22e..fd297797 100644 --- a/lib/caracal/core/models/table_model.rb +++ b/lib/caracal/core/models/table_model.rb @@ -21,7 +21,8 @@ class TableModel < BaseModel const_set(:DEFAULT_TABLE_BORDER_COLOR, 'auto') const_set(:DEFAULT_TABLE_BORDER_LINE, :single) const_set(:DEFAULT_TABLE_BORDER_SIZE, 0) # units in 1/8 points - const_set(:DEFAULT_TABLE_BORDER_SPACING, 0) + const_set(:DEFAULT_TABLE_BORDER_SPACING, 0) + const_set(:DEFAULT_TABLE_HEADER_ROWS, 0) # accessors attr_reader :table_align @@ -36,6 +37,7 @@ class TableModel < BaseModel attr_reader :table_border_right # returns border model attr_reader :table_border_horizontal # returns border model attr_reader :table_border_vertical # returns border model + attr_reader :table_header_rows # initialization def initialize(options={}, &block) @@ -44,6 +46,7 @@ def initialize(options={}, &block) @table_border_line = DEFAULT_TABLE_BORDER_LINE @table_border_size = DEFAULT_TABLE_BORDER_SIZE @table_border_spacing = DEFAULT_TABLE_BORDER_SPACING + @table_header_rows = DEFAULT_TABLE_HEADER_ROWS super options, &block end @@ -121,7 +124,7 @@ def cell_style(models, options={}) #=============== SETTERS ============================== # integers - [:border_size, :border_spacing, :width].each do |m| + [:border_size, :border_spacing, :header_rows, :width].each do |m| define_method "#{ m }" do |value| instance_variable_set("@table_#{ m }", value.to_i) end @@ -203,4 +206,4 @@ def option_keys end end -end +end \ No newline at end of file diff --git a/lib/caracal/renderers/document_renderer.rb b/lib/caracal/renderers/document_renderer.rb index 5b14b3fb..d2df61dc 100644 --- a/lib/caracal/renderers/document_renderer.rb +++ b/lib/caracal/renderers/document_renderer.rb @@ -349,8 +349,9 @@ def render_table(xml, model) end rowspan_hash = {} - model.rows.each do |row| + model.rows.each.with_index do |row, row_index| xml['w'].tr do + render_table_row_properties(xml, model, row_index) tc_index = 0 row.each do |tc| xml['w'].tc do @@ -390,6 +391,12 @@ def render_table(xml, model) end end + def render_table_row_properties(xml, model, index) + xml['w'].trPr do + xml['w'].tblHeader if index < model.table_header_rows + end + end + #============= OPTIONS =================================== diff --git a/spec/lib/caracal/core/tables_spec.rb b/spec/lib/caracal/core/tables_spec.rb index 7ba77839..5221eaf9 100644 --- a/spec/lib/caracal/core/tables_spec.rb +++ b/spec/lib/caracal/core/tables_spec.rb @@ -18,6 +18,13 @@ it { expect(subject.contents.size).to eq size + 1 } it { expect(subject.contents.last).to be_a(Caracal::Core::Models::TableModel) } + it { expect(subject.contents.last.table_header_rows).to eq(0) } + + context 'when .header_rows' do + before { subject.table [['Sample Text']] do header_rows 1 end } + + it { expect(subject.contents.last.table_header_rows).to eq(1) } + end end end