axlsx 1.0.18 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +11 -3
- data/README.md +93 -18
- data/examples/example.csv +1000 -0
- data/examples/example.rb +97 -5
- data/examples/example.xlsx +0 -0
- data/examples/example_streamed.xlsx +0 -0
- data/examples/no-use_autowidth.xlsx +0 -0
- data/examples/shared_strings_example.xlsx +0 -0
- data/lib/axlsx.rb +30 -9
- data/lib/axlsx/content_type/content_type.rb +9 -9
- data/lib/axlsx/content_type/default.rb +9 -6
- data/lib/axlsx/content_type/override.rb +12 -8
- data/lib/axlsx/doc_props/app.rb +37 -40
- data/lib/axlsx/doc_props/core.rb +12 -17
- data/lib/axlsx/drawing/axis.rb +38 -19
- data/lib/axlsx/drawing/bar_3D_chart.rb +33 -32
- data/lib/axlsx/drawing/bar_series.rb +13 -14
- data/lib/axlsx/drawing/cat_axis.rb +15 -14
- data/lib/axlsx/drawing/cat_axis_data.rb +16 -18
- data/lib/axlsx/drawing/chart.rb +37 -38
- data/lib/axlsx/drawing/drawing.rb +15 -12
- data/lib/axlsx/drawing/graphic_frame.rb +21 -21
- data/lib/axlsx/drawing/hyperlink.rb +12 -11
- data/lib/axlsx/drawing/line_3D_chart.rb +30 -28
- data/lib/axlsx/drawing/line_series.rb +11 -11
- data/lib/axlsx/drawing/marker.rb +10 -8
- data/lib/axlsx/drawing/named_axis_data.rb +36 -0
- data/lib/axlsx/drawing/one_cell_anchor.rb +17 -16
- data/lib/axlsx/drawing/pic.rb +24 -37
- data/lib/axlsx/drawing/picture_locking.rb +21 -18
- data/lib/axlsx/drawing/pie_3D_chart.rb +10 -8
- data/lib/axlsx/drawing/pie_series.rb +15 -12
- data/lib/axlsx/drawing/scaling.rb +10 -10
- data/lib/axlsx/drawing/scatter_chart.rb +69 -0
- data/lib/axlsx/drawing/scatter_series.rb +39 -0
- data/lib/axlsx/drawing/ser_axis.rb +10 -10
- data/lib/axlsx/drawing/series.rb +15 -15
- data/lib/axlsx/drawing/series_title.rb +14 -14
- data/lib/axlsx/drawing/title.rb +26 -26
- data/lib/axlsx/drawing/two_cell_anchor.rb +18 -20
- data/lib/axlsx/drawing/val_axis.rb +8 -7
- data/lib/axlsx/drawing/val_axis_data.rb +17 -17
- data/lib/axlsx/drawing/view_3D.rb +22 -20
- data/lib/axlsx/package.rb +32 -15
- data/lib/axlsx/rels/relationship.rb +9 -6
- data/lib/axlsx/rels/relationships.rb +7 -1
- data/lib/axlsx/stylesheet/#num_fmt.rb# +69 -0
- data/lib/axlsx/stylesheet/border.rb +27 -23
- data/lib/axlsx/stylesheet/border_pr.rb +16 -15
- data/lib/axlsx/stylesheet/cell_alignment.rb +23 -21
- data/lib/axlsx/stylesheet/cell_protection.rb +10 -7
- data/lib/axlsx/stylesheet/cell_style.rb +8 -5
- data/lib/axlsx/stylesheet/color.rb +20 -14
- data/lib/axlsx/stylesheet/fill.rb +7 -5
- data/lib/axlsx/stylesheet/font.rb +14 -14
- data/lib/axlsx/stylesheet/gradient_fill.rb +19 -16
- data/lib/axlsx/stylesheet/gradient_stop.rb +9 -5
- data/lib/axlsx/stylesheet/num_fmt.rb +12 -6
- data/lib/axlsx/stylesheet/pattern_fill.rb +25 -10
- data/lib/axlsx/stylesheet/styles.rb +41 -32
- data/lib/axlsx/stylesheet/table_style.rb +9 -4
- data/lib/axlsx/stylesheet/table_style_element.rb +10 -7
- data/lib/axlsx/stylesheet/table_styles.rb +11 -8
- data/lib/axlsx/stylesheet/xf.rb +29 -25
- data/lib/axlsx/util/constants.rb +4 -0
- data/lib/axlsx/util/simple_typed_list.rb +18 -9
- data/lib/axlsx/util/validators.rb +13 -6
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/shared_strings_table.rb +19 -21
- data/lib/axlsx/workbook/workbook.rb +43 -19
- data/lib/axlsx/workbook/worksheet/cell.rb +93 -91
- data/lib/axlsx/workbook/worksheet/col.rb +114 -0
- data/lib/axlsx/workbook/worksheet/col.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/page_margins.rb +16 -13
- data/lib/axlsx/workbook/worksheet/row.rb +13 -13
- data/lib/axlsx/workbook/worksheet/table.rb +96 -0
- data/lib/axlsx/workbook/worksheet/table.rb~ +97 -0
- data/lib/axlsx/workbook/worksheet/worksheet.rb +152 -118
- data/lib/schema/dc.xsd +5 -5
- data/lib/schema/dcmitype.xsd +5 -3
- data/lib/schema/dcterms.xsd +15 -15
- data/lib/schema/opc-coreProperties.xsd +6 -2
- data/lib/schema/xml.xsd +7 -8
- data/test/#benchmark.txt# +7 -0
- data/test/#tc_helper.rb# +3 -0
- data/test/benchmark.rb +81 -0
- data/test/benchmark.rb~ +0 -0
- data/test/benchmark.txt +6 -0
- data/test/benchmark.txt~ +6 -0
- data/test/content_type/tc_content_type.rb +30 -32
- data/test/content_type/tc_default.rb +8 -23
- data/test/content_type/tc_override.rb +7 -21
- data/test/doc_props/tc_app.rb +2 -8
- data/test/doc_props/tc_core.rb +6 -7
- data/test/drawing/tc_axis.rb +7 -3
- data/test/drawing/tc_bar_3D_chart.rb +6 -7
- data/test/drawing/tc_bar_series.rb +4 -5
- data/test/drawing/tc_cat_axis.rb +2 -3
- data/test/drawing/tc_cat_axis_data.rb +2 -3
- data/test/drawing/tc_chart.rb +11 -12
- data/test/drawing/tc_drawing.rb +7 -8
- data/test/drawing/tc_graphic_frame.rb +3 -4
- data/test/drawing/tc_hyperlink.rb +2 -3
- data/test/drawing/tc_line_3d_chart.rb +5 -6
- data/test/drawing/tc_line_series.rb +3 -4
- data/test/drawing/tc_marker.rb +3 -4
- data/test/drawing/tc_one_cell_anchor.rb +6 -7
- data/test/drawing/tc_pic.rb +8 -9
- data/test/drawing/tc_picture_locking.rb +2 -3
- data/test/drawing/tc_pie_3D_chart.rb +5 -6
- data/test/drawing/tc_pie_series.rb +4 -5
- data/test/drawing/tc_scaling.rb +3 -4
- data/test/drawing/tc_scatter_chart.rb +43 -0
- data/test/drawing/tc_scatter_series.rb +20 -0
- data/test/drawing/tc_ser_axis.rb +2 -3
- data/test/drawing/tc_series.rb +4 -5
- data/test/drawing/tc_series_title.rb +4 -5
- data/test/drawing/tc_title.rb +4 -5
- data/test/drawing/tc_two_cell_anchor.rb +4 -5
- data/test/drawing/tc_val_axis.rb +2 -3
- data/test/drawing/tc_val_axis_data.rb +2 -3
- data/test/drawing/tc_view_3D.rb +6 -7
- data/test/example.csv +1000 -0
- data/test/example.xlsx +0 -0
- data/test/example_streamed.xlsx +0 -0
- data/test/profile.rb +33 -0
- data/test/rels/tc_relationship.rb +5 -6
- data/test/rels/tc_relationships.rb +4 -5
- data/test/stylesheet/tc_border.rb +3 -4
- data/test/stylesheet/tc_border_pr.rb +3 -4
- data/test/stylesheet/tc_cell_alignment.rb +4 -5
- data/test/stylesheet/tc_cell_protection.rb +2 -3
- data/test/stylesheet/tc_cell_style.rb +2 -3
- data/test/stylesheet/tc_color.rb +2 -3
- data/test/stylesheet/tc_fill.rb +1 -2
- data/test/stylesheet/tc_font.rb +5 -6
- data/test/stylesheet/tc_gradient_fill.rb +1 -2
- data/test/stylesheet/tc_gradient_stop.rb +1 -2
- data/test/stylesheet/tc_num_fmt.rb +1 -2
- data/test/stylesheet/tc_pattern_fill.rb +3 -4
- data/test/stylesheet/tc_styles.rb +15 -9
- data/test/stylesheet/tc_table_style.rb +2 -3
- data/test/stylesheet/tc_table_style_element.rb +2 -3
- data/test/stylesheet/tc_table_styles.rb +3 -4
- data/test/stylesheet/tc_xf.rb +16 -17
- data/test/tc_axlsx.rb +39 -0
- data/test/tc_axlsx.rb~ +0 -0
- data/test/tc_helper.rb +3 -0
- data/test/tc_helper.rb~ +3 -0
- data/test/tc_package.rb +13 -10
- data/test/util/tc_simple_typed_list.rb +8 -9
- data/test/util/tc_validators.rb +7 -8
- data/test/workbook/tc_shared_strings_table.rb +5 -6
- data/test/workbook/tc_workbook.rb +24 -6
- data/test/workbook/worksheet/table/tc_table.rb +71 -0
- data/test/workbook/worksheet/table/tc_table.rb~ +72 -0
- data/test/workbook/worksheet/tc_cell.rb +24 -10
- data/test/workbook/worksheet/tc_col.rb +59 -0
- data/test/workbook/worksheet/tc_col.rb~ +10 -0
- data/test/workbook/worksheet/tc_date_time_converter.rb +1 -2
- data/test/workbook/worksheet/tc_page_margins.rb +6 -9
- data/test/workbook/worksheet/tc_row.rb +26 -12
- data/test/workbook/worksheet/tc_worksheet.rb +134 -68
- metadata +150 -90
- data/test/drawing/tc_hyperlink.rb~ +0 -71
- data/test/workbook/tc_shared_strings_table.rb~ +0 -8
- data/test/workbook/worksheet/tc_date_time_converter.rb~ +0 -69
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module Axlsx
|
|
3
|
+
|
|
4
|
+
# The Col class defines column attributes for columns in sheets.
|
|
5
|
+
class Col
|
|
6
|
+
|
|
7
|
+
# First column affected by this 'column info' record.
|
|
8
|
+
# @return [Integer]
|
|
9
|
+
attr_reader :min
|
|
10
|
+
|
|
11
|
+
# Last column affected by this 'column info' record.
|
|
12
|
+
# @return [Integer]
|
|
13
|
+
attr_reader :max
|
|
14
|
+
|
|
15
|
+
# Flag indicating if the specified column(s) is set to 'best fit'. 'Best fit' is set to true under these conditions:
|
|
16
|
+
# The column width has never been manually set by the user, AND The column width is not the default width
|
|
17
|
+
# 'Best fit' means that when numbers are typed into a cell contained in a 'best fit' column, the column width should
|
|
18
|
+
# automatically resize to display the number. [Note: In best fit cases, column width must not be made smaller, only larger. end note]
|
|
19
|
+
# @return [Boolean]
|
|
20
|
+
attr_reader :bestFit
|
|
21
|
+
|
|
22
|
+
# Flag indicating if the outlining of the affected column(s) is in the collapsed state.
|
|
23
|
+
# @return [Boolean]
|
|
24
|
+
attr_reader :collapsed
|
|
25
|
+
|
|
26
|
+
# Flag indicating if the affected column(s) are hidden on this worksheet.
|
|
27
|
+
# @return [Boolean]
|
|
28
|
+
attr_reader :hidden
|
|
29
|
+
|
|
30
|
+
# Outline level of affected column(s). Range is 0 to 7.
|
|
31
|
+
# @return [Integer]
|
|
32
|
+
attr_reader :outlineLevel
|
|
33
|
+
|
|
34
|
+
# Flag indicating if the phonetic information should be displayed by default for the affected column(s) of the worksheet.
|
|
35
|
+
# @return [Boolean]
|
|
36
|
+
attr_reader :phonetic
|
|
37
|
+
|
|
38
|
+
# Default style for the affected column(s). Affects cells not yet allocated in the column(s). In other words, this style applies to new columns.
|
|
39
|
+
# @return [Integer]
|
|
40
|
+
attr_reader :style
|
|
41
|
+
|
|
42
|
+
# The width of the column
|
|
43
|
+
# @return [Numeric]
|
|
44
|
+
attr_reader :width
|
|
45
|
+
|
|
46
|
+
# @return [Boolean]
|
|
47
|
+
attr_reader :customWidth
|
|
48
|
+
|
|
49
|
+
# @see Col#collapsed
|
|
50
|
+
def collapsed=(v)
|
|
51
|
+
Axlsx.validate_boolean(v)
|
|
52
|
+
@collapsed = v
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @see Col#hidden
|
|
56
|
+
def hidden=(v)
|
|
57
|
+
Axlsx.validate_boolean(v)
|
|
58
|
+
@hidden = v
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @see Col#outline
|
|
62
|
+
def outlineLevel=(v)
|
|
63
|
+
Axlsx.validate_boolean(v)
|
|
64
|
+
@outlineLevel = v
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @see Col#phonetic
|
|
68
|
+
def phonetic=(v)
|
|
69
|
+
Axlsx.validate_boolean(v)
|
|
70
|
+
@phonetic = v
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# @see Col#style
|
|
74
|
+
def style=(v)
|
|
75
|
+
Axlsx.validate_unsigned_int(v)
|
|
76
|
+
@style = v
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# @see Col#width
|
|
80
|
+
def width=(v)
|
|
81
|
+
Axlsx.validate_unsigned_numeric(v) unless v == nil
|
|
82
|
+
@customWidth = @bestFit = v != nil
|
|
83
|
+
@width = v
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Create a new Col objects
|
|
87
|
+
# @param min First column affected by this 'column info' record.
|
|
88
|
+
# @param max Last column affected by this 'column info' record.
|
|
89
|
+
# @option options [Boolean] collapsed see Col#collapsed
|
|
90
|
+
# @option options [Boolean] hidden see Col#hidden
|
|
91
|
+
# @option options [Boolean] outlineLevel see Col#outlineLevel
|
|
92
|
+
# @option options [Boolean] phonetic see Col#phonetic
|
|
93
|
+
# @option options [Integer] style see Col#style
|
|
94
|
+
# @option options [Numeric] width see Col#width
|
|
95
|
+
def initialize(min, max, options={})
|
|
96
|
+
Axlsx.validate_unsigned_int(max)
|
|
97
|
+
Axlsx.validate_unsigned_int(min)
|
|
98
|
+
@min = min
|
|
99
|
+
@max = max
|
|
100
|
+
options.each do |o|
|
|
101
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Serialize this columns data to an xml string
|
|
106
|
+
# @param [String] str
|
|
107
|
+
# @return [String]
|
|
108
|
+
def to_xml_string(str = '')
|
|
109
|
+
attrs = self.instance_values.reject{ |key, value| value == nil }
|
|
110
|
+
str << '<col ' << attrs.map { |key, value| '' << key << '="' << value.to_s << '"' }.join(' ') << '/>'
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
end
|
|
File without changes
|
|
@@ -12,13 +12,13 @@ module Axlsx
|
|
|
12
12
|
|
|
13
13
|
# Default left and right margin (in inches)
|
|
14
14
|
DEFAULT_LEFT_RIGHT = 0.75
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
# Default top and bottom margins (in inches)
|
|
17
17
|
DEFAULT_TOP_BOTTOM = 1.00
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
# Default header and footer margins (in inches)
|
|
20
20
|
DEFAULT_HEADER_FOOTER = 0.50
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
# Left margin (in inches)
|
|
23
23
|
# @return [Float]
|
|
24
24
|
attr_reader :left
|
|
@@ -26,23 +26,23 @@ module Axlsx
|
|
|
26
26
|
# Right margin (in inches)
|
|
27
27
|
# @return [Float]
|
|
28
28
|
attr_reader :right
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
# Top margin (in inches)
|
|
31
31
|
# @return [Float]
|
|
32
32
|
attr_reader :top
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
# Bottom margin (in inches)
|
|
35
35
|
# @return [Float]
|
|
36
36
|
attr_reader :bottom
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
# Header margin (in inches)
|
|
39
39
|
# @return [Float]
|
|
40
40
|
attr_reader :header
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
# Footer margin (in inches)
|
|
43
43
|
# @return [Float]
|
|
44
44
|
attr_reader :footer
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
# Creates a new PageMargins object
|
|
47
47
|
# @option options [Numeric] left The left margin in inches
|
|
48
48
|
# @option options [Numeric] right The right margin in inches
|
|
@@ -60,7 +60,7 @@ module Axlsx
|
|
|
60
60
|
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
# Set some or all margins at once.
|
|
65
65
|
# @param [Hash] margins the margins to set (possible keys are :left, :right, :top, :bottom, :header and :footer).
|
|
66
66
|
def set(margins)
|
|
@@ -69,7 +69,7 @@ module Axlsx
|
|
|
69
69
|
send("#{k}=", v)
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
|
-
|
|
72
|
+
|
|
73
73
|
# @see left
|
|
74
74
|
def left=(v); Axlsx::validate_unsigned_numeric(v); @left = v end
|
|
75
75
|
# @see right
|
|
@@ -84,11 +84,14 @@ module Axlsx
|
|
|
84
84
|
def footer=(v); Axlsx::validate_unsigned_numeric(v); @footer = v end
|
|
85
85
|
|
|
86
86
|
# Serializes the page margins element
|
|
87
|
+
# @param [String] str
|
|
88
|
+
# @return [String]
|
|
87
89
|
# @note For compatibility, this is a noop unless custom margins have been specified.
|
|
88
|
-
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
|
89
90
|
# @see #custom_margins_specified?
|
|
90
|
-
def
|
|
91
|
-
|
|
91
|
+
def to_xml_string(str = '')
|
|
92
|
+
str << '<pageMargins '
|
|
93
|
+
str << instance_values.map { |key, value| '' << key << '="' << value.to_s << '"' }.join(' ')
|
|
94
|
+
str << '/>'
|
|
92
95
|
end
|
|
93
96
|
end
|
|
94
97
|
end
|
|
@@ -60,19 +60,26 @@ module Axlsx
|
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
# Serializes the row
|
|
63
|
-
# @param [
|
|
63
|
+
# @param [Integer] r_index The row index, 0 based.
|
|
64
|
+
# @param [String] str The string this rows xml will be appended to.
|
|
64
65
|
# @return [String]
|
|
65
|
-
def
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
def to_xml_string(r_index, str = '')
|
|
67
|
+
str << '<row r="' << (r_index + 1 ).to_s << '" '
|
|
68
|
+
if custom_height?
|
|
69
|
+
str << 'customHeight="1" ht="' << height.to_s << '">'
|
|
70
|
+
else
|
|
71
|
+
str << '>'
|
|
72
|
+
end
|
|
73
|
+
@cells.each_with_index { |cell, c_index| cell.to_xml_string(r_index, c_index, str) }
|
|
74
|
+
str << '</row>'
|
|
75
|
+
str
|
|
69
76
|
end
|
|
70
77
|
|
|
71
78
|
# Adds a singel sell to the row based on the data provided and updates the worksheet's autofit data.
|
|
72
79
|
# @return [Cell]
|
|
73
80
|
def add_cell(value="", options={})
|
|
74
81
|
c = Cell.new(self, value, options)
|
|
75
|
-
|
|
82
|
+
worksheet.send(:update_column_info, self.cells, self.cells.map(&:style))
|
|
76
83
|
c
|
|
77
84
|
end
|
|
78
85
|
|
|
@@ -106,13 +113,6 @@ module Axlsx
|
|
|
106
113
|
# assigns the owning worksheet for this row
|
|
107
114
|
def worksheet=(v) DataTypeValidator.validate "Row.worksheet", Worksheet, v; @worksheet=v; end
|
|
108
115
|
|
|
109
|
-
# Tell the worksheet to update autofit data for the columns based on this row's cells.
|
|
110
|
-
# @return [SimpleTypedList]
|
|
111
|
-
def update_auto_fit_data
|
|
112
|
-
worksheet.send(:update_auto_fit_data, self.cells)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
|
|
116
116
|
# Converts values, types, and style options into cells and associates them with this row.
|
|
117
117
|
# A new cell is created for each item in the values array.
|
|
118
118
|
# If value option is defined and is a symbol it is applied to all the cells created.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module Axlsx
|
|
3
|
+
# Table
|
|
4
|
+
# @note Worksheet#add_table is the recommended way to create tables for your worksheets.
|
|
5
|
+
# @see README for examples
|
|
6
|
+
class Table
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# The reference to the table data
|
|
10
|
+
# @return [String]
|
|
11
|
+
attr_reader :ref
|
|
12
|
+
|
|
13
|
+
# The name of the table.
|
|
14
|
+
# @return [String]
|
|
15
|
+
attr_reader :name
|
|
16
|
+
|
|
17
|
+
# The style for the table.
|
|
18
|
+
# @return [TableStyle]
|
|
19
|
+
attr_reader :style
|
|
20
|
+
|
|
21
|
+
# Creates a new Table object
|
|
22
|
+
# @param [String] ref The reference to the table data.
|
|
23
|
+
# @param [Sheet] ref The sheet containing the table data.
|
|
24
|
+
# @option options [Cell, String] name
|
|
25
|
+
# @option options [TableStyle] style
|
|
26
|
+
def initialize(ref, sheet, options={})
|
|
27
|
+
@ref = ref
|
|
28
|
+
@sheet = sheet
|
|
29
|
+
@style = nil
|
|
30
|
+
@sheet.workbook.tables << self
|
|
31
|
+
@name = "Table#{index+1}"
|
|
32
|
+
options.each do |o|
|
|
33
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
34
|
+
end
|
|
35
|
+
yield self if block_given?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# The index of this chart in the workbooks charts collection
|
|
39
|
+
# @return [Integer]
|
|
40
|
+
def index
|
|
41
|
+
@sheet.workbook.tables.index(self)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# The part name for this table
|
|
45
|
+
# @return [String]
|
|
46
|
+
def pn
|
|
47
|
+
"#{TABLE_PN % (index+1)}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# The relation reference id for this table
|
|
51
|
+
# @return [String]
|
|
52
|
+
def rId
|
|
53
|
+
"rId#{index+1}"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# The name of the Table.
|
|
57
|
+
# @param [String, Cell] v
|
|
58
|
+
# @return [Title]
|
|
59
|
+
def name=(v)
|
|
60
|
+
DataTypeValidator.validate "#{self.class}.name", [String], v
|
|
61
|
+
if v.is_a?(String)
|
|
62
|
+
@name = v
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Serializes the object
|
|
67
|
+
# @param [String] str
|
|
68
|
+
# @return [String]
|
|
69
|
+
def to_xml_string(str = '')
|
|
70
|
+
str << '<?xml version="1.0" encoding="UTF-8"?>'
|
|
71
|
+
str << '<table xmlns="' << XML_NS << '" id="' << (index+1).to_s << '" name="' << @name << '" displayName="' << @name.gsub(/\s/,'_') << '" '
|
|
72
|
+
str << 'ref="' << @ref << '" totalsRowShown="0">'
|
|
73
|
+
str << '<autoFilter ref="' << @ref << '"/>'
|
|
74
|
+
str << '<tableColumns count="' << header_cells.length.to_s << '">'
|
|
75
|
+
header_cells.each_with_index do |cell,index|
|
|
76
|
+
str << '<tableColumn id ="' << (index+1).to_s << '" name="' << cell.value << '"/>'
|
|
77
|
+
end
|
|
78
|
+
str << '</tableColumns>'
|
|
79
|
+
#TODO implement tableStyleInfo
|
|
80
|
+
str << '<tableStyleInfo showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0" name="TableStyleMedium9" />'
|
|
81
|
+
str << '</table>'
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# The style for the table.
|
|
85
|
+
# TODO
|
|
86
|
+
# def style=(v) DataTypeValidator.validate "Table.style", Integer, v, lambda { |arg| arg >= 1 && arg <= 48 }; @style = v; end
|
|
87
|
+
|
|
88
|
+
private
|
|
89
|
+
|
|
90
|
+
# get the header cells (hackish)
|
|
91
|
+
def header_cells
|
|
92
|
+
header = @ref.gsub(/^(\w+)(\d+)\:(\w+)\d+$/, '\1\2:\3\2')
|
|
93
|
+
@sheet[header]
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module Axlsx
|
|
3
|
+
# Table
|
|
4
|
+
# @note Worksheet#add_table is the recommended way to create charts for your worksheets.
|
|
5
|
+
# @see README for examples
|
|
6
|
+
class Table
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# The reference to the table data
|
|
10
|
+
# @return [String]
|
|
11
|
+
attr_reader :ref
|
|
12
|
+
|
|
13
|
+
# The name of the table.
|
|
14
|
+
# @return [String]
|
|
15
|
+
attr_reader :name
|
|
16
|
+
|
|
17
|
+
# The style for the table.
|
|
18
|
+
# @return [TableStyle]
|
|
19
|
+
attr_reader :style
|
|
20
|
+
|
|
21
|
+
# Creates a new Table object
|
|
22
|
+
# @param [String] ref The reference to the table data.
|
|
23
|
+
# @param [Sheet] ref The sheet containing the table data.
|
|
24
|
+
# @option options [Cell, String] name
|
|
25
|
+
# @option options [TableStyle] style
|
|
26
|
+
def initialize(ref, sheet, options={})
|
|
27
|
+
@ref = ref
|
|
28
|
+
@sheet = sheet
|
|
29
|
+
@style = nil
|
|
30
|
+
@sheet.workbook.tables << self
|
|
31
|
+
@name = "Table#{index+1}"
|
|
32
|
+
options.each do |o|
|
|
33
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
34
|
+
end
|
|
35
|
+
yield self if block_given?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# The index of this chart in the workbooks charts collection
|
|
39
|
+
# @return [Integer]
|
|
40
|
+
def index
|
|
41
|
+
@sheet.workbook.tables.index(self)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# The part name for this table
|
|
45
|
+
# @return [String]
|
|
46
|
+
def pn
|
|
47
|
+
"#{TABLE_PN % (index+1)}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# The relation reference id for this table
|
|
51
|
+
# @return [String]
|
|
52
|
+
def rId
|
|
53
|
+
"rId#{index+1}"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# The name of the Table.
|
|
57
|
+
# @param [String, Cell] v
|
|
58
|
+
# @return [Title]
|
|
59
|
+
def name=(v)
|
|
60
|
+
DataTypeValidator.validate "#{self.class}.name", [String], v
|
|
61
|
+
if v.is_a?(String)
|
|
62
|
+
@name = v
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# The style for the table.
|
|
68
|
+
# TODO
|
|
69
|
+
# def style=(v) DataTypeValidator.validate "Chart.style", Integer, v, lambda { |arg| arg >= 1 && arg <= 48 }; @style = v; end
|
|
70
|
+
|
|
71
|
+
# Table Serialization
|
|
72
|
+
# serializes the table
|
|
73
|
+
def to_xml
|
|
74
|
+
builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml|
|
|
75
|
+
xml.table(:xmlns => XML_NS, :id => index+1, :name => @name, :displayName => @name.gsub(/\s/,'_'), :ref => @ref, :totalsRowShown => 0) {
|
|
76
|
+
xml.autoFilter :ref=>@ref
|
|
77
|
+
xml.tableColumns(:count => header_cells.length) {
|
|
78
|
+
header_cells.each_with_index do |cell,index|
|
|
79
|
+
xml.tableColumn :id => index+1, :name => cell.value
|
|
80
|
+
end
|
|
81
|
+
}
|
|
82
|
+
xml.tableStyleInfo :showFirstColumn=>"0", :showLastColumn=>"0", :showRowStripes=>"1", :showColumnStripes=>"0", :name=>"TableStyleMedium9"
|
|
83
|
+
#TODO implement tableStyleInfo
|
|
84
|
+
}
|
|
85
|
+
end
|
|
86
|
+
builder.to_xml(:save_with => 0)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
private
|
|
90
|
+
|
|
91
|
+
# get the header cells (hackish)
|
|
92
|
+
def header_cells
|
|
93
|
+
header = @ref.gsub(/^(\w+)(\d+)\:(\w+)\d+$/, '\1\2:\3\2')
|
|
94
|
+
@sheet[header]
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -12,6 +12,9 @@ module Axlsx
|
|
|
12
12
|
# @return [Workbook]
|
|
13
13
|
attr_reader :workbook
|
|
14
14
|
|
|
15
|
+
# The tables in this worksheet
|
|
16
|
+
# @return [Array] of Table
|
|
17
|
+
attr_reader :tables
|
|
15
18
|
|
|
16
19
|
# The rows in this worksheet
|
|
17
20
|
# @note The recommended way to manage rows is Worksheet#add_row
|
|
@@ -35,6 +38,26 @@ module Axlsx
|
|
|
35
38
|
# @return Array
|
|
36
39
|
attr_reader :auto_filter
|
|
37
40
|
|
|
41
|
+
# Indicates if the worksheet should show gridlines or not
|
|
42
|
+
# @return Boolean
|
|
43
|
+
attr_reader :show_gridlines
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# Indicates if the worksheet is selected in the workbook
|
|
47
|
+
# It is possible to have more than one worksheet selected, however it might cause issues
|
|
48
|
+
# in some older versions of excel when using copy and paste.
|
|
49
|
+
# @return Boolean
|
|
50
|
+
attr_reader :selected
|
|
51
|
+
|
|
52
|
+
# Indicates if the worksheet should print in a single page
|
|
53
|
+
# @return Boolean
|
|
54
|
+
attr_reader :fit_to_page
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# Column info for the sheet
|
|
58
|
+
# @return [SimpleTypedList]
|
|
59
|
+
attr_reader :column_info
|
|
60
|
+
|
|
38
61
|
# Page margins for printing the worksheet.
|
|
39
62
|
# @example
|
|
40
63
|
# wb = Axlsx::Package.new.workbook
|
|
@@ -55,6 +78,7 @@ module Axlsx
|
|
|
55
78
|
@page_margins ||= PageMargins.new
|
|
56
79
|
yield @page_margins if block_given?
|
|
57
80
|
@page_margins
|
|
81
|
+
|
|
58
82
|
end
|
|
59
83
|
|
|
60
84
|
# Creates a new worksheet.
|
|
@@ -62,19 +86,36 @@ module Axlsx
|
|
|
62
86
|
# @see Workbook#add_worksheet
|
|
63
87
|
# @option options [String] name The name of this worksheet.
|
|
64
88
|
# @option options [Hash] page_margins A hash containing page margins for this worksheet. @see PageMargins
|
|
89
|
+
# @option options [Boolean] show_gridlines indicates if gridlines should be shown for this sheet.
|
|
65
90
|
def initialize(wb, options={})
|
|
66
|
-
@drawing = @page_margins = @auto_filter = nil
|
|
67
|
-
@rows = SimpleTypedList.new Row
|
|
68
91
|
self.workbook = wb
|
|
69
92
|
@workbook.worksheets << self
|
|
70
|
-
@auto_fit_data = []
|
|
71
|
-
self.name = options[:name] || "Sheet" + (index+1).to_s
|
|
72
93
|
|
|
73
|
-
@
|
|
74
|
-
@cols = SimpleTypedList.new Cell
|
|
94
|
+
@drawing = @page_margins = @auto_filter = nil
|
|
75
95
|
@merged_cells = []
|
|
96
|
+
@auto_fit_data = []
|
|
76
97
|
|
|
98
|
+
@selected = false
|
|
99
|
+
@show_gridlines = true
|
|
100
|
+
self.name = "Sheet" + (index+1).to_s
|
|
77
101
|
@page_margins = PageMargins.new options[:page_margins] if options[:page_margins]
|
|
102
|
+
|
|
103
|
+
@rows = SimpleTypedList.new Row
|
|
104
|
+
@column_info = SimpleTypedList.new Col
|
|
105
|
+
# @cols = SimpleTypedList.new Cell
|
|
106
|
+
@tables = SimpleTypedList.new Table
|
|
107
|
+
|
|
108
|
+
if self.workbook.use_autowidth
|
|
109
|
+
require 'RMagick' unless defined?(Magick)
|
|
110
|
+
@magick_draw = Magick::Draw.new
|
|
111
|
+
else
|
|
112
|
+
@magick_draw = nil
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
options.each do |o|
|
|
116
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
117
|
+
end
|
|
118
|
+
|
|
78
119
|
end
|
|
79
120
|
|
|
80
121
|
# convinience method to access all cells in this worksheet
|
|
@@ -109,29 +150,31 @@ module Axlsx
|
|
|
109
150
|
"#{rows.first.cells.first.r}:#{rows.last.cells.last.r}"
|
|
110
151
|
end
|
|
111
152
|
|
|
153
|
+
# Indicates if gridlines should be shown in the sheet.
|
|
154
|
+
# This is true by default.
|
|
155
|
+
# @return [Boolean]
|
|
156
|
+
def show_gridlines=(v)
|
|
157
|
+
Axlsx::validate_boolean v
|
|
158
|
+
@show_gridlines = v
|
|
159
|
+
end
|
|
112
160
|
|
|
113
|
-
#
|
|
114
|
-
# @
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
first = name_to_cell parts[0]
|
|
161
|
+
# @see selected
|
|
162
|
+
# @return [Boolean]
|
|
163
|
+
def selected=(v)
|
|
164
|
+
Axlsx::validate_boolean v
|
|
165
|
+
@selected = v
|
|
166
|
+
end
|
|
120
167
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
cells << c
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
cells
|
|
132
|
-
end
|
|
168
|
+
|
|
169
|
+
# Indicates if the worksheet should print in a single page.
|
|
170
|
+
# This is true by default.
|
|
171
|
+
# @return [Boolean]
|
|
172
|
+
def fit_to_page=(v)
|
|
173
|
+
Axlsx::validate_boolean v
|
|
174
|
+
@fit_to_page = v
|
|
133
175
|
end
|
|
134
176
|
|
|
177
|
+
|
|
135
178
|
# returns the column and row index for a named based cell
|
|
136
179
|
# @param [String] name The cell or cell range to return. "A1" will return the first cell of the first row.
|
|
137
180
|
# @return [Cell]
|
|
@@ -152,6 +195,12 @@ module Axlsx
|
|
|
152
195
|
@name=v
|
|
153
196
|
end
|
|
154
197
|
|
|
198
|
+
# The absolute auto filter range
|
|
199
|
+
# @see auto_filter
|
|
200
|
+
def abs_auto_filter
|
|
201
|
+
Axlsx.cell_range(@auto_filter.split(':').collect { |name| name_to_cell(name)}) if @auto_filter
|
|
202
|
+
end
|
|
203
|
+
|
|
155
204
|
# The auto filter range for the worksheet
|
|
156
205
|
# @param [String] v
|
|
157
206
|
# @see auto_filter
|
|
@@ -233,7 +282,8 @@ module Axlsx
|
|
|
233
282
|
# @option options [Float] height the row's height (in points)
|
|
234
283
|
def add_row(values=[], options={})
|
|
235
284
|
Row.new(self, values, options)
|
|
236
|
-
|
|
285
|
+
update_column_info @rows.last.cells, options.delete(:widths) ||[], options.delete(:style) || []
|
|
286
|
+
# update_auto_fit_data @rows.last.cells, options.delete(:widths) || []
|
|
237
287
|
yield @rows.last if block_given?
|
|
238
288
|
@rows.last
|
|
239
289
|
end
|
|
@@ -292,9 +342,9 @@ module Axlsx
|
|
|
292
342
|
# @param [Integer|Float|Fixnum|nil] values
|
|
293
343
|
def column_widths(*args)
|
|
294
344
|
args.each_with_index do |value, index|
|
|
295
|
-
raise ArgumentError, "Invalid column specification" unless index < @
|
|
345
|
+
raise ArgumentError, "Invalid column specification" unless index < @column_info.size
|
|
296
346
|
Axlsx::validate_unsigned_numeric(value) unless value == nil
|
|
297
|
-
@
|
|
347
|
+
@column_info[index].width = value
|
|
298
348
|
end
|
|
299
349
|
end
|
|
300
350
|
|
|
@@ -317,6 +367,14 @@ module Axlsx
|
|
|
317
367
|
chart
|
|
318
368
|
end
|
|
319
369
|
|
|
370
|
+
# needs documentation
|
|
371
|
+
def add_table(ref, options={})
|
|
372
|
+
table = Table.new(ref, self, options)
|
|
373
|
+
@tables << table
|
|
374
|
+
yield table if block_given?
|
|
375
|
+
table
|
|
376
|
+
end
|
|
377
|
+
|
|
320
378
|
# Adds a media item to the worksheets drawing
|
|
321
379
|
# @param [Class] media_type
|
|
322
380
|
# @option options [] unknown
|
|
@@ -326,125 +384,101 @@ module Axlsx
|
|
|
326
384
|
image
|
|
327
385
|
end
|
|
328
386
|
|
|
329
|
-
# Serializes the
|
|
387
|
+
# Serializes the object
|
|
388
|
+
# @param [String] str
|
|
330
389
|
# @return [String]
|
|
331
|
-
def
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
}
|
|
353
|
-
end
|
|
354
|
-
xml.sheetData {
|
|
355
|
-
@rows.each do |row|
|
|
356
|
-
row.to_xml(xml)
|
|
357
|
-
end
|
|
358
|
-
}
|
|
359
|
-
xml.autoFilter :ref=>@auto_filter if @auto_filter
|
|
360
|
-
xml.mergeCells(:count=>@merged_cells.size) { @merged_cells.each { | mc | xml.mergeCell(:ref=>mc) } } unless @merged_cells.empty?
|
|
361
|
-
page_margins.to_xml(xml) if @page_margins
|
|
362
|
-
xml.drawing :"r:id"=>"rId1" if @drawing
|
|
363
|
-
}
|
|
390
|
+
def to_xml_string
|
|
391
|
+
str = '<?xml version="1.0" encoding="UTF-8"?>'
|
|
392
|
+
str.concat "<worksheet xmlns=\"%s\" xmlns:r=\"%s\">" % [XML_NS, XML_NS_R]
|
|
393
|
+
str.concat "<sheetPr><pageSetUpPr fitToPage=\"%s\"></pageSetUpPr></sheetPr>" % fit_to_page if fit_to_page
|
|
394
|
+
str.concat "<dimension ref=\"%s\"></dimension>" % dimension unless rows.size == 0
|
|
395
|
+
str.concat "<sheetViews><sheetView tabSelected='%s' workbookViewId='0' showGridLines='%s'><selection activeCell=\"A1\" sqref=\"A1\"/></sheetView></sheetViews>" % [@selected, show_gridlines]
|
|
396
|
+
|
|
397
|
+
if @column_info.size > 0
|
|
398
|
+
str << "<cols>"
|
|
399
|
+
@column_info.each { |col| col.to_xml_string(str) }
|
|
400
|
+
str.concat '</cols>'
|
|
401
|
+
end
|
|
402
|
+
str.concat '<sheetData>'
|
|
403
|
+
@rows.each_with_index { |row, index| row.to_xml_string(index, str) }
|
|
404
|
+
str.concat '</sheetData>'
|
|
405
|
+
page_margins.to_xml_string(str) if @page_margins
|
|
406
|
+
str.concat "<autoFilter ref='%s'></autoFilter>" % @auto_filter if @auto_filter
|
|
407
|
+
str.concat "<mergeCells count='%s'>%s</mergeCells>" % [@merged_cells.size, @merged_cells.reduce('') { |memo, obj| "<mergeCell ref='%s'></mergeCell>" % obj } ] unless @merged_cells.empty?
|
|
408
|
+
str.concat "<drawing r:id='rId1'></drawing>" if @drawing
|
|
409
|
+
unless @tables.empty?
|
|
410
|
+
str.concat "<tableParts count='%s'>%s</tableParts>" % [@tables.size, @tables.reduce('') { |memo, obj| memo += "<tablePart r:id='%s'/>" % obj.rId }]
|
|
364
411
|
end
|
|
365
|
-
|
|
412
|
+
str + '</worksheet>'
|
|
366
413
|
end
|
|
367
414
|
|
|
368
415
|
# The worksheet relationships. This is managed automatically by the worksheet
|
|
369
416
|
# @return [Relationships]
|
|
370
417
|
def relationships
|
|
371
418
|
r = Relationships.new
|
|
419
|
+
@tables.each do |table|
|
|
420
|
+
r << Relationship.new(TABLE_R, "../#{table.pn}")
|
|
421
|
+
end
|
|
372
422
|
r << Relationship.new(DRAWING_R, "../#{@drawing.pn}") if @drawing
|
|
373
423
|
r
|
|
374
424
|
end
|
|
375
425
|
|
|
426
|
+
# Returns the cell or cells defined using excel style A1:B3 references.
|
|
427
|
+
# @param [String|Integer] cell_def the string defining the cell or range of cells, or the rownumber
|
|
428
|
+
# @return [Cell, Array]
|
|
429
|
+
|
|
430
|
+
def [] (cell_def)
|
|
431
|
+
return rows[cell_def] if cell_def.is_a?(Integer)
|
|
432
|
+
|
|
433
|
+
parts = cell_def.split(':')
|
|
434
|
+
first = name_to_cell parts[0]
|
|
435
|
+
if parts.size == 1
|
|
436
|
+
first
|
|
437
|
+
else
|
|
438
|
+
cells = []
|
|
439
|
+
last = name_to_cell(parts[1])
|
|
440
|
+
rows[(first.row.index..last.row.index)].each do |r|
|
|
441
|
+
r.cells[(first.index..last.index)].each do |c|
|
|
442
|
+
cells << c
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
cells
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
376
449
|
private
|
|
377
450
|
|
|
378
451
|
# assigns the owner workbook for this worksheet
|
|
379
452
|
def workbook=(v) DataTypeValidator.validate "Worksheet.workbook", Workbook, v; @workbook = v; end
|
|
380
453
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
# attempt to identify the longest cell in the column. This is not 100% accurate as it needs to take into account
|
|
384
|
-
# any formatting that will be applied to the data, as well as the actual rendering size when the length and size is equal
|
|
385
|
-
# for two cells.
|
|
386
|
-
|
|
387
|
-
# @return [Array] of Cell objects
|
|
388
|
-
# @param [Array] cells an array of cells
|
|
389
|
-
# @param [Array] widths an array of cell widths @see Worksheet#add_row
|
|
390
|
-
def update_auto_fit_data(cells, widths=[])
|
|
391
|
-
# TODO delay this until rendering. too much work when we dont know what they are going to do to the sheet.
|
|
454
|
+
|
|
455
|
+
def update_column_info(cells, widths=[], style=[])
|
|
392
456
|
styles = self.workbook.styles
|
|
393
457
|
cellXfs, fonts = styles.cellXfs, styles.fonts
|
|
394
458
|
sz = 11
|
|
395
|
-
cells.each_with_index do |
|
|
396
|
-
|
|
459
|
+
cells.each_with_index do |cell, index|
|
|
460
|
+
@column_info[index] ||= Col.new index+1, index+1
|
|
461
|
+
col = @column_info[index]
|
|
397
462
|
width = widths[index]
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
font = fonts[cell_xf.fontId || 0]
|
|
407
|
-
sz = item.sz || font.sz || fonts[0].sz
|
|
408
|
-
if (col[:longest].scan(/./mu).size * col[:sz]) < (item.value.to_s.scan(/./mu).size * sz)
|
|
409
|
-
col[:sz] = sz
|
|
410
|
-
col[:longest] = item.value.to_s
|
|
463
|
+
col.width = width if [Integer, Float, Fixnum].include?(width.class)
|
|
464
|
+
c_style = style[index] if [Integer, Fixnum].include?(style[index].class)
|
|
465
|
+
next if width == :ignore || col.width || (cell.value.is_a?(String) && cell.value.start_with?('='))
|
|
466
|
+
if self.workbook.use_autowidth
|
|
467
|
+
cell_xf = cellXfs[(c_style || 0)]
|
|
468
|
+
font = fonts[(cell_xf.fontId || 0)]
|
|
469
|
+
sz = cell.sz || font.sz || sz
|
|
470
|
+
col.width = [(col.width || 0), calculate_width(cell.value.to_s, sz)].max
|
|
411
471
|
end
|
|
412
472
|
end
|
|
413
|
-
cells
|
|
414
473
|
end
|
|
415
474
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
# @return [Float]
|
|
420
|
-
# @param [Hash] A hash of auto_fit_data
|
|
421
|
-
def auto_width(col)
|
|
422
|
-
return col[:fixed] unless col[:fixed] == nil
|
|
423
|
-
|
|
424
|
-
mdw_count, font_scale, mdw = 0, col[:sz]/11.0, 6.0
|
|
425
|
-
mdw_count = col[:longest].scan(/./mu).reduce(0) do | count, char |
|
|
475
|
+
def calculate_width(text, sz)
|
|
476
|
+
mdw_count, font_scale, mdw = 0, sz/11.0, 6.0
|
|
477
|
+
mdw_count = text.scan(/./mu).reduce(0) do | count, char |
|
|
426
478
|
count +=1 if @magick_draw.get_type_metrics(char).max_advance >= mdw
|
|
427
479
|
count
|
|
428
480
|
end
|
|
429
481
|
((mdw_count * mdw + 5) / mdw * 256) / 256.0 * font_scale
|
|
430
482
|
end
|
|
431
|
-
|
|
432
|
-
# Something to look into:
|
|
433
|
-
# width calculation actually needs to be done agains the formatted value for items that apply a
|
|
434
|
-
# format
|
|
435
|
-
# def excel_format(cell)
|
|
436
|
-
# # The most common case.
|
|
437
|
-
# return time.value.to_s if cell.style == 0
|
|
438
|
-
#
|
|
439
|
-
# # The second most common case
|
|
440
|
-
# num_fmt = workbook.styles.cellXfs[items.style].numFmtId
|
|
441
|
-
# return value.to_s if num_fmt == 0
|
|
442
|
-
#
|
|
443
|
-
# format_code = workbook.styles.numFmts[num_fmt]
|
|
444
|
-
# # need to find some exceptionally fast way of parsing value according to
|
|
445
|
-
# # an excel format_code
|
|
446
|
-
# item.value.to_s
|
|
447
|
-
# end
|
|
448
|
-
|
|
449
483
|
end
|
|
450
484
|
end
|