axlsx 1.0.11 → 1.0.12
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +4 -0
- data/README.md +7 -4
- data/examples/example.rb +6 -4
- data/examples/example.rb~ +112 -0
- data/lib/schema/dc.xsd~ +118 -0
- data/lib/schema/dcterms.xsd~ +331 -0
- data/lib/schema/opc-coreProperties.xsd~ +50 -0
- metadata +43 -193
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -29
- data/axlsx.gemspec +0 -42
- data/doc/Axlsx.html +0 -2718
- data/doc/Axlsx/App.html +0 -2640
- data/doc/Axlsx/Axis.html +0 -1075
- data/doc/Axlsx/Bar3DChart.html +0 -1182
- data/doc/Axlsx/BarSeries.html +0 -711
- data/doc/Axlsx/Border.html +0 -779
- data/doc/Axlsx/BorderPr.html +0 -709
- data/doc/Axlsx/CatAxis.html +0 -769
- data/doc/Axlsx/CatAxisData.html +0 -397
- data/doc/Axlsx/Cell.html +0 -3187
- data/doc/Axlsx/CellAlignment.html +0 -1247
- data/doc/Axlsx/CellProtection.html +0 -565
- data/doc/Axlsx/CellStyle.html +0 -949
- data/doc/Axlsx/Chart.html +0 -1692
- data/doc/Axlsx/Color.html +0 -670
- data/doc/Axlsx/ContentType.html +0 -335
- data/doc/Axlsx/Core.html +0 -465
- data/doc/Axlsx/DataTypeValidator.html +0 -324
- data/doc/Axlsx/Default.html +0 -565
- data/doc/Axlsx/Drawing.html +0 -1264
- data/doc/Axlsx/Fill.html +0 -460
- data/doc/Axlsx/Font.html +0 -1554
- data/doc/Axlsx/GradientFill.html +0 -1026
- data/doc/Axlsx/GradientStop.html +0 -526
- data/doc/Axlsx/GraphicFrame.html +0 -642
- data/doc/Axlsx/Line3DChart.html +0 -1004
- data/doc/Axlsx/LineSeries.html +0 -605
- data/doc/Axlsx/Marker.html +0 -857
- data/doc/Axlsx/NumFmt.html +0 -562
- data/doc/Axlsx/OneCellAnchor.html +0 -982
- data/doc/Axlsx/Override.html +0 -552
- data/doc/Axlsx/Package.html +0 -825
- data/doc/Axlsx/Parser.html +0 -549
- data/doc/Axlsx/PatternFill.html +0 -681
- data/doc/Axlsx/Pic.html +0 -1701
- data/doc/Axlsx/PictureLocking.html +0 -1159
- data/doc/Axlsx/Pie3DChart.html +0 -489
- data/doc/Axlsx/PieSeries.html +0 -710
- data/doc/Axlsx/RegexValidator.html +0 -268
- data/doc/Axlsx/Relationship.html +0 -554
- data/doc/Axlsx/Relationships.html +0 -338
- data/doc/Axlsx/RestrictionValidator.html +0 -300
- data/doc/Axlsx/Row.html +0 -916
- data/doc/Axlsx/Scaling.html +0 -742
- data/doc/Axlsx/SerAxis.html +0 -641
- data/doc/Axlsx/Series.html +0 -813
- data/doc/Axlsx/SeriesTitle.html +0 -290
- data/doc/Axlsx/Styles.html +0 -1754
- data/doc/Axlsx/TableStyle.html +0 -705
- data/doc/Axlsx/TableStyleElement.html +0 -677
- data/doc/Axlsx/TableStyles.html +0 -594
- data/doc/Axlsx/Title.html +0 -543
- data/doc/Axlsx/TwoCellAnchor.html +0 -973
- data/doc/Axlsx/ValAxis.html +0 -538
- data/doc/Axlsx/ValAxisData.html +0 -321
- data/doc/Axlsx/View3D.html +0 -973
- data/doc/Axlsx/Workbook.html +0 -1630
- data/doc/Axlsx/Worksheet.html +0 -2682
- data/doc/Axlsx/Xf.html +0 -1780
- data/doc/_index.html +0 -649
- data/doc/class_list.html +0 -47
- data/doc/css/common.css +0 -1
- data/doc/css/full_list.css +0 -55
- data/doc/css/style.css +0 -322
- data/doc/file.LICENSE.html +0 -91
- data/doc/file.README.html +0 -338
- data/doc/file_list.html +0 -52
- data/doc/frames.html +0 -13
- data/doc/index.html +0 -338
- data/doc/js/app.js +0 -205
- data/doc/js/full_list.js +0 -167
- data/doc/js/jquery.js +0 -16
- data/doc/method_list.html +0 -3502
- data/doc/top-level-namespace.html +0 -103
- data/lib/axlsx.rb +0 -54
- data/lib/axlsx/content_type/content_type.rb +0 -23
- data/lib/axlsx/content_type/default.rb +0 -37
- data/lib/axlsx/content_type/override.rb +0 -37
- data/lib/axlsx/doc_props/app.rb +0 -178
- data/lib/axlsx/doc_props/core.rb +0 -34
- data/lib/axlsx/drawing/axis.rb +0 -90
- data/lib/axlsx/drawing/bar_3D_chart.rb +0 -128
- data/lib/axlsx/drawing/bar_series.rb +0 -64
- data/lib/axlsx/drawing/cat_axis.rb +0 -63
- data/lib/axlsx/drawing/cat_axis_data.rb +0 -35
- data/lib/axlsx/drawing/chart.rb +0 -179
- data/lib/axlsx/drawing/drawing.rb +0 -137
- data/lib/axlsx/drawing/graphic_frame.rb +0 -52
- data/lib/axlsx/drawing/line_3D_chart.rb +0 -106
- data/lib/axlsx/drawing/line_series.rb +0 -46
- data/lib/axlsx/drawing/marker.rb +0 -61
- data/lib/axlsx/drawing/one_cell_anchor.rb +0 -89
- data/lib/axlsx/drawing/pic.rb +0 -153
- data/lib/axlsx/drawing/picture_locking.rb +0 -72
- data/lib/axlsx/drawing/pie_3D_chart.rb +0 -41
- data/lib/axlsx/drawing/pie_series.rb +0 -56
- data/lib/axlsx/drawing/scaling.rb +0 -59
- data/lib/axlsx/drawing/ser_axis.rb +0 -45
- data/lib/axlsx/drawing/series.rb +0 -71
- data/lib/axlsx/drawing/series_title.rb +0 -22
- data/lib/axlsx/drawing/title.rb +0 -61
- data/lib/axlsx/drawing/two_cell_anchor.rb +0 -76
- data/lib/axlsx/drawing/val_axis.rb +0 -34
- data/lib/axlsx/drawing/val_axis_data.rb +0 -28
- data/lib/axlsx/drawing/view_3D.rb +0 -85
- data/lib/axlsx/package.rb +0 -214
- data/lib/axlsx/rels/relationship.rb +0 -44
- data/lib/axlsx/rels/relationships.rb +0 -25
- data/lib/axlsx/stylesheet/border.rb +0 -57
- data/lib/axlsx/stylesheet/border_pr.rb +0 -68
- data/lib/axlsx/stylesheet/cell_alignment.rb +0 -105
- data/lib/axlsx/stylesheet/cell_protection.rb +0 -36
- data/lib/axlsx/stylesheet/cell_style.rb +0 -65
- data/lib/axlsx/stylesheet/color.rb +0 -69
- data/lib/axlsx/stylesheet/fill.rb +0 -32
- data/lib/axlsx/stylesheet/font.rb +0 -139
- data/lib/axlsx/stylesheet/gradient_fill.rb +0 -76
- data/lib/axlsx/stylesheet/gradient_stop.rb +0 -33
- data/lib/axlsx/stylesheet/num_fmt.rb +0 -63
- data/lib/axlsx/stylesheet/pattern_fill.rb +0 -66
- data/lib/axlsx/stylesheet/styles.rb +0 -298
- data/lib/axlsx/stylesheet/table_style.rb +0 -47
- data/lib/axlsx/stylesheet/table_style_element.rb +0 -71
- data/lib/axlsx/stylesheet/table_styles.rb +0 -39
- data/lib/axlsx/stylesheet/xf.rb +0 -138
- data/lib/axlsx/util/constants.rb +0 -216
- data/lib/axlsx/util/parser.rb +0 -43
- data/lib/axlsx/util/simple_typed_list.rb +0 -160
- data/lib/axlsx/util/validators.rb +0 -132
- data/lib/axlsx/version.rb +0 -4
- data/lib/axlsx/workbook/workbook.rb +0 -160
- data/lib/axlsx/workbook/worksheet/cell.rb +0 -340
- data/lib/axlsx/workbook/worksheet/row.rb +0 -107
- data/lib/axlsx/workbook/worksheet/worksheet.rb +0 -278
@@ -1,340 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
module Axlsx
|
3
|
-
# A cell in a worksheet.
|
4
|
-
# 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
|
-
# @example Manually creating and manipulating Cell objects
|
6
|
-
# ws = Workbook.new.add_worksheet
|
7
|
-
# # This is the simple, and recommended way to create cells. Data types will automatically be determined for you.
|
8
|
-
# ws.add_row :values => [1,"fish",Time.now]
|
9
|
-
#
|
10
|
-
# # but you can also do this
|
11
|
-
# r = ws.add_row
|
12
|
-
# r.add_cell 1
|
13
|
-
#
|
14
|
-
# # or even this
|
15
|
-
# r = ws.add_row
|
16
|
-
# c = Cell.new row, 1, :value=>integer
|
17
|
-
#
|
18
|
-
# # 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
|
-
# r.cells.last.type = :float
|
20
|
-
#
|
21
|
-
# @note The recommended way to generate cells is via Worksheet#add_row
|
22
|
-
#
|
23
|
-
# @see Worksheet#add_row
|
24
|
-
class Cell
|
25
|
-
|
26
|
-
# The index of the cellXfs item to be applied to this cell.
|
27
|
-
# @return [Integer]
|
28
|
-
# @see Axlsx::Styles
|
29
|
-
attr_reader :style
|
30
|
-
|
31
|
-
# The row this cell belongs to.
|
32
|
-
# @return [Row]
|
33
|
-
attr_reader :row
|
34
|
-
|
35
|
-
# The cell's data type. Currently only four types are supported, :time, :float, :integer and :string.
|
36
|
-
# 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
|
37
|
-
# automatically determed.
|
38
|
-
# @see Cell#cell_type_from_value
|
39
|
-
# @return [Symbol] The type of data this cell's value is cast to.
|
40
|
-
# @raise [ArgumentExeption] Cell.type must be one of [:time, :float, :integer, :string]
|
41
|
-
# @note
|
42
|
-
# If the value provided cannot be cast into the type specified, type is changed to :string and the following logic is applied.
|
43
|
-
# :string to :integer or :float, type coversions always return 0 or 0.0
|
44
|
-
# :string, :integer, or :float to :time conversions always return the original value as a string and set the cells type to :string.
|
45
|
-
# No support is currently implemented for parsing time strings.
|
46
|
-
attr_reader :type
|
47
|
-
# @see type
|
48
|
-
def type=(v)
|
49
|
-
RestrictionValidator.validate "Cell.type", [:time, :float, :integer, :string], v
|
50
|
-
@type=v
|
51
|
-
self.value = @value
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
# The value of this cell.
|
56
|
-
# @return [String, Integer, Float, Time] casted value based on cell's type attribute.
|
57
|
-
attr_reader :value
|
58
|
-
# @see value
|
59
|
-
def value=(v)
|
60
|
-
#TODO: consider doing value based type determination first?
|
61
|
-
@value = cast_value(v)
|
62
|
-
end
|
63
|
-
|
64
|
-
# The inline font_name property for the cell
|
65
|
-
# @return [String]
|
66
|
-
attr_reader :font_name
|
67
|
-
# @see font_name
|
68
|
-
def font_name=(v) Axlsx::validate_string(v); @font_name = v; end
|
69
|
-
|
70
|
-
# The inline charset property for the cell
|
71
|
-
# @return [String]
|
72
|
-
attr_reader :charset
|
73
|
-
# @see charset
|
74
|
-
def charset=(v) Axlsx::validate_unsigned_int(v); @charset = v; end
|
75
|
-
|
76
|
-
# The inline family property for the cell
|
77
|
-
# @return [String]
|
78
|
-
attr_reader :family
|
79
|
-
# @see family
|
80
|
-
def family=(v) Axlsx::validate_string(v); @family = v; end
|
81
|
-
|
82
|
-
# The inline bold property for the cell
|
83
|
-
# @return [Boolean]
|
84
|
-
attr_reader :b
|
85
|
-
# @see b
|
86
|
-
def b=(v) Axlsx::validate_boolean(v); @b = v; end
|
87
|
-
|
88
|
-
# The inline italic property for the cell
|
89
|
-
# @return [Boolean]
|
90
|
-
attr_reader :i
|
91
|
-
# @see i
|
92
|
-
def i=(v) Axlsx::validate_boolean(v); @i = v; end
|
93
|
-
|
94
|
-
# The inline strike property for the cell
|
95
|
-
# @return [Boolean]
|
96
|
-
attr_reader :strike
|
97
|
-
# @see strike
|
98
|
-
def strike=(v) Axlsx::validate_boolean(v); @strike = v; end
|
99
|
-
|
100
|
-
# The inline outline property for the cell
|
101
|
-
# @return [Boolean]
|
102
|
-
attr_reader :outline
|
103
|
-
# @see outline
|
104
|
-
def outline=(v) Axlsx::validate_boolean(v); @outline = v; end
|
105
|
-
|
106
|
-
# The inline shadow property for the cell
|
107
|
-
# @return [Boolean]
|
108
|
-
attr_reader :shadow
|
109
|
-
# @see shadow
|
110
|
-
def shadow=(v) Axlsx::validate_boolean(v); @shadow = v; end
|
111
|
-
|
112
|
-
# The inline condense property for the cell
|
113
|
-
# @return [Boolean]
|
114
|
-
attr_reader :condense
|
115
|
-
# @see condense
|
116
|
-
def condense=(v) Axlsx::validate_boolean(v); @condense = v; end
|
117
|
-
|
118
|
-
# The inline extend property for the cell
|
119
|
-
# @return [Boolean]
|
120
|
-
attr_reader :extend
|
121
|
-
# @see extend
|
122
|
-
def extend=(v) Axlsx::validate_boolean(v); @extend = v; end
|
123
|
-
|
124
|
-
# The inline underline property for the cell
|
125
|
-
# @return [Boolean]
|
126
|
-
attr_reader :u
|
127
|
-
# @see u
|
128
|
-
def u=(v) Axlsx::validate_boolean(v); @u = v; end
|
129
|
-
|
130
|
-
# The inline color property for the cell
|
131
|
-
# @return [Color]
|
132
|
-
attr_reader :color
|
133
|
-
# @param [String] The 8 character representation for an rgb color #FFFFFFFF"
|
134
|
-
def color=(v)
|
135
|
-
@color = v.is_a?(Color) ? v : Color.new(:rgb=>v)
|
136
|
-
end
|
137
|
-
|
138
|
-
# The inline sz property for the cell
|
139
|
-
# @return [Boolean]
|
140
|
-
attr_reader :sz
|
141
|
-
# @see sz
|
142
|
-
def sz=(v) Axlsx::validate_unsigned_int(v); @sz = v; end
|
143
|
-
|
144
|
-
# The inline vertical alignment property for the cell
|
145
|
-
# this must be one of [:baseline, :subscript, :superscript]
|
146
|
-
# @return [Symbol]
|
147
|
-
attr_reader :vertAlign
|
148
|
-
# @see vertAlign
|
149
|
-
def vertAlign=(v) RestrictionValidator.validate "Cell.vertAlign", [:baseline, :subscript, :superscript], v; @vertAlign = v; end
|
150
|
-
|
151
|
-
# The inline scheme property for the cell
|
152
|
-
# this must be one of [:none, major, minor]
|
153
|
-
# @return [Symbol]
|
154
|
-
attr_reader :scheme
|
155
|
-
# @see scheme
|
156
|
-
def scheme=(v) RestrictionValidator.validate "Cell.schema", [:none, :major, :minor], v; @scheme = v; end
|
157
|
-
|
158
|
-
# @param [Row] row The row this cell belongs to.
|
159
|
-
# @param [Any] value The value associated with this cell.
|
160
|
-
# @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.
|
161
|
-
# @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.
|
162
|
-
# @option options [String] font_name
|
163
|
-
# @option options [Integer] charset
|
164
|
-
# @option options [String] family
|
165
|
-
# @option options [Boolean] b
|
166
|
-
# @option options [Boolean] i
|
167
|
-
# @option options [Boolean] strike
|
168
|
-
# @option options [Boolean] outline
|
169
|
-
# @option options [Boolean] shadow
|
170
|
-
# @option options [Boolean] condense
|
171
|
-
# @option options [Boolean] extend
|
172
|
-
# @option options [Boolean] u
|
173
|
-
# @option options [Symbol] vertAlign must be one of :baseline, :subscript, :superscript
|
174
|
-
# @option options [Integer] sz
|
175
|
-
# @option options [String] color an 8 letter rgb specification
|
176
|
-
# @option options [Symbol] scheme must be one of :none, major, :minor
|
177
|
-
def initialize(row, value="", options={})
|
178
|
-
self.row=row
|
179
|
-
@styles = row.worksheet.workbook.styles
|
180
|
-
@style = 0
|
181
|
-
@type = cell_type_from_value(value)
|
182
|
-
@row.cells << self
|
183
|
-
options.each do |o|
|
184
|
-
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
185
|
-
end
|
186
|
-
@value = cast_value(value)
|
187
|
-
end
|
188
|
-
|
189
|
-
# @return [Integer] The index of the cell in the containing row.
|
190
|
-
def index
|
191
|
-
@row.cells.index(self)
|
192
|
-
end
|
193
|
-
|
194
|
-
# @return [String] The alpha(column)numeric(row) reference for this sell.
|
195
|
-
# @example Relative Cell Reference
|
196
|
-
# ws.rows.first.cells.first.r #=> "A1"
|
197
|
-
def r
|
198
|
-
"#{col_ref}#{@row.index+1}"
|
199
|
-
end
|
200
|
-
|
201
|
-
# @return [String] The absolute alpha(column)numeric(row) reference for this sell.
|
202
|
-
# @example Absolute Cell Reference
|
203
|
-
# ws.rows.first.cells.first.r #=> "$A$1"
|
204
|
-
def r_abs
|
205
|
-
"$#{r.split('').join('$')}"
|
206
|
-
end
|
207
|
-
|
208
|
-
# @return [Integer] The cellXfs item index applied to this cell.
|
209
|
-
# @raise [ArgumentError] Invalid cellXfs id if the value provided is not within cellXfs items range.
|
210
|
-
def style=(v)
|
211
|
-
Axlsx::validate_unsigned_int(v)
|
212
|
-
count = @styles.cellXfs.size
|
213
|
-
raise ArgumentError, "Invalid cellXfs id" unless v < count
|
214
|
-
@style = v
|
215
|
-
end
|
216
|
-
|
217
|
-
# @return [Array] of x/y coordinates in the cheet for this cell.
|
218
|
-
def pos
|
219
|
-
[index, row.index]
|
220
|
-
end
|
221
|
-
|
222
|
-
# Serializes the cell
|
223
|
-
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
224
|
-
# @return [String] xml text for the cell
|
225
|
-
# @note
|
226
|
-
# Shared Strings are not used in this library. All values are set directly in the each sheet.
|
227
|
-
def to_xml(xml)
|
228
|
-
# Both 1.8 and 1.9 return the same 'fast_xf'
|
229
|
-
# ニホンゴ
|
230
|
-
# ニホンゴ
|
231
|
-
|
232
|
-
# however nokogiri does a nice 'force_encoding' which we shall remove!
|
233
|
-
if @type == :string
|
234
|
-
#parse formula
|
235
|
-
if @value.start_with?('=')
|
236
|
-
xml.c(:r => r, :s=>style) {
|
237
|
-
xml.f @value.to_s.gsub('=', '')
|
238
|
-
}
|
239
|
-
else
|
240
|
-
#parse standard string
|
241
|
-
#xml.c(:r => r, :t=>:inlineStr, :s=>style) {
|
242
|
-
# xml.is { xml.t @value.to_s }
|
243
|
-
#}
|
244
|
-
#parse styled string
|
245
|
-
xml.c(:r => r, :s=>style) {
|
246
|
-
xml.is {
|
247
|
-
xml.r {
|
248
|
-
xml.rPr {
|
249
|
-
xml.rFont(:val=>@font_name) if @font_name
|
250
|
-
xml.charset(:val=>@charset) if @charset
|
251
|
-
xml.family(:val=>@family) if @family
|
252
|
-
xml.b(:val=>@b) if @b
|
253
|
-
xml.i(:val=>@i) if @i
|
254
|
-
xml.strike(:val=>@strike) if @strike
|
255
|
-
xml.outline(:val=>@outline) if @outline
|
256
|
-
xml.shadow(:val=>@shadow) if @shadow
|
257
|
-
xml.condense(:val=>@condense) if @condense
|
258
|
-
xml.extend(:val=>@extend) if @extend
|
259
|
-
@color.to_xml(xml) if @color
|
260
|
-
xml.sz(:val=>@sz) if @sz
|
261
|
-
xml.u(:val=>@u) if @u
|
262
|
-
# :baseline, :subscript, :superscript
|
263
|
-
xml.vertAlign(:val=>@vertAlign) if @verAlign
|
264
|
-
# :none, major, :minor
|
265
|
-
xml.scheme(:val=>@scheme) if @scheme
|
266
|
-
}
|
267
|
-
xml.t @value.to_s
|
268
|
-
}
|
269
|
-
}
|
270
|
-
}
|
271
|
-
end
|
272
|
-
|
273
|
-
else
|
274
|
-
xml.c(:r => r, :s => style) { xml.v value }
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
|
279
|
-
private
|
280
|
-
|
281
|
-
# assigns the owning row for this cell.
|
282
|
-
def row=(v) DataTypeValidator.validate "Cell.row", Row, v; @row=v end
|
283
|
-
|
284
|
-
# converts the column index into alphabetical values.
|
285
|
-
# @note This follows the standard spreadsheet convention of naming columns A to Z, followed by AA to AZ etc.
|
286
|
-
# @return [String]
|
287
|
-
def col_ref
|
288
|
-
chars = []
|
289
|
-
index = self.index
|
290
|
-
while index >= 26 do
|
291
|
-
chars << ((index % 26) + 65).chr
|
292
|
-
index /= 26
|
293
|
-
end
|
294
|
-
chars << ((chars.empty? ? index : index-1) + 65).chr
|
295
|
-
chars.reverse.join
|
296
|
-
end
|
297
|
-
|
298
|
-
# Determines the cell type based on the cell value.
|
299
|
-
# @note This is only used when a cell is created but no :type option is specified, the following rules apply:
|
300
|
-
# 1. If the value is an instance of Time, the type is set to :time
|
301
|
-
# 2. :float and :integer types are determined by regular expression matching.
|
302
|
-
# 3. Anything that does not meet either of the above is determined to be :string.
|
303
|
-
# @return [Symbol] The determined type
|
304
|
-
def cell_type_from_value(v)
|
305
|
-
if v.is_a? Time
|
306
|
-
:time
|
307
|
-
elsif v.to_s.match(/\A[+-]?\d+?\Z/) #numeric
|
308
|
-
:integer
|
309
|
-
elsif v.to_s.match(/\A[+-]?\d+\.\d+?\Z/) #float
|
310
|
-
:float
|
311
|
-
else
|
312
|
-
:string
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
# Cast the value into this cells data type.
|
317
|
-
# @note
|
318
|
-
# 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.
|
319
|
-
# @see Axlsx#date1904
|
320
|
-
def cast_value(v)
|
321
|
-
if (@type == :time && v.is_a?(Time)) || (@type == :time && v.respond_to?(:to_time))
|
322
|
-
v = v.respond_to?(:to_time) ? v.to_time : v
|
323
|
-
self.style = STYLE_DATE if self.style == 0
|
324
|
-
# Using hardcoded offsets here as some operating systems will not except a 'negative' offset from the ruby epoc.
|
325
|
-
# (1970)
|
326
|
-
epoc1900 = -2209021200 #Time.local(1900, 1, 1)
|
327
|
-
epoc1904 = -2082877200 #Time.local(1904, 1, 1)
|
328
|
-
epoc = Workbook.date1904 ? epoc1904 : epoc1900
|
329
|
-
((v.localtime.to_f - epoc) /60.0/60.0/24.0).to_f
|
330
|
-
elsif @type == :float
|
331
|
-
v.to_f
|
332
|
-
elsif @type == :integer
|
333
|
-
v.to_i
|
334
|
-
else
|
335
|
-
@type = :string
|
336
|
-
v.to_s
|
337
|
-
end
|
338
|
-
end
|
339
|
-
end
|
340
|
-
end
|
@@ -1,107 +0,0 @@
|
|
1
|
-
module Axlsx
|
2
|
-
# A Row is a single row in a worksheet.
|
3
|
-
# @note The recommended way to manage rows and cells is to use Worksheet#add_row
|
4
|
-
# @see Worksheet#add_row
|
5
|
-
class Row
|
6
|
-
|
7
|
-
# The worksheet this row belongs to
|
8
|
-
# @return [Worksheet]
|
9
|
-
attr_reader :worksheet
|
10
|
-
|
11
|
-
# The cells this row holds
|
12
|
-
# @return [SimpleTypedList]
|
13
|
-
attr_reader :cells
|
14
|
-
|
15
|
-
# Creates a new row. New Cell objects are created based on the values, types and style options.
|
16
|
-
# A new cell is created for each item in the values array. style and types options are applied as follows:
|
17
|
-
# If the types option is defined and is a symbol it is applied to all the cells created.
|
18
|
-
# If the types option is an array, cell types are applied by index for each cell
|
19
|
-
# If the types option is not set, the cell will automatically determine its type.
|
20
|
-
# If the style option is defined and is an Integer, it is applied to all cells created.
|
21
|
-
# If the style option is an array, style is applied by index for each cell.
|
22
|
-
# If the style option is not defined, the default style (0) is applied to each cell.
|
23
|
-
# @param [Worksheet] worksheet
|
24
|
-
# @option options [Array] values
|
25
|
-
# @option options [Array, Symbol] types
|
26
|
-
# @option options [Array, Integer] style
|
27
|
-
# @see Row#array_to_cells
|
28
|
-
# @see Cell
|
29
|
-
def initialize(worksheet, values=[], options={})
|
30
|
-
self.worksheet = worksheet
|
31
|
-
@cells = SimpleTypedList.new Cell
|
32
|
-
@worksheet.rows << self
|
33
|
-
array_to_cells(values, options)
|
34
|
-
end
|
35
|
-
|
36
|
-
# The index of this row in the worksheet
|
37
|
-
# @return [Integer]
|
38
|
-
def index
|
39
|
-
worksheet.rows.index(self)
|
40
|
-
end
|
41
|
-
|
42
|
-
# Serializes the row
|
43
|
-
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
44
|
-
# @return [String]
|
45
|
-
def to_xml(xml)
|
46
|
-
xml.row(:r => index+1) { @cells.each { |cell| cell.to_xml(xml) } }
|
47
|
-
end
|
48
|
-
|
49
|
-
# Adds a singel sell to the row based on the data provided and updates the worksheet's autofit data.
|
50
|
-
# @return [Cell]
|
51
|
-
def add_cell(value="", options={})
|
52
|
-
c = Cell.new(self, value, options)
|
53
|
-
update_auto_fit_data
|
54
|
-
c
|
55
|
-
end
|
56
|
-
|
57
|
-
# sets the style for every cell in this row
|
58
|
-
def style=(style)
|
59
|
-
cells.each_with_index do | cell, index |
|
60
|
-
s = style.is_a?(Array) ? style[index] : style
|
61
|
-
cell.style = s
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# returns the cells in this row as an array
|
66
|
-
# This lets us transpose the rows into columns
|
67
|
-
# @return [Array]
|
68
|
-
def to_ary
|
69
|
-
@cells.to_ary
|
70
|
-
end
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
# assigns the owning worksheet for this row
|
75
|
-
def worksheet=(v) DataTypeValidator.validate "Row.worksheet", Worksheet, v; @worksheet=v; end
|
76
|
-
|
77
|
-
# Tell the worksheet to update autofit data for the columns based on this row's cells.
|
78
|
-
# @return [SimpleTypedList]
|
79
|
-
def update_auto_fit_data
|
80
|
-
worksheet.send(:update_auto_fit_data, self.cells)
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
|
-
# Converts values, types, and style options into cells and associates them with this row.
|
85
|
-
# A new cell is created for each item in the values array.
|
86
|
-
# If value option is defined and is a symbol it is applied to all the cells created.
|
87
|
-
# If the value option is an array, cell types are applied by index for each cell
|
88
|
-
# If the style option is defined and is an Integer, it is applied to all cells created.
|
89
|
-
# If the style option is an array, style is applied by index for each cell.
|
90
|
-
# @option options [Array] values
|
91
|
-
# @option options [Array, Symbol] types
|
92
|
-
# @option options [Array, Integer] style
|
93
|
-
def array_to_cells(values, options={})
|
94
|
-
values = values
|
95
|
-
DataTypeValidator.validate 'Row.array_to_cells', Array, values
|
96
|
-
types, style = options.delete(:types), options.delete(:style)
|
97
|
-
values.each_with_index do |value, index|
|
98
|
-
cell_style = style.is_a?(Array) ? style[index] : style
|
99
|
-
options[:style] = cell_style if cell_style
|
100
|
-
cell_type = types.is_a?(Array)? types[index] : types
|
101
|
-
options[:type] = cell_type if cell_type
|
102
|
-
Cell.new(self, value, options)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
end
|
@@ -1,278 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
module Axlsx
|
3
|
-
|
4
|
-
# The Worksheet class represents a worksheet in the workbook.
|
5
|
-
class Worksheet
|
6
|
-
|
7
|
-
# The name of the worksheet
|
8
|
-
# @return [String]
|
9
|
-
attr_reader :name
|
10
|
-
|
11
|
-
# The workbook that owns this worksheet
|
12
|
-
# @return [Workbook]
|
13
|
-
attr_reader :workbook
|
14
|
-
|
15
|
-
|
16
|
-
# The rows in this worksheet
|
17
|
-
# @note The recommended way to manage rows is Worksheet#add_row
|
18
|
-
# @return [SimpleTypedList]
|
19
|
-
# @see Worksheet#add_row
|
20
|
-
attr_reader :rows
|
21
|
-
|
22
|
-
# An array of content based calculated column widths.
|
23
|
-
# @note a single auto fit data item is a hash with :longest => [String] and :sz=> [Integer] members.
|
24
|
-
# @return [Array] of Hash
|
25
|
-
attr_reader :auto_fit_data
|
26
|
-
|
27
|
-
# TODO Merge Cells
|
28
|
-
# attr_reader :merge_cells
|
29
|
-
|
30
|
-
# Creates a new worksheet.
|
31
|
-
# @note the recommended way to manage worksheets is Workbook#add_worksheet
|
32
|
-
# @see Workbook#add_worksheet
|
33
|
-
# @option options [String] name The name of this sheet.
|
34
|
-
def initialize(wb, options={})
|
35
|
-
@drawing = nil
|
36
|
-
@rows = SimpleTypedList.new Row
|
37
|
-
self.workbook = wb
|
38
|
-
@workbook.worksheets << self
|
39
|
-
@auto_fit_data = []
|
40
|
-
self.name = options[:name] || "Sheet" + (index+1).to_s
|
41
|
-
@magick_draw = Magick::Draw.new
|
42
|
-
@cols = SimpleTypedList.new Cell
|
43
|
-
end
|
44
|
-
|
45
|
-
# Returns the cell or cells defined using excel style A1:B3 references.
|
46
|
-
# @param [String] cell_def the string defining the cell or range of cells
|
47
|
-
# @return [Cell, Array]
|
48
|
-
def [](cell_def)
|
49
|
-
parts = cell_def.split(':')
|
50
|
-
first = name_to_cell parts[0]
|
51
|
-
|
52
|
-
if parts.size == 1
|
53
|
-
first
|
54
|
-
else
|
55
|
-
cells = []
|
56
|
-
last = name_to_cell(parts[1])
|
57
|
-
rows[(first.row.index..last.row.index)].each do |r|
|
58
|
-
r.cells[(first.index..last.index)].each do |c|
|
59
|
-
cells << c
|
60
|
-
end
|
61
|
-
end
|
62
|
-
cells
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# returns the column and row index for a named based cell
|
67
|
-
# @param [String] name The cell or cell range to return. "A1" will return the first cell of the first row.
|
68
|
-
# @return [Cell]
|
69
|
-
def name_to_cell(name)
|
70
|
-
col_index, row_index = *Axlsx::name_to_indices(name)
|
71
|
-
r = rows[row_index]
|
72
|
-
r.cells[col_index] if r
|
73
|
-
end
|
74
|
-
|
75
|
-
# The name of the worksheet
|
76
|
-
# @param [String] v
|
77
|
-
def name=(v)
|
78
|
-
DataTypeValidator.validate "Worksheet.name", String, v
|
79
|
-
sheet_names = @workbook.worksheets.map { |s| s.name }
|
80
|
-
raise ArgumentError, (ERR_DUPLICATE_SHEET_NAME % v) if sheet_names.include?(v)
|
81
|
-
@name=v
|
82
|
-
end
|
83
|
-
|
84
|
-
# The part name of this worksheet
|
85
|
-
# @return [String]
|
86
|
-
def pn
|
87
|
-
"#{WORKSHEET_PN % (index+1)}"
|
88
|
-
end
|
89
|
-
|
90
|
-
# The relationship part name of this worksheet
|
91
|
-
# @return [String]
|
92
|
-
def rels_pn
|
93
|
-
"#{WORKSHEET_RELS_PN % (index+1)}"
|
94
|
-
end
|
95
|
-
|
96
|
-
# The relationship Id of thiw worksheet
|
97
|
-
# @return [String]
|
98
|
-
def rId
|
99
|
-
"rId#{index+1}"
|
100
|
-
end
|
101
|
-
|
102
|
-
# The index of this worksheet in the owning Workbook's worksheets list.
|
103
|
-
# @return [Integer]
|
104
|
-
def index
|
105
|
-
@workbook.worksheets.index(self)
|
106
|
-
end
|
107
|
-
|
108
|
-
# The drawing associated with this worksheet.
|
109
|
-
# @note the recommended way to work with drawings and charts is Worksheet#add_chart
|
110
|
-
# @return [Drawing]
|
111
|
-
# @see Worksheet#add_chart
|
112
|
-
def drawing
|
113
|
-
@drawing || @drawing = Axlsx::Drawing.new(self)
|
114
|
-
end
|
115
|
-
|
116
|
-
# Adds a row to the worksheet and updates auto fit data
|
117
|
-
# @return [Row]
|
118
|
-
# @option options [Array] values
|
119
|
-
# @option options [Array, Symbol] types
|
120
|
-
# @option options [Array, Integer] style
|
121
|
-
def add_row(values=[], options={})
|
122
|
-
Row.new(self, values, options)
|
123
|
-
update_auto_fit_data @rows.last.cells
|
124
|
-
yield @rows.last if block_given?
|
125
|
-
@rows.last
|
126
|
-
end
|
127
|
-
|
128
|
-
# Set the style for cells in a specific row
|
129
|
-
# @param [Integer] index or range of indexes in the table
|
130
|
-
# @param [Integer] the cellXfs index
|
131
|
-
# @option options [Integer] col_offset only cells after this column will be updated.
|
132
|
-
# @note You can also specify the style in the add_row call
|
133
|
-
# @see Worksheet#add_row
|
134
|
-
# @see README.md for an example
|
135
|
-
def row_style(index, style, options={})
|
136
|
-
offset = options.delete(:col_offset) || 0
|
137
|
-
rs = @rows[index]
|
138
|
-
if rs.is_a?(Array)
|
139
|
-
rs.each { |r| r.cells[(offset..-1)].each { |c| c.style = style } }
|
140
|
-
else
|
141
|
-
rs.cells[(offset..-1)].each { |c| c.style = style }
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
# returns the sheet data as columnw
|
146
|
-
def cols
|
147
|
-
@rows.transpose
|
148
|
-
end
|
149
|
-
|
150
|
-
|
151
|
-
# Set the style for cells in a specific column
|
152
|
-
# @param [Integer] index the index of the column
|
153
|
-
# @param [Integer] the cellXfs index
|
154
|
-
# @option options [Integer] row_offset only cells after this column will be updated.
|
155
|
-
# @note You can also specify the style for specific columns in the call to add_row by using an array for the :styles option
|
156
|
-
# @see Worksheet#add_row
|
157
|
-
# @see README.md for an example
|
158
|
-
def col_style(index, style, options={})
|
159
|
-
offset = options.delete(:row_offset) || 0
|
160
|
-
@rows[(offset..-1)].each do |r|
|
161
|
-
cells = r.cells[index]
|
162
|
-
if cells.is_a?(Array)
|
163
|
-
cells.each { |c| c.style = style }
|
164
|
-
else
|
165
|
-
cells.style = style
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
# Adds a chart to this worksheets drawing. This is the recommended way to create charts for your worksheet. This method wraps the complexity of dealing with ooxml drawing, anchors, markers graphic frames chart objects and all the other dirty details.
|
171
|
-
# @param [Class] chart_type
|
172
|
-
# @option options [Array] start_at
|
173
|
-
# @option options [Array] end_at
|
174
|
-
# @option options [Cell, String] title
|
175
|
-
# @option options [Boolean] show_legend
|
176
|
-
# @option options [Integer] style
|
177
|
-
# @note each chart type also specifies additional options
|
178
|
-
# @see Chart
|
179
|
-
# @see Pie3DChart
|
180
|
-
# @see Bar3DChart
|
181
|
-
# @see Line3DChart
|
182
|
-
# @see README for examples
|
183
|
-
def add_chart(chart_type, options={})
|
184
|
-
chart = drawing.add_chart(chart_type, options)
|
185
|
-
yield chart if block_given?
|
186
|
-
chart
|
187
|
-
end
|
188
|
-
|
189
|
-
# Adds a media item to the worksheets drawing
|
190
|
-
# @param [Class] media_type
|
191
|
-
# @option options [] unknown
|
192
|
-
def add_image(options={})
|
193
|
-
image = drawing.add_image(options)
|
194
|
-
yield image if block_given?
|
195
|
-
image
|
196
|
-
end
|
197
|
-
|
198
|
-
# Serializes the worksheet document
|
199
|
-
# @return [String]
|
200
|
-
def to_xml
|
201
|
-
builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml|
|
202
|
-
xml.worksheet(:xmlns => XML_NS, :'xmlns:r' => XML_NS_R) {
|
203
|
-
if @auto_fit_data.size > 0
|
204
|
-
xml.cols {
|
205
|
-
@auto_fit_data.each_with_index do |col, index|
|
206
|
-
min_max = index+1
|
207
|
-
xml.col(:min=>min_max, :max=>min_max, :width => auto_width(col), :customWidth=>"true")
|
208
|
-
end
|
209
|
-
}
|
210
|
-
end
|
211
|
-
xml.sheetData {
|
212
|
-
@rows.each do |row|
|
213
|
-
row.to_xml(xml)
|
214
|
-
end
|
215
|
-
}
|
216
|
-
xml.drawing :"r:id"=>"rId1" if @drawing
|
217
|
-
}
|
218
|
-
end
|
219
|
-
builder.to_xml
|
220
|
-
end
|
221
|
-
|
222
|
-
# The worksheet relationships. This is managed automatically by the worksheet
|
223
|
-
# @return [Relationships]
|
224
|
-
def relationships
|
225
|
-
r = Relationships.new
|
226
|
-
r << Relationship.new(DRAWING_R, "../#{@drawing.pn}") if @drawing
|
227
|
-
r
|
228
|
-
end
|
229
|
-
|
230
|
-
private
|
231
|
-
|
232
|
-
# assigns the owner workbook for this worksheet
|
233
|
-
def workbook=(v) DataTypeValidator.validate "Worksheet.workbook", Workbook, v; @workbook = v; end
|
234
|
-
|
235
|
-
# Updates auto fit data.
|
236
|
-
# Autofit data attempts to determine the cell in a column that has the greatest width by comparing the length of the text multiplied by the size of the font.
|
237
|
-
# @return [Array] of Cell objects
|
238
|
-
# @param [Array] cells an array of cells
|
239
|
-
def update_auto_fit_data(cells)
|
240
|
-
styles = self.workbook.styles
|
241
|
-
cellXfs, fonts = styles.cellXfs, styles.fonts
|
242
|
-
sz = fonts[0].sz
|
243
|
-
cells.each_with_index do |item, index|
|
244
|
-
next if item.value.is_a?(String) && item.value.start_with?('=')
|
245
|
-
col = @auto_fit_data[index] || {:longest=>"", :sz=>sz}
|
246
|
-
cell_xf = cellXfs[item.style]
|
247
|
-
font = fonts[cell_xf.fontId || 0]
|
248
|
-
sz = item.sz || font.sz || fonts[0].sz
|
249
|
-
if (col[:longest].scan(/./mu).size * col[:sz]) < (item.value.to_s.scan(/./mu).size * sz)
|
250
|
-
col[:sz] = sz
|
251
|
-
col[:longest] = item.value.to_s
|
252
|
-
end
|
253
|
-
@auto_fit_data[index] = col
|
254
|
-
end
|
255
|
-
cells
|
256
|
-
end
|
257
|
-
|
258
|
-
# Determines the proper width for a column based on content.
|
259
|
-
# @note
|
260
|
-
# From ECMA docs
|
261
|
-
# Column width measured as the number of characters of the maximum digit width of the numbers 0 .. 9 as
|
262
|
-
# rendered in the normal style's font. There are 4 pixels of margin padding (two on each side), plus 1 pixel padding for the gridlines.
|
263
|
-
# width = Truncate([!{Number of Characters} * !{Maximum Digit Width} + !{5 pixel padding}]/{Maximum Digit Width}*256)/256
|
264
|
-
# @return [Float]
|
265
|
-
# @param [Hash] A hash of auto_fit_data
|
266
|
-
def auto_width(col)
|
267
|
-
mdw = 6.0 # maximum digit with is always 6.0 with RMagick's default font
|
268
|
-
mdw_count = 0
|
269
|
-
best_guess = 1.5 #direct testing shows the results of the documented formula to be a bit too small. This is a best guess scaling
|
270
|
-
font_scale = col[:sz].to_f / (self.workbook.styles.fonts[0].sz.to_f || 11.0)
|
271
|
-
|
272
|
-
col[:longest].scan(/./mu).each do |i|
|
273
|
-
mdw_count +=1 if @magick_draw.get_type_metrics(i).width >= mdw
|
274
|
-
end
|
275
|
-
((mdw_count * mdw + 5) / mdw * 256) / 256.0 * best_guess * font_scale
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|