summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lib/axlsx/workbook/worksheet/cell.rb14
-rw-r--r--lib/axlsx/workbook/worksheet/col.rb15
-rw-r--r--lib/axlsx/workbook/worksheet/row.rb2
-rw-r--r--lib/axlsx/workbook/worksheet/worksheet.rb45
-rw-r--r--test/workbook/worksheet/tc_row.rb4
-rw-r--r--test/workbook/worksheet/tc_worksheet.rb2
6 files changed, 48 insertions, 34 deletions
diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb
index 407aef4d..7b302865 100644
--- a/lib/axlsx/workbook/worksheet/cell.rb
+++ b/lib/axlsx/workbook/worksheet/cell.rb
@@ -321,8 +321,22 @@ module Axlsx
@type == :string && @value.start_with?('=')
end
+ # This is still not perfect...
+ # - scaling is not linear as font sizes increst
+ # - different fonts have different mdw and char widths
+ def autowidth
+ return if is_formula? || value == nil
+ mdw = 1.78 #This is the widest width of 0..9 in arial@10px)
+ font_scale = (font_size/10.0).to_f
+ ((value.to_s.count(Worksheet.thin_chars) * mdw + 5) / mdw * 256) / 256.0 * font_scale
+ end
+
private
+ def font_size
+ sz || @styles.fonts[@styles.cellXfs[style].fontId].sz
+ end
+
# Utility method for setting inline style attributes
def set_run_style( validator, attr, value)
return unless INLINE_STYLES.include?(attr.to_s)
diff --git a/lib/axlsx/workbook/worksheet/col.rb b/lib/axlsx/workbook/worksheet/col.rb
index fb19a1bd..18414b62 100644
--- a/lib/axlsx/workbook/worksheet/col.rb
+++ b/lib/axlsx/workbook/worksheet/col.rb
@@ -102,6 +102,21 @@ module Axlsx
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
end
end
+
+ # updates the width for this col based on the cells autowidth and
+ # an optionally specified fixed width
+ # @param [Cell] cell The cell to use in updating this col's width
+ # @param [Integer] fixed_width If this is specified the width is set
+ # to this value and the cell's attributes are ignored.
+ # @param [Boolean] use_autowidth If this is false, the cell's
+ # autowidth value will be ignored.
+ def update_width(cell, fixed_width=nil, use_autowidth=true)
+ if fixed_width.is_a? Numeric
+ self.width = fixed_width
+ elsif use_autowidth
+ self.width = [width || 0, cell.autowidth || 0].max
+ end
+ end
# Serialize this columns data to an xml string
# @param [String] str
diff --git a/lib/axlsx/workbook/worksheet/row.rb b/lib/axlsx/workbook/worksheet/row.rb
index c15b2064..b10d8403 100644
--- a/lib/axlsx/workbook/worksheet/row.rb
+++ b/lib/axlsx/workbook/worksheet/row.rb
@@ -134,7 +134,7 @@ module Axlsx
# @return [Cell]
def add_cell(value="", options={})
c = Cell.new(self, value, options)
- worksheet.send(:update_column_info, self.cells, [], self.cells.map(&:style))
+ worksheet.send(:update_column_info, self.cells, [])
c
end
diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb
index 54f42553..41b50a4a 100644
--- a/lib/axlsx/workbook/worksheet/worksheet.rb
+++ b/lib/axlsx/workbook/worksheet/worksheet.rb
@@ -274,10 +274,10 @@ module Axlsx
# but at least a few other document readers expect this for conversion
# @return [String] the A1:B2 style reference for the first and last row column intersection in the workbook
def dimension
- "#{dimension_reference(rows.first.cells.first, 'A1')}:#{dimension_reference(rows.last.cells.last, 'AA200')}"
+ "#{dimension_reference(rows.first.cells.first, 'A1')}:#{dimension_reference(rows.last.cells.last, 'AA200')}"
end
- #
+ #
# Indicates if gridlines should be shown in the sheet.
# This is true by default.
# @return [Boolean]
@@ -415,8 +415,7 @@ module Axlsx
# @option options [Float] height the row's height (in points)
def add_row(values=[], options={})
Row.new(self, values, options)
- update_column_info @rows.last.cells, options.delete(:widths) ||[], options.delete(:style) || []
- # update_auto_fit_data @rows.last.cells, options.delete(:widths) || []
+ update_column_info @rows.last.cells, options.delete(:widths) || []
yield @rows.last if block_given?
@rows.last
end
@@ -470,7 +469,7 @@ module Axlsx
# This is a helper method that Lets you specify a fixed width for multiple columns in a worksheet in one go.
# Axlsx is sparse, so if you have not set data for a column, you cannot set the width.
- # Setting a fixed column width to nil will revert the behaviour back to calculating the width for you.
+ # Setting a fixed column width to nil will revert the behaviour back to calculating the width for you on the next call to add_row.
# @example This would set the first and third column widhts but leave the second column in autofit state.
# ws.column_widths 7.2, nil, 3
# @note For updating only a single column it is probably easier to just set the width of the ws.column_info[col_index].width directly
@@ -709,36 +708,22 @@ module Axlsx
# assigns the owner workbook for this worksheet
def workbook=(v) DataTypeValidator.validate "Worksheet.workbook", Workbook, v; @workbook = v; end
- # TODO this needs cleanup!
- def update_column_info(cells, widths=[], style=[])
- styles = self.workbook.styles
- cellXfs, fonts = styles.cellXfs, styles.fonts
- sz = 11
+ def styles
+ @styles ||= self.workbook.styles
+ end
+ def update_column_info(cells, widths=[])
cells.each_with_index do |cell, index|
- @column_info[index] ||= Col.new index+1, index+1
- col = @column_info[index]
- width = widths[index]
- col.width = width if [Integer, Float, Fixnum].include?(width.class)
- c_style = style[index] if [Integer, Fixnum].include?(style[index].class)
- next if width == :ignore || (cell.value.is_a?(String) && cell.value.start_with?('=') || cell.value == nil)
- if self.workbook.use_autowidth
- cell_xf = cellXfs[(c_style || 0)]
- font = fonts[(cell_xf.fontId || 0)]
- sz = cell.sz || font.sz || sz
- col.width = [(col.width || 0), calculate_width(cell.value.to_s, sz)].max
- end
+ col = find_or_create_column_info(index)
+ next if widths[index] == :ignore
+ col.update_width(cell, widths[index], workbook.use_autowidth)
end
end
-
- # This is still not perfect...
- # - scaling is not linear as font sizes increst
- # - different fonts have different mdw and char widths
- def calculate_width(text, sz)
- mdw = 1.78 #This is the widest width of 0..9 in arial@10px)
- font_scale = (sz/10.0).to_f
- ((text.count(Worksheet.thin_chars) * mdw + 5) / mdw * 256) / 256.0 * font_scale
+ def find_or_create_column_info(index, fixed_width=nil)
+ col = @column_info[index] || Col.new(index + 1, index + 1)
+ @column_info[index] = col if index == @column_info.size
+ col
end
def dimension_reference(cell, default)
diff --git a/test/workbook/worksheet/tc_row.rb b/test/workbook/worksheet/tc_row.rb
index bfd5ae9f..b126845a 100644
--- a/test/workbook/worksheet/tc_row.rb
+++ b/test/workbook/worksheet/tc_row.rb
@@ -38,8 +38,8 @@ class TestRow < Test::Unit::TestCase
end
def test_add_cell_autowidth_info
- width = @ws.send :calculate_width, 'this is the cell of cells', @ws.workbook.styles.fonts.first.sz
- @row.add_cell("this is the cell of cells")
+ cell = @row.add_cell("this is the cell of cells")
+ width = cell.send(:autowidth)
assert_equal(@ws.column_info.last.width, width)
end
diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb
index 3ab80ed2..9f7529c4 100644
--- a/test/workbook/worksheet/tc_worksheet.rb
+++ b/test/workbook/worksheet/tc_worksheet.rb
@@ -365,7 +365,7 @@ class TestWorksheet < Test::Unit::TestCase
def test_set_fixed_width_column
@ws.add_row ["mule", "donkey", "horse"], :widths => [20, :ignore, nil]
assert(@ws.column_info.size == 3, "a data item for each column")
- assert_equal(@ws.column_info[0].width, 20, "adding a row with fixed width updates :fixed attribute")
+ assert_equal(20, @ws.column_info[0].width, "adding a row with fixed width updates :fixed attribute")
assert_equal(@ws.column_info[1].width, nil, ":ignore does not set any data")
end