axlsx 1.0.17 → 1.0.18
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +70 -37
- data/examples/example.rb +163 -150
- data/lib/axlsx.rb +2 -2
- data/lib/axlsx/content_type/content_type.rb +3 -3
- data/lib/axlsx/drawing/chart.rb +3 -3
- data/lib/axlsx/drawing/pic.rb +1 -0
- data/lib/axlsx/package.rb +29 -29
- data/lib/axlsx/rels/relationship.rb +3 -3
- data/lib/axlsx/stylesheet/font.rb +7 -0
- data/lib/axlsx/stylesheet/styles.rb +6 -3
- data/lib/axlsx/util/constants.rb +16 -14
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/workbook.rb +24 -24
- data/lib/axlsx/workbook/worksheet/cell.rb +68 -53
- data/lib/axlsx/workbook/worksheet/date_time_converter.rb +29 -0
- data/lib/axlsx/workbook/worksheet/page_margins.rb +94 -0
- data/lib/axlsx/workbook/worksheet/row.rb +31 -14
- data/lib/axlsx/workbook/worksheet/worksheet.rb +127 -45
- data/test/drawing/tc_chart.rb +2 -2
- data/test/stylesheet/tc_cell_alignment.rb +8 -3
- data/test/stylesheet/tc_font.rb +8 -0
- data/test/stylesheet/tc_styles.rb +6 -2
- data/test/workbook/worksheet/tc_cell.rb +39 -9
- data/test/workbook/worksheet/tc_date_time_converter.rb +127 -0
- data/test/workbook/worksheet/tc_date_time_converter.rb~ +69 -0
- data/test/workbook/worksheet/tc_page_margins.rb +100 -0
- data/test/workbook/worksheet/tc_row.rb +36 -0
- data/test/workbook/worksheet/tc_worksheet.rb +78 -1
- metadata +87 -119
@@ -1,61 +1,61 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
module Axlsx
|
3
|
-
# A cell in a worksheet.
|
3
|
+
# A cell in a worksheet.
|
4
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
5
|
# @example Manually creating and manipulating Cell objects
|
6
|
-
# ws = Workbook.new.add_worksheet
|
6
|
+
# ws = Workbook.new.add_worksheet
|
7
7
|
# # This is the simple, and recommended way to create cells. Data types will automatically be determined for you.
|
8
8
|
# ws.add_row :values => [1,"fish",Time.now]
|
9
9
|
#
|
10
10
|
# # but you can also do this
|
11
11
|
# r = ws.add_row
|
12
12
|
# r.add_cell 1
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# # or even this
|
15
15
|
# r = ws.add_row
|
16
16
|
# c = Cell.new row, 1, :value=>integer
|
17
17
|
#
|
18
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
19
|
# r.cells.last.type = :float
|
20
|
-
#
|
20
|
+
#
|
21
21
|
# @note The recommended way to generate cells is via Worksheet#add_row
|
22
|
-
#
|
22
|
+
#
|
23
23
|
# @see Worksheet#add_row
|
24
24
|
class Cell
|
25
25
|
|
26
26
|
|
27
27
|
# An array of available inline styes.
|
28
|
-
INLINE_STYLES = ['value', 'type', 'font_name', 'charset',
|
29
|
-
'family', 'b', 'i', 'strike','outline',
|
30
|
-
'shadow', 'condense', 'extend', 'u',
|
28
|
+
INLINE_STYLES = ['value', 'type', 'font_name', 'charset',
|
29
|
+
'family', 'b', 'i', 'strike','outline',
|
30
|
+
'shadow', 'condense', 'extend', 'u',
|
31
31
|
'vertAlign', 'sz', 'color', 'scheme']
|
32
32
|
|
33
33
|
|
34
34
|
# The index of the cellXfs item to be applied to this cell.
|
35
|
-
# @return [Integer]
|
35
|
+
# @return [Integer]
|
36
36
|
# @see Axlsx::Styles
|
37
37
|
attr_reader :style
|
38
38
|
|
39
39
|
# The row this cell belongs to.
|
40
40
|
# @return [Row]
|
41
41
|
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
|
42
|
+
|
43
|
+
# The cell's data type. Currently only six types are supported, :date, :time, :float, :integer, :string and :boolean.
|
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
|
45
45
|
# automatically determed.
|
46
46
|
# @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
|
47
|
+
# @return [Symbol] The type of data this cell's value is cast to.
|
48
|
+
# @raise [ArgumentExeption] Cell.type must be one of [:date, time, :float, :integer, :string, :boolean]
|
49
|
+
# @note
|
50
50
|
# 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
|
51
|
+
# :string to :integer or :float, type conversions always return 0 or 0.0
|
52
52
|
# :string, :integer, or :float to :time conversions always return the original value as a string and set the cells type to :string.
|
53
53
|
# No support is currently implemented for parsing time strings.
|
54
54
|
attr_reader :type
|
55
55
|
# @see type
|
56
|
-
def type=(v)
|
57
|
-
RestrictionValidator.validate "Cell.type", [:time, :float, :integer, :string], v
|
58
|
-
@type=v
|
56
|
+
def type=(v)
|
57
|
+
RestrictionValidator.validate "Cell.type", [:date, :time, :float, :integer, :string, :boolean], v
|
58
|
+
@type=v
|
59
59
|
self.value = @value unless @value.nil?
|
60
60
|
end
|
61
61
|
|
@@ -68,7 +68,7 @@ module Axlsx
|
|
68
68
|
#TODO: consider doing value based type determination first?
|
69
69
|
@value = cast_value(v)
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
# The inline font_name property for the cell
|
73
73
|
# @return [String]
|
74
74
|
attr_reader :font_name
|
@@ -139,7 +139,7 @@ module Axlsx
|
|
139
139
|
# @return [Color]
|
140
140
|
attr_reader :color
|
141
141
|
# @param [String] The 8 character representation for an rgb color #FFFFFFFF"
|
142
|
-
def color=(v)
|
142
|
+
def color=(v)
|
143
143
|
@color = v.is_a?(Color) ? v : Color.new(:rgb=>v)
|
144
144
|
end
|
145
145
|
|
@@ -164,7 +164,7 @@ module Axlsx
|
|
164
164
|
def scheme=(v) RestrictionValidator.validate "Cell.schema", [:none, :major, :minor], v; @scheme = v; end
|
165
165
|
|
166
166
|
# @param [Row] row The row this cell belongs to.
|
167
|
-
# @param [Any] value The value associated with this cell.
|
167
|
+
# @param [Any] value The value associated with this cell.
|
168
168
|
# @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
169
|
# @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
170
|
# @option options [String] font_name
|
@@ -183,9 +183,11 @@ module Axlsx
|
|
183
183
|
# @option options [String] color an 8 letter rgb specification
|
184
184
|
# @option options [Symbol] scheme must be one of :none, major, :minor
|
185
185
|
def initialize(row, value="", options={})
|
186
|
-
self.row=row
|
186
|
+
self.row=row
|
187
|
+
@font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil
|
188
|
+
@condense = @u = @vertAlign = @sz = @color = @scheme = @extend = @ssti = nil
|
187
189
|
@styles = row.worksheet.workbook.styles
|
188
|
-
@row.cells << self
|
190
|
+
@row.cells << self
|
189
191
|
options.each do |o|
|
190
192
|
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
191
193
|
end
|
@@ -197,14 +199,14 @@ module Axlsx
|
|
197
199
|
# The Shared Strings Table index for this cell
|
198
200
|
# @return [Integer]
|
199
201
|
attr_reader :ssti
|
200
|
-
|
202
|
+
|
201
203
|
# equality comparison to test value, type and inline style attributes
|
202
204
|
# this is how we work out if the cell needs to be added or already exists in the shared strings table
|
203
205
|
def shareable(v)
|
204
206
|
|
205
207
|
#using reject becase 1.8.7 select returns an array...
|
206
|
-
v_hash = v.instance_values.reject { |
|
207
|
-
self_hash = self.instance_values.reject { |
|
208
|
+
v_hash = v.instance_values.reject { |key, val| !INLINE_STYLES.include?(key) }
|
209
|
+
self_hash = self.instance_values.reject { |key, val| !INLINE_STYLES.include?(key) }
|
208
210
|
# required as color is an object, and the comparison will fail even though both use the same color.
|
209
211
|
v_hash['color'] = v_hash['color'].instance_values if v_hash['color']
|
210
212
|
self_hash['color'] = self_hash['color'].instance_values if self_hash['color']
|
@@ -219,14 +221,14 @@ module Axlsx
|
|
219
221
|
|
220
222
|
# @return [String] The alpha(column)numeric(row) reference for this sell.
|
221
223
|
# @example Relative Cell Reference
|
222
|
-
# ws.rows.first.cells.first.r #=> "A1"
|
224
|
+
# ws.rows.first.cells.first.r #=> "A1"
|
223
225
|
def r
|
224
|
-
"#{col_ref}#{@row.index+1}"
|
226
|
+
"#{col_ref}#{@row.index+1}"
|
225
227
|
end
|
226
228
|
|
227
229
|
# @return [String] The absolute alpha(column)numeric(row) reference for this sell.
|
228
230
|
# @example Absolute Cell Reference
|
229
|
-
# ws.rows.first.cells.first.r #=> "$A$1"
|
231
|
+
# ws.rows.first.cells.first.r #=> "$A$1"
|
230
232
|
def r_abs
|
231
233
|
"$#{r.split('').join('$')}"
|
232
234
|
end
|
@@ -255,7 +257,7 @@ module Axlsx
|
|
255
257
|
target.r
|
256
258
|
end
|
257
259
|
self.row.worksheet.merge_cells "#{self.r}:#{range_end}" unless range_end.nil?
|
258
|
-
end
|
260
|
+
end
|
259
261
|
|
260
262
|
# builds an xml text run based on this cells attributes. This is extracted from to_xml so that shared strings can use it.
|
261
263
|
# @param [Nokogiri::XML::Builder] xml The document builder instance this output will be added to.
|
@@ -278,7 +280,7 @@ module Axlsx
|
|
278
280
|
xml.sz(:val=>@sz) if @sz
|
279
281
|
xml.u(:val=>@u) if @u
|
280
282
|
# :baseline, :subscript, :superscript
|
281
|
-
xml.vertAlign(:val=>@vertAlign) if @
|
283
|
+
xml.vertAlign(:val=>@vertAlign) if @vertAlign
|
282
284
|
# :none, major, :minor
|
283
285
|
xml.scheme(:val=>@scheme) if @scheme
|
284
286
|
}
|
@@ -286,14 +288,14 @@ module Axlsx
|
|
286
288
|
}
|
287
289
|
else
|
288
290
|
xml.t @value.to_s
|
289
|
-
end
|
291
|
+
end
|
290
292
|
end
|
291
293
|
|
292
294
|
# Serializes the cell
|
293
295
|
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
294
296
|
# @return [String] xml text for the cell
|
295
|
-
def to_xml(xml)
|
296
|
-
if @type == :string
|
297
|
+
def to_xml(xml)
|
298
|
+
if @type == :string
|
297
299
|
#parse formula
|
298
300
|
if @value.start_with?('=')
|
299
301
|
xml.c(:r => r, :t=>:str, :s=>style) {
|
@@ -312,29 +314,31 @@ module Axlsx
|
|
312
314
|
}
|
313
315
|
end
|
314
316
|
end
|
317
|
+
elsif @type == :date
|
318
|
+
# TODO: See if this is subject to the same restriction as Time below
|
319
|
+
v = DateTimeConverter::date_to_serial @value
|
320
|
+
xml.c(:r => r, :s => style) { xml.v v }
|
315
321
|
elsif @type == :time
|
316
|
-
|
317
|
-
epoc1900 = -2209021200 #Time.local(1900, 1, 1)
|
318
|
-
epoc1904 = -2082877200 #Time.local(1904, 1, 1)
|
319
|
-
epoc = Workbook.date1904 ? epoc1904 : epoc1900
|
320
|
-
v = ((@value.localtime.to_f - epoc) /60.0/60.0/24.0).to_f
|
322
|
+
v = DateTimeConverter::time_to_serial @value
|
321
323
|
xml.c(:r => r, :s => style) { xml.v v }
|
324
|
+
elsif @type == :boolean
|
325
|
+
xml.c(:r => r, :s => style, :t => :b) { xml.v value }
|
322
326
|
else
|
323
327
|
xml.c(:r => r, :s => style) { xml.v value }
|
324
328
|
end
|
325
329
|
end
|
326
330
|
|
327
|
-
private
|
331
|
+
private
|
328
332
|
|
329
333
|
# @see ssti
|
330
|
-
def ssti=(v)
|
334
|
+
def ssti=(v)
|
331
335
|
Axlsx::validate_unsigned_int(v)
|
332
336
|
@ssti = v
|
333
337
|
end
|
334
338
|
|
335
339
|
# assigns the owning row for this cell.
|
336
340
|
def row=(v) DataTypeValidator.validate "Cell.row", Row, v; @row=v end
|
337
|
-
|
341
|
+
|
338
342
|
# converts the column index into alphabetical values.
|
339
343
|
# @note This follows the standard spreadsheet convention of naming columns A to Z, followed by AA to AZ etc.
|
340
344
|
# @return [String]
|
@@ -349,15 +353,21 @@ module Axlsx
|
|
349
353
|
chars.reverse.join
|
350
354
|
end
|
351
355
|
|
352
|
-
# Determines the cell type based on the cell value.
|
356
|
+
# Determines the cell type based on the cell value.
|
353
357
|
# @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.
|
358
|
+
# 1. If the value is an instance of Date, the type is set to :date
|
359
|
+
# 2. If the value is an instance of Time, the type is set to :time
|
360
|
+
# 3. If the value is an instance of TrueClass or FalseClass, the type is set to :boolean
|
361
|
+
# 4. :float and :integer types are determined by regular expression matching.
|
362
|
+
# 5. Anything that does not meet either of the above is determined to be :string.
|
357
363
|
# @return [Symbol] The determined type
|
358
|
-
def cell_type_from_value(v)
|
359
|
-
if v.is_a?
|
364
|
+
def cell_type_from_value(v)
|
365
|
+
if v.is_a?(Date)
|
366
|
+
:date
|
367
|
+
elsif v.is_a?(Time)
|
360
368
|
:time
|
369
|
+
elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
370
|
+
:boolean
|
361
371
|
elsif v.to_s.match(/\A[+-]?\d+?\Z/) #numeric
|
362
372
|
:integer
|
363
373
|
elsif v.to_s.match(/\A[+-]?\d+\.\d+?\Z/) #float
|
@@ -367,22 +377,27 @@ module Axlsx
|
|
367
377
|
end
|
368
378
|
end
|
369
379
|
|
370
|
-
# Cast the value into this cells data type.
|
371
|
-
# @note
|
380
|
+
# Cast the value into this cells data type.
|
381
|
+
# @note
|
372
382
|
# 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
383
|
# @see Axlsx#date1904
|
374
384
|
def cast_value(v)
|
375
|
-
if
|
385
|
+
if @type == :date
|
386
|
+
self.style = STYLE_DATE if self.style == 0
|
387
|
+
v
|
388
|
+
elsif (@type == :time && v.is_a?(Time)) || (@type == :time && v.respond_to?(:to_time))
|
376
389
|
self.style = STYLE_DATE if self.style == 0
|
377
390
|
v.respond_to?(:to_time) ? v.to_time : v
|
378
391
|
elsif @type == :float
|
379
392
|
v.to_f
|
380
393
|
elsif @type == :integer
|
381
394
|
v.to_i
|
395
|
+
elsif @type == :boolean
|
396
|
+
v ? 1 : 0
|
382
397
|
else
|
383
398
|
@type = :string
|
384
399
|
v.to_s
|
385
400
|
end
|
386
|
-
end
|
401
|
+
end
|
387
402
|
end
|
388
403
|
end
|
@@ -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
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Axlsx
|
2
|
+
# PageMargins specify the margins when printing a worksheet.
|
3
|
+
#
|
4
|
+
# For compatibility, PageMargins serialize to an empty string, unless at least one custom margin value
|
5
|
+
# has been specified. Otherwise, it serializes to a PageMargin element specifying all 6 margin values
|
6
|
+
# (using default values for margins that have not been specified explicitly).
|
7
|
+
#
|
8
|
+
# @note The recommended way to manage page margins is via Worksheet#page_margins
|
9
|
+
# @see Worksheet#page_margins
|
10
|
+
# @see Worksheet#initialize
|
11
|
+
class PageMargins
|
12
|
+
|
13
|
+
# Default left and right margin (in inches)
|
14
|
+
DEFAULT_LEFT_RIGHT = 0.75
|
15
|
+
|
16
|
+
# Default top and bottom margins (in inches)
|
17
|
+
DEFAULT_TOP_BOTTOM = 1.00
|
18
|
+
|
19
|
+
# Default header and footer margins (in inches)
|
20
|
+
DEFAULT_HEADER_FOOTER = 0.50
|
21
|
+
|
22
|
+
# Left margin (in inches)
|
23
|
+
# @return [Float]
|
24
|
+
attr_reader :left
|
25
|
+
|
26
|
+
# Right margin (in inches)
|
27
|
+
# @return [Float]
|
28
|
+
attr_reader :right
|
29
|
+
|
30
|
+
# Top margin (in inches)
|
31
|
+
# @return [Float]
|
32
|
+
attr_reader :top
|
33
|
+
|
34
|
+
# Bottom margin (in inches)
|
35
|
+
# @return [Float]
|
36
|
+
attr_reader :bottom
|
37
|
+
|
38
|
+
# Header margin (in inches)
|
39
|
+
# @return [Float]
|
40
|
+
attr_reader :header
|
41
|
+
|
42
|
+
# Footer margin (in inches)
|
43
|
+
# @return [Float]
|
44
|
+
attr_reader :footer
|
45
|
+
|
46
|
+
# Creates a new PageMargins object
|
47
|
+
# @option options [Numeric] left The left margin in inches
|
48
|
+
# @option options [Numeric] right The right margin in inches
|
49
|
+
# @option options [Numeric] bottom The bottom margin in inches
|
50
|
+
# @option options [Numeric] top The top margin in inches
|
51
|
+
# @option options [Numeric] header The header margin in inches
|
52
|
+
# @option options [Numeric] footer The footer margin in inches
|
53
|
+
def initialize(options={})
|
54
|
+
# Default values taken from MS Excel for Mac 2011
|
55
|
+
@left = @right = DEFAULT_LEFT_RIGHT
|
56
|
+
@top = @bottom = DEFAULT_TOP_BOTTOM
|
57
|
+
@header = @footer = DEFAULT_HEADER_FOOTER
|
58
|
+
|
59
|
+
options.each do |o|
|
60
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Set some or all margins at once.
|
65
|
+
# @param [Hash] margins the margins to set (possible keys are :left, :right, :top, :bottom, :header and :footer).
|
66
|
+
def set(margins)
|
67
|
+
margins.select do |k, v|
|
68
|
+
next unless [:left, :right, :top, :bottom, :header, :footer].include? k
|
69
|
+
send("#{k}=", v)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# @see left
|
74
|
+
def left=(v); Axlsx::validate_unsigned_numeric(v); @left = v end
|
75
|
+
# @see right
|
76
|
+
def right=(v); Axlsx::validate_unsigned_numeric(v); @right = v end
|
77
|
+
# @see top
|
78
|
+
def top=(v); Axlsx::validate_unsigned_numeric(v); @top = v end
|
79
|
+
# @see bottom
|
80
|
+
def bottom=(v); Axlsx::validate_unsigned_numeric(v); @bottom = v end
|
81
|
+
# @see header
|
82
|
+
def header=(v); Axlsx::validate_unsigned_numeric(v); @header = v end
|
83
|
+
# @see footer
|
84
|
+
def footer=(v); Axlsx::validate_unsigned_numeric(v); @footer = v end
|
85
|
+
|
86
|
+
# Serializes the page margins element
|
87
|
+
# @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
|
+
# @see #custom_margins_specified?
|
90
|
+
def to_xml(xml)
|
91
|
+
xml.pageMargins :left => left, :right => right, :top => top, :bottom => bottom, :header => header, :footer => footer
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -13,12 +13,14 @@ module Axlsx
|
|
13
13
|
# @return [SimpleTypedList]
|
14
14
|
attr_reader :cells
|
15
15
|
|
16
|
+
# The height of this row in points, if set explicitly.
|
17
|
+
# @return [Float]
|
18
|
+
attr_reader :height
|
19
|
+
|
16
20
|
# TODO 18.3.1.73
|
17
21
|
# collapsed
|
18
22
|
# customFormat
|
19
|
-
# customHeight
|
20
23
|
# hidden
|
21
|
-
# ht (height)
|
22
24
|
# outlineLevel
|
23
25
|
# ph
|
24
26
|
# s (style)
|
@@ -37,28 +39,33 @@ module Axlsx
|
|
37
39
|
# If the style option is not defined, the default style (0) is applied to each cell.
|
38
40
|
# @param [Worksheet] worksheet
|
39
41
|
# @option options [Array] values
|
40
|
-
# @option options [Array, Symbol] types
|
41
|
-
# @option options [Array, Integer] style
|
42
|
+
# @option options [Array, Symbol] types
|
43
|
+
# @option options [Array, Integer] style
|
44
|
+
# @option options [Float] height the row's height (in points)
|
42
45
|
# @see Row#array_to_cells
|
43
46
|
# @see Cell
|
44
47
|
def initialize(worksheet, values=[], options={})
|
48
|
+
@height = nil
|
45
49
|
self.worksheet = worksheet
|
46
50
|
@cells = SimpleTypedList.new Cell
|
47
51
|
@worksheet.rows << self
|
52
|
+
self.height = options.delete(:height) if options[:height]
|
48
53
|
array_to_cells(values, options)
|
49
54
|
end
|
50
55
|
|
51
56
|
# The index of this row in the worksheet
|
52
57
|
# @return [Integer]
|
53
|
-
def index
|
58
|
+
def index
|
54
59
|
worksheet.rows.index(self)
|
55
60
|
end
|
56
|
-
|
61
|
+
|
57
62
|
# Serializes the row
|
58
63
|
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
59
64
|
# @return [String]
|
60
65
|
def to_xml(xml)
|
61
|
-
|
66
|
+
attrs = {:r => index+1}
|
67
|
+
attrs.merge!(:customHeight => 1, :ht => height) if custom_height?
|
68
|
+
xml.row(attrs) { |ixml| @cells.each { |cell| cell.to_xml(ixml) } }
|
62
69
|
end
|
63
70
|
|
64
71
|
# Adds a singel sell to the row based on the data provided and updates the worksheet's autofit data.
|
@@ -68,7 +75,7 @@ module Axlsx
|
|
68
75
|
update_auto_fit_data
|
69
76
|
c
|
70
77
|
end
|
71
|
-
|
78
|
+
|
72
79
|
# sets the style for every cell in this row
|
73
80
|
def style=(style)
|
74
81
|
cells.each_with_index do | cell, index |
|
@@ -78,17 +85,27 @@ module Axlsx
|
|
78
85
|
end
|
79
86
|
|
80
87
|
# returns the cells in this row as an array
|
81
|
-
# This lets us transpose the rows into columns
|
88
|
+
# This lets us transpose the rows into columns
|
82
89
|
# @return [Array]
|
83
90
|
def to_ary
|
84
91
|
@cells.to_ary
|
85
92
|
end
|
86
93
|
|
94
|
+
# @see height
|
95
|
+
def height=(v); Axlsx::validate_unsigned_numeric(v) unless v.nil?; @height = v end
|
96
|
+
|
97
|
+
# true if the row height has been manually set
|
98
|
+
# @return [Boolean]
|
99
|
+
# @see #height
|
100
|
+
def custom_height?
|
101
|
+
@height != nil
|
102
|
+
end
|
103
|
+
|
87
104
|
private
|
88
105
|
|
89
106
|
# assigns the owning worksheet for this row
|
90
107
|
def worksheet=(v) DataTypeValidator.validate "Row.worksheet", Worksheet, v; @worksheet=v; end
|
91
|
-
|
108
|
+
|
92
109
|
# Tell the worksheet to update autofit data for the columns based on this row's cells.
|
93
110
|
# @return [SimpleTypedList]
|
94
111
|
def update_auto_fit_data
|
@@ -103,13 +120,13 @@ module Axlsx
|
|
103
120
|
# If the style option is defined and is an Integer, it is applied to all cells created.
|
104
121
|
# If the style option is an array, style is applied by index for each cell.
|
105
122
|
# @option options [Array] values
|
106
|
-
# @option options [Array, Symbol] types
|
107
|
-
# @option options [Array, Integer] style
|
123
|
+
# @option options [Array, Symbol] types
|
124
|
+
# @option options [Array, Integer] style
|
108
125
|
def array_to_cells(values, options={})
|
109
126
|
values = values
|
110
127
|
DataTypeValidator.validate 'Row.array_to_cells', Array, values
|
111
128
|
types, style = options.delete(:types), options.delete(:style)
|
112
|
-
values.each_with_index do |value, index|
|
129
|
+
values.each_with_index do |value, index|
|
113
130
|
cell_style = style.is_a?(Array) ? style[index] : style
|
114
131
|
options[:style] = cell_style if cell_style
|
115
132
|
cell_type = types.is_a?(Array)? types[index] : types
|
@@ -118,5 +135,5 @@ module Axlsx
|
|
118
135
|
end
|
119
136
|
end
|
120
137
|
end
|
121
|
-
|
138
|
+
|
122
139
|
end
|