axlsx 1.0.17 → 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 +159 -51
- data/examples/example.csv +1000 -0
- data/examples/example.rb +255 -150
- 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/content_type/content_type.rb +12 -12
- 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 +39 -40
- 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 +25 -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 +60 -43
- data/lib/axlsx/rels/relationship.rb +11 -8
- 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 +21 -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 +47 -35
- 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 +20 -14
- 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 +58 -34
- data/lib/axlsx/workbook/worksheet/cell.rb +149 -132
- data/lib/axlsx/workbook/worksheet/col.rb +114 -0
- data/lib/axlsx/workbook/worksheet/col.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/date_time_converter.rb +29 -0
- data/lib/axlsx/workbook/worksheet/page_margins.rb +97 -0
- data/lib/axlsx/workbook/worksheet/row.rb +40 -23
- 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 +243 -127
- data/lib/axlsx.rb +30 -9
- 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 +13 -14
- 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 +10 -6
- 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 +12 -5
- 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 +16 -6
- 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 +62 -18
- 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 +126 -0
- data/test/workbook/worksheet/tc_page_margins.rb +97 -0
- data/test/workbook/worksheet/tc_row.rb +54 -4
- data/test/workbook/worksheet/tc_worksheet.rb +177 -34
- metadata +69 -41
- data/test/drawing/tc_hyperlink.rb~ +0 -71
- data/test/workbook/tc_shared_strings_table.rb~ +0 -8
|
@@ -1,61 +1,66 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
|
+
require 'cgi'
|
|
2
3
|
module Axlsx
|
|
3
|
-
# A cell in a worksheet.
|
|
4
|
+
# A cell in a worksheet.
|
|
4
5
|
# Cell stores inforamation requried to serialize a single worksheet cell to xml. You must provde the Row that the cell belongs to and the cells value. The data type will automatically be determed if you do not specify the :type option. The default style will be applied if you do not supply the :style option. Changing the cell's type will recast the value to the type specified. Altering the cell's value via the property accessor will also automatically cast the provided value to the cell's type.
|
|
5
6
|
# @example Manually creating and manipulating Cell objects
|
|
6
|
-
# ws = Workbook.new.add_worksheet
|
|
7
|
+
# ws = Workbook.new.add_worksheet
|
|
7
8
|
# # This is the simple, and recommended way to create cells. Data types will automatically be determined for you.
|
|
8
9
|
# ws.add_row :values => [1,"fish",Time.now]
|
|
9
10
|
#
|
|
10
11
|
# # but you can also do this
|
|
11
12
|
# r = ws.add_row
|
|
12
13
|
# r.add_cell 1
|
|
13
|
-
#
|
|
14
|
+
#
|
|
14
15
|
# # or even this
|
|
15
16
|
# r = ws.add_row
|
|
16
17
|
# c = Cell.new row, 1, :value=>integer
|
|
17
18
|
#
|
|
18
19
|
# # cells can also be accessed via Row#cells. The example here changes the cells type, which will automatically updated the value from 1 to 1.0
|
|
19
20
|
# r.cells.last.type = :float
|
|
20
|
-
#
|
|
21
|
+
#
|
|
21
22
|
# @note The recommended way to generate cells is via Worksheet#add_row
|
|
22
|
-
#
|
|
23
|
+
#
|
|
23
24
|
# @see Worksheet#add_row
|
|
24
25
|
class Cell
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
# An array of available inline styes.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
# TODO change this to a hash where each key defines attr name and validator (and any info the validator requires)
|
|
30
|
+
# then move it out to a module so we can re-use in in other classes.
|
|
31
|
+
# needs to define bla=(v) and bla methods on the class that hook into a
|
|
32
|
+
# set_attr method that kicks the suplied validator and updates the instance_variable
|
|
33
|
+
# for the key
|
|
34
|
+
INLINE_STYLES = ['value', 'type', 'font_name', 'charset',
|
|
35
|
+
'family', 'b', 'i', 'strike','outline',
|
|
36
|
+
'shadow', 'condense', 'extend', 'u',
|
|
31
37
|
'vertAlign', 'sz', 'color', 'scheme']
|
|
32
38
|
|
|
33
|
-
|
|
34
39
|
# The index of the cellXfs item to be applied to this cell.
|
|
35
|
-
# @return [Integer]
|
|
40
|
+
# @return [Integer]
|
|
36
41
|
# @see Axlsx::Styles
|
|
37
42
|
attr_reader :style
|
|
38
43
|
|
|
39
44
|
# The row this cell belongs to.
|
|
40
45
|
# @return [Row]
|
|
41
46
|
attr_reader :row
|
|
42
|
-
|
|
43
|
-
# The cell's data type. Currently only
|
|
44
|
-
# Changing the type for a cell will recast the value into that type. If no type option is specified in the constructor, the type is
|
|
47
|
+
|
|
48
|
+
# The cell's data type. Currently only six types are supported, :date, :time, :float, :integer, :string and :boolean.
|
|
49
|
+
# Changing the type for a cell will recast the value into that type. If no type option is specified in the constructor, the type is
|
|
45
50
|
# automatically determed.
|
|
46
51
|
# @see Cell#cell_type_from_value
|
|
47
|
-
# @return [Symbol] The type of data this cell's value is cast to.
|
|
48
|
-
# @raise [ArgumentExeption] Cell.type must be one of [:time, :float, :integer, :string]
|
|
49
|
-
# @note
|
|
52
|
+
# @return [Symbol] The type of data this cell's value is cast to.
|
|
53
|
+
# @raise [ArgumentExeption] Cell.type must be one of [:date, time, :float, :integer, :string, :boolean]
|
|
54
|
+
# @note
|
|
50
55
|
# If the value provided cannot be cast into the type specified, type is changed to :string and the following logic is applied.
|
|
51
|
-
# :string to :integer or :float, type
|
|
56
|
+
# :string to :integer or :float, type conversions always return 0 or 0.0
|
|
52
57
|
# :string, :integer, or :float to :time conversions always return the original value as a string and set the cells type to :string.
|
|
53
58
|
# No support is currently implemented for parsing time strings.
|
|
54
59
|
attr_reader :type
|
|
55
60
|
# @see type
|
|
56
|
-
def type=(v)
|
|
57
|
-
RestrictionValidator.validate "Cell.type", [:time, :float, :integer, :string], v
|
|
58
|
-
@type=v
|
|
61
|
+
def type=(v)
|
|
62
|
+
RestrictionValidator.validate "Cell.type", [:date, :time, :float, :integer, :string, :boolean], v
|
|
63
|
+
@type=v
|
|
59
64
|
self.value = @value unless @value.nil?
|
|
60
65
|
end
|
|
61
66
|
|
|
@@ -68,103 +73,118 @@ module Axlsx
|
|
|
68
73
|
#TODO: consider doing value based type determination first?
|
|
69
74
|
@value = cast_value(v)
|
|
70
75
|
end
|
|
71
|
-
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# Indicates that the cell has one or more of the custom cell styles applied.
|
|
79
|
+
# @return [Boolean]
|
|
80
|
+
def is_text_run?
|
|
81
|
+
@is_text_run ||= false
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
|
|
72
85
|
# The inline font_name property for the cell
|
|
73
86
|
# @return [String]
|
|
74
87
|
attr_reader :font_name
|
|
75
88
|
# @see font_name
|
|
76
|
-
def font_name=(v)
|
|
89
|
+
def font_name=(v) set_run_style :validate_string, :font_name, v; end
|
|
77
90
|
|
|
78
91
|
# The inline charset property for the cell
|
|
79
92
|
# @return [String]
|
|
80
93
|
attr_reader :charset
|
|
81
94
|
# @see charset
|
|
82
|
-
def charset=(v)
|
|
95
|
+
def charset=(v) set_run_style :validate_unsigned_int, :charset, v; end
|
|
83
96
|
|
|
84
97
|
# The inline family property for the cell
|
|
85
98
|
# @return [String]
|
|
86
99
|
attr_reader :family
|
|
87
100
|
# @see family
|
|
88
|
-
def family=(v)
|
|
101
|
+
def family=(v) set_run_style :validate_string, :family, v; end
|
|
89
102
|
|
|
90
103
|
# The inline bold property for the cell
|
|
91
104
|
# @return [Boolean]
|
|
92
105
|
attr_reader :b
|
|
93
106
|
# @see b
|
|
94
|
-
def b=(v)
|
|
107
|
+
def b=(v) set_run_style :validate_boolean, :b, v; end
|
|
95
108
|
|
|
96
109
|
# The inline italic property for the cell
|
|
97
110
|
# @return [Boolean]
|
|
98
111
|
attr_reader :i
|
|
99
112
|
# @see i
|
|
100
|
-
def i=(v)
|
|
113
|
+
def i=(v) set_run_style :validate_boolean, :i, v; end
|
|
101
114
|
|
|
102
115
|
# The inline strike property for the cell
|
|
103
116
|
# @return [Boolean]
|
|
104
117
|
attr_reader :strike
|
|
105
118
|
# @see strike
|
|
106
|
-
def strike=(v)
|
|
119
|
+
def strike=(v) set_run_style :validate_boolean, :strike, v; end
|
|
107
120
|
|
|
108
121
|
# The inline outline property for the cell
|
|
109
122
|
# @return [Boolean]
|
|
110
123
|
attr_reader :outline
|
|
111
124
|
# @see outline
|
|
112
|
-
def outline=(v)
|
|
125
|
+
def outline=(v) set_run_style :validate_boolean, :outline, v; end
|
|
113
126
|
|
|
114
127
|
# The inline shadow property for the cell
|
|
115
128
|
# @return [Boolean]
|
|
116
129
|
attr_reader :shadow
|
|
117
130
|
# @see shadow
|
|
118
|
-
def shadow=(v)
|
|
131
|
+
def shadow=(v) set_run_style :validate_boolean, :shadow, v; end
|
|
119
132
|
|
|
120
133
|
# The inline condense property for the cell
|
|
121
134
|
# @return [Boolean]
|
|
122
135
|
attr_reader :condense
|
|
123
136
|
# @see condense
|
|
124
|
-
def condense=(v)
|
|
137
|
+
def condense=(v) set_run_style :validate_boolean, :condense, v; end
|
|
125
138
|
|
|
126
139
|
# The inline extend property for the cell
|
|
127
140
|
# @return [Boolean]
|
|
128
141
|
attr_reader :extend
|
|
129
142
|
# @see extend
|
|
130
|
-
def extend=(v)
|
|
143
|
+
def extend=(v) set_run_style :validate_boolean, :extend, v; end
|
|
131
144
|
|
|
132
145
|
# The inline underline property for the cell
|
|
133
146
|
# @return [Boolean]
|
|
134
147
|
attr_reader :u
|
|
135
148
|
# @see u
|
|
136
|
-
def u=(v)
|
|
149
|
+
def u=(v) set_run_style :validate_boolean, :u, v; end
|
|
137
150
|
|
|
138
151
|
# The inline color property for the cell
|
|
139
152
|
# @return [Color]
|
|
140
153
|
attr_reader :color
|
|
141
154
|
# @param [String] The 8 character representation for an rgb color #FFFFFFFF"
|
|
142
|
-
def color=(v)
|
|
155
|
+
def color=(v)
|
|
143
156
|
@color = v.is_a?(Color) ? v : Color.new(:rgb=>v)
|
|
157
|
+
@has_run_style = true
|
|
144
158
|
end
|
|
145
159
|
|
|
146
160
|
# The inline sz property for the cell
|
|
147
161
|
# @return [Boolean]
|
|
148
162
|
attr_reader :sz
|
|
149
163
|
# @see sz
|
|
150
|
-
def sz=(v)
|
|
164
|
+
def sz=(v) set_run_style :validate_unsigned_int, :sz, v; end
|
|
151
165
|
|
|
152
166
|
# The inline vertical alignment property for the cell
|
|
153
167
|
# this must be one of [:baseline, :subscript, :superscript]
|
|
154
168
|
# @return [Symbol]
|
|
155
169
|
attr_reader :vertAlign
|
|
156
170
|
# @see vertAlign
|
|
157
|
-
def vertAlign=(v)
|
|
171
|
+
def vertAlign=(v)
|
|
172
|
+
RestrictionValidator.validate "Cell.vertAlign", [:baseline, :subscript, :superscript], v
|
|
173
|
+
set_run_style nil, :vertAlign, v
|
|
174
|
+
end
|
|
158
175
|
|
|
159
176
|
# The inline scheme property for the cell
|
|
160
177
|
# this must be one of [:none, major, minor]
|
|
161
178
|
# @return [Symbol]
|
|
162
179
|
attr_reader :scheme
|
|
163
180
|
# @see scheme
|
|
164
|
-
def scheme=(v)
|
|
181
|
+
def scheme=(v)
|
|
182
|
+
RestrictionValidator.validate "Cell.schema", [:none, :major, :minor], v
|
|
183
|
+
set_run_style nil, :scheme, v
|
|
184
|
+
end
|
|
165
185
|
|
|
166
186
|
# @param [Row] row The row this cell belongs to.
|
|
167
|
-
# @param [Any] value The value associated with this cell.
|
|
187
|
+
# @param [Any] value The value associated with this cell.
|
|
168
188
|
# @option options [Symbol] type The intended data type for this cell. If not specified the data type will be determined internally based on the vlue provided.
|
|
169
189
|
# @option options [Integer] style The index of the cellXfs item to be applied to this cell. If not specified, the default style (0) will be applied.
|
|
170
190
|
# @option options [String] font_name
|
|
@@ -183,9 +203,11 @@ module Axlsx
|
|
|
183
203
|
# @option options [String] color an 8 letter rgb specification
|
|
184
204
|
# @option options [Symbol] scheme must be one of :none, major, :minor
|
|
185
205
|
def initialize(row, value="", options={})
|
|
186
|
-
self.row=row
|
|
206
|
+
self.row=row
|
|
207
|
+
@font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil
|
|
208
|
+
@condense = @u = @vertAlign = @sz = @color = @scheme = @extend = @ssti = nil
|
|
187
209
|
@styles = row.worksheet.workbook.styles
|
|
188
|
-
@row.cells << self
|
|
210
|
+
@row.cells << self
|
|
189
211
|
options.each do |o|
|
|
190
212
|
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
191
213
|
end
|
|
@@ -197,19 +219,14 @@ module Axlsx
|
|
|
197
219
|
# The Shared Strings Table index for this cell
|
|
198
220
|
# @return [Integer]
|
|
199
221
|
attr_reader :ssti
|
|
200
|
-
|
|
222
|
+
|
|
201
223
|
# equality comparison to test value, type and inline style attributes
|
|
202
224
|
# this is how we work out if the cell needs to be added or already exists in the shared strings table
|
|
203
|
-
def
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
v_hash = v.instance_values.reject { |k, v| !INLINE_STYLES.include?(k) }
|
|
207
|
-
self_hash = self.instance_values.reject { |k, v| !INLINE_STYLES.include?(k) }
|
|
208
|
-
# required as color is an object, and the comparison will fail even though both use the same color.
|
|
209
|
-
v_hash['color'] = v_hash['color'].instance_values if v_hash['color']
|
|
225
|
+
def shareable_hash
|
|
226
|
+
self_hash = {}
|
|
227
|
+
INLINE_STYLES.each { |style| self_hash[style] = self.instance_variable_get("@" + style) }
|
|
210
228
|
self_hash['color'] = self_hash['color'].instance_values if self_hash['color']
|
|
211
|
-
|
|
212
|
-
v_hash == self_hash
|
|
229
|
+
self_hash
|
|
213
230
|
end
|
|
214
231
|
|
|
215
232
|
# @return [Integer] The index of the cell in the containing row.
|
|
@@ -219,16 +236,17 @@ module Axlsx
|
|
|
219
236
|
|
|
220
237
|
# @return [String] The alpha(column)numeric(row) reference for this sell.
|
|
221
238
|
# @example Relative Cell Reference
|
|
222
|
-
# ws.rows.first.cells.first.r #=> "A1"
|
|
239
|
+
# ws.rows.first.cells.first.r #=> "A1"
|
|
240
|
+
# @note this will be discontinued in 1.1.0 - prefer Axlsx.cell_r
|
|
223
241
|
def r
|
|
224
|
-
"#{col_ref}#{@row.index+1}"
|
|
242
|
+
"#{Axlsx::col_ref(index)}#{@row.index+1}"
|
|
225
243
|
end
|
|
226
244
|
|
|
227
245
|
# @return [String] The absolute alpha(column)numeric(row) reference for this sell.
|
|
228
246
|
# @example Absolute Cell Reference
|
|
229
|
-
# ws.rows.first.cells.first.r #=> "$A$1"
|
|
247
|
+
# ws.rows.first.cells.first.r #=> "$A$1"
|
|
230
248
|
def r_abs
|
|
231
|
-
"$#{r.
|
|
249
|
+
"$#{r.match(%r{([A-Z]+)([0-9]+)})[1,2].join('$')}"
|
|
232
250
|
end
|
|
233
251
|
|
|
234
252
|
# @return [Integer] The cellXfs item index applied to this cell.
|
|
@@ -255,109 +273,102 @@ module Axlsx
|
|
|
255
273
|
target.r
|
|
256
274
|
end
|
|
257
275
|
self.row.worksheet.merge_cells "#{self.r}:#{range_end}" unless range_end.nil?
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
# builds an xml text run based on this cells attributes.
|
|
261
|
-
# @param [
|
|
262
|
-
# @return [String]
|
|
263
|
-
def
|
|
264
|
-
if
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
# :baseline, :subscript, :superscript
|
|
281
|
-
xml.vertAlign(:val=>@vertAlign) if @verAlign
|
|
282
|
-
# :none, major, :minor
|
|
283
|
-
xml.scheme(:val=>@scheme) if @scheme
|
|
284
|
-
}
|
|
285
|
-
xml.t @value.to_s
|
|
286
|
-
}
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# builds an xml text run based on this cells attributes.
|
|
279
|
+
# @param [String] str The string instance this run will be concated to.
|
|
280
|
+
# @return [String]
|
|
281
|
+
def run_xml_string(str = '')
|
|
282
|
+
if is_text_run?
|
|
283
|
+
data = self.instance_values.reject{|key, value| value == nil }
|
|
284
|
+
keys = data.keys & INLINE_STYLES
|
|
285
|
+
keys.delete ['value', 'type']
|
|
286
|
+
str << "<r><rPr>"
|
|
287
|
+
keys.each do |key|
|
|
288
|
+
case key
|
|
289
|
+
when 'font_name'
|
|
290
|
+
str << "<rFont val='"<< @font_name << "'/>"
|
|
291
|
+
when 'color'
|
|
292
|
+
str << data[key].to_xml_string
|
|
293
|
+
else
|
|
294
|
+
"<" << key.to_s << " val='" << data[key].to_s << "'/>"
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
str << "</rPr>" << "<t>" << value.to_s << "</t></r>"
|
|
287
298
|
else
|
|
288
|
-
|
|
289
|
-
end
|
|
299
|
+
str << "<t>" << value.to_s << "</t>"
|
|
300
|
+
end
|
|
301
|
+
str
|
|
290
302
|
end
|
|
291
303
|
|
|
292
304
|
# Serializes the cell
|
|
293
|
-
# @param [
|
|
305
|
+
# @param [Integer] r_index The row index for the cell
|
|
306
|
+
# @param [Integer] c_index The cell index in the row.
|
|
307
|
+
# @param [String] str The string index the cell content will be appended to. Defaults to empty string.
|
|
294
308
|
# @return [String] xml text for the cell
|
|
295
|
-
def
|
|
296
|
-
if @
|
|
309
|
+
def to_xml_string(r_index, c_index, str = '')
|
|
310
|
+
return str if @value.nil?
|
|
311
|
+
str << '<c r="' << Axlsx::cell_r(c_index, r_index) << '" s="' << @style.to_s << '" '
|
|
312
|
+
case @type
|
|
313
|
+
when :string
|
|
297
314
|
#parse formula
|
|
298
315
|
if @value.start_with?('=')
|
|
299
|
-
|
|
300
|
-
xml.f @value.to_s.gsub('=', '')
|
|
301
|
-
}
|
|
316
|
+
str << 't="str"><f>' << @value.to_s.gsub('=', '') << '</f>'
|
|
302
317
|
else
|
|
303
318
|
#parse shared
|
|
304
319
|
if @ssti
|
|
305
|
-
|
|
320
|
+
str << 't="s"><v>' << @ssti.to_s << '</v>'
|
|
306
321
|
else
|
|
307
|
-
|
|
308
|
-
xml.c(:r => r, :s=>style, :t => :inlineStr) {
|
|
309
|
-
xml.is {
|
|
310
|
-
run_xml(xml)
|
|
311
|
-
}
|
|
312
|
-
}
|
|
322
|
+
str << 't="inlineStr"><is>' << run_xml_string << '</is>'
|
|
313
323
|
end
|
|
314
324
|
end
|
|
315
|
-
|
|
316
|
-
#
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
325
|
+
when :date
|
|
326
|
+
# TODO: See if this is subject to the same restriction as Time below
|
|
327
|
+
str << '><v>' << DateTimeConverter::date_to_serial(@value).to_s << '</v>'
|
|
328
|
+
when :time
|
|
329
|
+
str << '><v>' << DateTimeConverter::time_to_serial(@value).to_s << '</v>'
|
|
330
|
+
when :boolean
|
|
331
|
+
str << 't="b"><v>' << @value.to_s << '</v>'
|
|
322
332
|
else
|
|
323
|
-
|
|
333
|
+
str << '><v>' << @value.to_s << '</v>'
|
|
324
334
|
end
|
|
335
|
+
str << '</c>'
|
|
325
336
|
end
|
|
326
337
|
|
|
327
|
-
private
|
|
338
|
+
private
|
|
339
|
+
|
|
340
|
+
# Utility method for setting inline style attributes
|
|
341
|
+
def set_run_style( validator, attr, value)
|
|
342
|
+
return unless INLINE_STYLES.include?(attr.to_s)
|
|
343
|
+
Axlsx.send(validator, value) unless validator == nil
|
|
344
|
+
self.instance_variable_set :"@#{attr.to_s}", value
|
|
345
|
+
@is_text_run = true
|
|
346
|
+
end
|
|
328
347
|
|
|
329
348
|
# @see ssti
|
|
330
|
-
def ssti=(v)
|
|
349
|
+
def ssti=(v)
|
|
331
350
|
Axlsx::validate_unsigned_int(v)
|
|
332
351
|
@ssti = v
|
|
333
352
|
end
|
|
334
353
|
|
|
335
354
|
# assigns the owning row for this cell.
|
|
336
355
|
def row=(v) DataTypeValidator.validate "Cell.row", Row, v; @row=v end
|
|
337
|
-
|
|
338
|
-
# converts the column index into alphabetical values.
|
|
339
|
-
# @note This follows the standard spreadsheet convention of naming columns A to Z, followed by AA to AZ etc.
|
|
340
|
-
# @return [String]
|
|
341
|
-
def col_ref
|
|
342
|
-
chars = []
|
|
343
|
-
index = self.index
|
|
344
|
-
while index >= 26 do
|
|
345
|
-
chars << ((index % 26) + 65).chr
|
|
346
|
-
index /= 26
|
|
347
|
-
end
|
|
348
|
-
chars << ((chars.empty? ? index : index-1) + 65).chr
|
|
349
|
-
chars.reverse.join
|
|
350
|
-
end
|
|
351
356
|
|
|
352
|
-
# Determines the cell type based on the cell value.
|
|
357
|
+
# Determines the cell type based on the cell value.
|
|
353
358
|
# @note This is only used when a cell is created but no :type option is specified, the following rules apply:
|
|
354
|
-
# 1. If the value is an instance of
|
|
355
|
-
# 2.
|
|
356
|
-
# 3.
|
|
359
|
+
# 1. If the value is an instance of Date, the type is set to :date
|
|
360
|
+
# 2. If the value is an instance of Time, the type is set to :time
|
|
361
|
+
# 3. If the value is an instance of TrueClass or FalseClass, the type is set to :boolean
|
|
362
|
+
# 4. :float and :integer types are determined by regular expression matching.
|
|
363
|
+
# 5. Anything that does not meet either of the above is determined to be :string.
|
|
357
364
|
# @return [Symbol] The determined type
|
|
358
|
-
def cell_type_from_value(v)
|
|
359
|
-
if v.is_a?
|
|
365
|
+
def cell_type_from_value(v)
|
|
366
|
+
if v.is_a?(Date)
|
|
367
|
+
:date
|
|
368
|
+
elsif v.is_a?(Time)
|
|
360
369
|
:time
|
|
370
|
+
elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
|
371
|
+
:boolean
|
|
361
372
|
elsif v.to_s.match(/\A[+-]?\d+?\Z/) #numeric
|
|
362
373
|
:integer
|
|
363
374
|
elsif v.to_s.match(/\A[+-]?\d+\.\d+?\Z/) #float
|
|
@@ -367,22 +378,28 @@ module Axlsx
|
|
|
367
378
|
end
|
|
368
379
|
end
|
|
369
380
|
|
|
370
|
-
# Cast the value into this cells data type.
|
|
371
|
-
# @note
|
|
381
|
+
# Cast the value into this cells data type.
|
|
382
|
+
# @note
|
|
372
383
|
# About Time - Time in OOXML is *different* from what you might expect. The history as to why is interesting, but you can safely assume that if you are generating docs on a mac, you will want to specify Workbook.1904 as true when using time typed values.
|
|
373
384
|
# @see Axlsx#date1904
|
|
374
385
|
def cast_value(v)
|
|
375
|
-
|
|
386
|
+
return nil if v.nil?
|
|
387
|
+
if @type == :date
|
|
388
|
+
self.style = STYLE_DATE if self.style == 0
|
|
389
|
+
v
|
|
390
|
+
elsif (@type == :time && v.is_a?(Time)) || (@type == :time && v.respond_to?(:to_time))
|
|
376
391
|
self.style = STYLE_DATE if self.style == 0
|
|
377
392
|
v.respond_to?(:to_time) ? v.to_time : v
|
|
378
393
|
elsif @type == :float
|
|
379
394
|
v.to_f
|
|
380
395
|
elsif @type == :integer
|
|
381
396
|
v.to_i
|
|
397
|
+
elsif @type == :boolean
|
|
398
|
+
v ? 1 : 0
|
|
382
399
|
else
|
|
383
400
|
@type = :string
|
|
384
|
-
v.to_s
|
|
401
|
+
::CGI.escapeHTML(v.to_s)
|
|
385
402
|
end
|
|
386
|
-
end
|
|
403
|
+
end
|
|
387
404
|
end
|
|
388
405
|
end
|
|
@@ -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
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require "date"
|
|
3
|
+
|
|
4
|
+
module Axlsx
|
|
5
|
+
# The DateTimeConverter class converts both data and time types to their apprpriate excel serializations
|
|
6
|
+
class DateTimeConverter
|
|
7
|
+
|
|
8
|
+
# The date_to_serial method converts Date objects to the equivelant excel serialized forms
|
|
9
|
+
# @param [Date] date the date to be serialized
|
|
10
|
+
# @return [Numeric]
|
|
11
|
+
def self.date_to_serial(date)
|
|
12
|
+
epoch = Axlsx::Workbook::date1904 ? Date.new(1904) : Date.new(1899, 12, 30)
|
|
13
|
+
(date-epoch).to_f
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# The time_to_serial methond converts a Time object its excel serialized form.
|
|
17
|
+
# @param [Time] time the time to be serialized
|
|
18
|
+
# @return [Numeric]
|
|
19
|
+
def self.time_to_serial(time)
|
|
20
|
+
# Using hardcoded offsets here as some operating systems will not except
|
|
21
|
+
# a 'negative' offset from the ruby epoch.
|
|
22
|
+
epoch1900 = -2209161600 # Time.utc(1899, 12, 30).to_i
|
|
23
|
+
epoch1904 = -2082844800 # Time.utc(1904, 1, 1).to_i
|
|
24
|
+
seconds_per_day = 86400 # 60*60*24
|
|
25
|
+
epoch = Axlsx::Workbook::date1904 ? epoch1904 : epoch1900
|
|
26
|
+
(time.to_f - epoch)/seconds_per_day
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|