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,9 +1,9 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
module Axlsx
|
3
|
-
|
4
|
-
# The Worksheet class represents a worksheet in the workbook.
|
3
|
+
|
4
|
+
# The Worksheet class represents a worksheet in the workbook.
|
5
5
|
class Worksheet
|
6
|
-
|
6
|
+
|
7
7
|
# The name of the worksheet
|
8
8
|
# @return [String]
|
9
9
|
attr_reader :name
|
@@ -21,7 +21,7 @@ module Axlsx
|
|
21
21
|
|
22
22
|
# An array of content based calculated column widths.
|
23
23
|
# @note a single auto fit data item is a hash with :longest => [String] and :sz=> [Integer] members.
|
24
|
-
# @return [Array] of Hash
|
24
|
+
# @return [Array] of Hash
|
25
25
|
attr_reader :auto_fit_data
|
26
26
|
|
27
27
|
# An array of merged cell ranges e.d "A1:B3"
|
@@ -34,21 +34,47 @@ module Axlsx
|
|
34
34
|
# The first row is considered the header, while subsequent rows are considerd to be data.
|
35
35
|
# @return Array
|
36
36
|
attr_reader :auto_filter
|
37
|
-
|
37
|
+
|
38
|
+
# Page margins for printing the worksheet.
|
39
|
+
# @example
|
40
|
+
# wb = Axlsx::Package.new.workbook
|
41
|
+
# # using options when creating the worksheet.
|
42
|
+
# ws = wb.add_worksheet :page_margins => {:left => 1.9, :header => 0.1}
|
43
|
+
#
|
44
|
+
# # use the set method of the page_margins object
|
45
|
+
# ws.page_margins.set(:bottom => 3, :footer => 0.7)
|
46
|
+
#
|
47
|
+
# # set page margins in a block
|
48
|
+
# ws.page_margins do |margins|
|
49
|
+
# margins.right = 6
|
50
|
+
# margins.top = 0.2
|
51
|
+
# end
|
52
|
+
# @see PageMargins#initialize
|
53
|
+
# @return [PageMargins]
|
54
|
+
def page_margins
|
55
|
+
@page_margins ||= PageMargins.new
|
56
|
+
yield @page_margins if block_given?
|
57
|
+
@page_margins
|
58
|
+
end
|
59
|
+
|
38
60
|
# Creates a new worksheet.
|
39
61
|
# @note the recommended way to manage worksheets is Workbook#add_worksheet
|
40
62
|
# @see Workbook#add_worksheet
|
41
|
-
# @option options [String] name The name of this
|
63
|
+
# @option options [String] name The name of this worksheet.
|
64
|
+
# @option options [Hash] page_margins A hash containing page margins for this worksheet. @see PageMargins
|
42
65
|
def initialize(wb, options={})
|
43
|
-
@drawing = nil
|
66
|
+
@drawing = @page_margins = @auto_filter = nil
|
44
67
|
@rows = SimpleTypedList.new Row
|
45
68
|
self.workbook = wb
|
46
69
|
@workbook.worksheets << self
|
47
70
|
@auto_fit_data = []
|
48
71
|
self.name = options[:name] || "Sheet" + (index+1).to_s
|
72
|
+
|
49
73
|
@magick_draw = Magick::Draw.new
|
50
74
|
@cols = SimpleTypedList.new Cell
|
51
75
|
@merged_cells = []
|
76
|
+
|
77
|
+
@page_margins = PageMargins.new options[:page_margins] if options[:page_margins]
|
52
78
|
end
|
53
79
|
|
54
80
|
# convinience method to access all cells in this worksheet
|
@@ -57,26 +83,26 @@ module Axlsx
|
|
57
83
|
rows.flatten
|
58
84
|
end
|
59
85
|
|
60
|
-
# Creates merge information for this worksheet.
|
86
|
+
# Creates merge information for this worksheet.
|
61
87
|
# Cells can be merged by calling the merge_cells method on a worksheet.
|
62
|
-
# @example This would merge the three cells C1..E1 #
|
88
|
+
# @example This would merge the three cells C1..E1 #
|
63
89
|
# worksheet.merge_cells "C1:E1"
|
64
90
|
# # you can also provide an array of cells to be merged
|
65
91
|
# worksheet.merge_cells worksheet.rows.first.cells[(2..4)]
|
66
92
|
# #alternatively you can do it from a single cell
|
67
93
|
# worksheet["C1"].merge worksheet["E1"]
|
68
|
-
# @param [Array, string]
|
94
|
+
# @param [Array, string]
|
69
95
|
def merge_cells(cells)
|
70
96
|
@merged_cells << if cells.is_a?(String)
|
71
97
|
cells
|
72
98
|
elsif cells.is_a?(Array)
|
73
99
|
cells = cells.sort { |x, y| x.r <=> y.r }
|
74
100
|
"#{cells.first.r}:#{cells.last.r}"
|
75
|
-
end
|
101
|
+
end
|
76
102
|
end
|
77
103
|
|
78
104
|
|
79
|
-
# The demensions of a worksheet. This is not actually a required element by the spec,
|
105
|
+
# The demensions of a worksheet. This is not actually a required element by the spec,
|
80
106
|
# but at least a few other document readers expect this for conversion
|
81
107
|
# @return [String] the A1:B2 style reference for the first and last row column intersection in the workbook
|
82
108
|
def dimension
|
@@ -85,9 +111,10 @@ module Axlsx
|
|
85
111
|
|
86
112
|
|
87
113
|
# Returns the cell or cells defined using excel style A1:B3 references.
|
88
|
-
# @param [String] cell_def the string defining the cell or range of cells
|
114
|
+
# @param [String|Integer] cell_def the string defining the cell or range of cells, or the rownumber
|
89
115
|
# @return [Cell, Array]
|
90
116
|
def [](cell_def)
|
117
|
+
return rows[cell_def - 1] if cell_def.is_a? Integer
|
91
118
|
parts = cell_def.split(':')
|
92
119
|
first = name_to_cell parts[0]
|
93
120
|
|
@@ -115,18 +142,20 @@ module Axlsx
|
|
115
142
|
end
|
116
143
|
|
117
144
|
# The name of the worksheet
|
145
|
+
# The name of a worksheet must be unique in the workbook, and must not exceed 31 characters
|
118
146
|
# @param [String] v
|
119
|
-
def name=(v)
|
147
|
+
def name=(v)
|
120
148
|
DataTypeValidator.validate "Worksheet.name", String, v
|
149
|
+
raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG % v) if v.size > 31
|
121
150
|
sheet_names = @workbook.worksheets.map { |s| s.name }
|
122
|
-
raise ArgumentError, (ERR_DUPLICATE_SHEET_NAME % v) if sheet_names.include?(v)
|
123
|
-
@name=v
|
151
|
+
raise ArgumentError, (ERR_DUPLICATE_SHEET_NAME % v) if sheet_names.include?(v)
|
152
|
+
@name=v
|
124
153
|
end
|
125
154
|
|
126
155
|
# The auto filter range for the worksheet
|
127
156
|
# @param [String] v
|
128
157
|
# @see auto_filter
|
129
|
-
def auto_filter=(v)
|
158
|
+
def auto_filter=(v)
|
130
159
|
DataTypeValidator.validate "Worksheet.auto_filter", String, v
|
131
160
|
@auto_filter = v
|
132
161
|
end
|
@@ -163,18 +192,54 @@ module Axlsx
|
|
163
192
|
@drawing || @drawing = Axlsx::Drawing.new(self)
|
164
193
|
end
|
165
194
|
|
166
|
-
# Adds a row to the worksheet and updates auto fit data
|
195
|
+
# Adds a row to the worksheet and updates auto fit data.
|
196
|
+
# @example - put a vanilla row in your spreadsheet
|
197
|
+
# ws.add_row [1, 'fish on my pl', '8']
|
198
|
+
#
|
199
|
+
# @example - specify a fixed width for a column in your spreadsheet
|
200
|
+
# # The first column will ignore the content of this cell when calculating column autowidth.
|
201
|
+
# # The second column will include this text in calculating the columns autowidth
|
202
|
+
# # The third cell will set a fixed with of 80 for the column.
|
203
|
+
# # If you need to un-fix a column width, use :auto. That will recalculate the column width based on all content in the column
|
204
|
+
#
|
205
|
+
# ws.add_row ['I wish', 'for a fish', 'on my fish wish dish'], :widths=>[:ignore, :auto, 80]
|
206
|
+
#
|
207
|
+
# @example - specify a fixed height for a row
|
208
|
+
# ws.add_row ['I wish', 'for a fish', 'on my fish wish dish'], :height => 40
|
209
|
+
#
|
210
|
+
# @example - create and use a style for all cells in the row
|
211
|
+
# blue = ws.styles.add_style :color => "#00FF00"
|
212
|
+
# ws.add_row [1, 2, 3], :style=>blue
|
213
|
+
#
|
214
|
+
# @example - only style some cells
|
215
|
+
# blue = ws.styles.add_style :color => "#00FF00"
|
216
|
+
# red = ws.styles.add_style :color => "#FF0000"
|
217
|
+
# big = ws.styles.add_style :sz => 40
|
218
|
+
# ws.add_row ["red fish", "blue fish", "one fish", "two fish"], :style=>[red, blue, nil, big] # the last nil is optional
|
219
|
+
#
|
220
|
+
#
|
221
|
+
# @example - force the second cell to be a float value
|
222
|
+
# ws.add_row [3, 4, 5], :types => [nil, :float]
|
223
|
+
#
|
224
|
+
# @example - use << alias
|
225
|
+
# ws << [3, 4, 5], :types => [nil, :float]
|
226
|
+
#
|
227
|
+
# @see Worksheet#column_widths
|
167
228
|
# @return [Row]
|
168
229
|
# @option options [Array] values
|
169
|
-
# @option options [Array, Symbol] types
|
170
|
-
# @option options [Array, Integer] style
|
230
|
+
# @option options [Array, Symbol] types
|
231
|
+
# @option options [Array, Integer] style
|
232
|
+
# @option options [Array] widths each member of the widths array will affect how auto_fit behavies.
|
233
|
+
# @option options [Float] height the row's height (in points)
|
171
234
|
def add_row(values=[], options={})
|
172
235
|
Row.new(self, values, options)
|
173
|
-
update_auto_fit_data @rows.last.cells
|
236
|
+
update_auto_fit_data @rows.last.cells, options.delete(:widths) || []
|
174
237
|
yield @rows.last if block_given?
|
175
238
|
@rows.last
|
176
239
|
end
|
177
240
|
|
241
|
+
alias :<< :add_row
|
242
|
+
|
178
243
|
# Set the style for cells in a specific row
|
179
244
|
# @param [Integer] index or range of indexes in the table
|
180
245
|
# @param [Integer] the cellXfs index
|
@@ -207,7 +272,7 @@ module Axlsx
|
|
207
272
|
# @see README.md for an example
|
208
273
|
def col_style(index, style, options={})
|
209
274
|
offset = options.delete(:row_offset) || 0
|
210
|
-
@rows[(offset..-1)].each do |r|
|
275
|
+
@rows[(offset..-1)].each do |r|
|
211
276
|
cells = r.cells[index]
|
212
277
|
next unless cells
|
213
278
|
if cells.is_a?(Array)
|
@@ -218,13 +283,13 @@ module Axlsx
|
|
218
283
|
end
|
219
284
|
end
|
220
285
|
|
221
|
-
# This is a helper method that Lets you specify a fixed width for multiple columns in a worksheet in one go.
|
286
|
+
# This is a helper method that Lets you specify a fixed width for multiple columns in a worksheet in one go.
|
222
287
|
# Axlsx is sparse, so if you have not set data for a column, you cannot set the width.
|
223
288
|
# Setting a fixed column width to nil will revert the behaviour back to calculating the width for you.
|
224
289
|
# @example This would set the first and third column widhts but leave the second column in autofit state.
|
225
290
|
# ws.column_widths 7.2, nil, 3
|
226
291
|
# @note For updating only a single column it is probably easier to just set ws.auto_fit_data[col_index][:fixed] directly
|
227
|
-
# @param [Integer|Float|Fixnum|nil] values
|
292
|
+
# @param [Integer|Float|Fixnum|nil] values
|
228
293
|
def column_widths(*args)
|
229
294
|
args.each_with_index do |value, index|
|
230
295
|
raise ArgumentError, "Invalid column specification" unless index < @auto_fit_data.size
|
@@ -233,14 +298,14 @@ module Axlsx
|
|
233
298
|
end
|
234
299
|
end
|
235
300
|
|
236
|
-
# 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.
|
301
|
+
# 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.
|
237
302
|
# @param [Class] chart_type
|
238
303
|
# @option options [Array] start_at
|
239
304
|
# @option options [Array] end_at
|
240
305
|
# @option options [Cell, String] title
|
241
306
|
# @option options [Boolean] show_legend
|
242
|
-
# @option options [Integer] style
|
243
|
-
# @note each chart type also specifies additional options
|
307
|
+
# @option options [Integer] style
|
308
|
+
# @note each chart type also specifies additional options
|
244
309
|
# @see Chart
|
245
310
|
# @see Pie3DChart
|
246
311
|
# @see Bar3DChart
|
@@ -265,9 +330,19 @@ module Axlsx
|
|
265
330
|
# @return [String]
|
266
331
|
def to_xml
|
267
332
|
builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml|
|
268
|
-
xml.worksheet(:xmlns => XML_NS,
|
333
|
+
xml.worksheet(:xmlns => XML_NS,
|
269
334
|
:'xmlns:r' => XML_NS_R) {
|
335
|
+
# another patch for the folks at rubyXL as thier parser depends on this optional element.
|
270
336
|
xml.dimension :ref=>dimension unless rows.size == 0
|
337
|
+
# this is required by rubyXL, spec says who cares - but it seems they didnt notice
|
338
|
+
# however, it also seems to be causing some odd [Grouped] stuff in excel 2011 - so
|
339
|
+
# removing until I understand it better.
|
340
|
+
# xml.sheetViews {
|
341
|
+
# xml.sheetView(:tabSelected => 1, :workbookViewId => 0) {
|
342
|
+
# xml.selection :activeCell=>"A1", :sqref => "A1"
|
343
|
+
# }
|
344
|
+
# }
|
345
|
+
|
271
346
|
if @auto_fit_data.size > 0
|
272
347
|
xml.cols {
|
273
348
|
@auto_fit_data.each_with_index do |col, index|
|
@@ -283,7 +358,8 @@ module Axlsx
|
|
283
358
|
}
|
284
359
|
xml.autoFilter :ref=>@auto_filter if @auto_filter
|
285
360
|
xml.mergeCells(:count=>@merged_cells.size) { @merged_cells.each { | mc | xml.mergeCell(:ref=>mc) } } unless @merged_cells.empty?
|
286
|
-
xml
|
361
|
+
page_margins.to_xml(xml) if @page_margins
|
362
|
+
xml.drawing :"r:id"=>"rId1" if @drawing
|
287
363
|
}
|
288
364
|
end
|
289
365
|
builder.to_xml(:save_with => 0)
|
@@ -297,28 +373,35 @@ module Axlsx
|
|
297
373
|
r
|
298
374
|
end
|
299
375
|
|
300
|
-
private
|
376
|
+
private
|
301
377
|
|
302
378
|
# assigns the owner workbook for this worksheet
|
303
379
|
def workbook=(v) DataTypeValidator.validate "Worksheet.workbook", Workbook, v; @workbook = v; end
|
304
380
|
|
305
|
-
# Updates auto fit data.
|
306
|
-
# We store an auto_fit_data item for each column. when a row is added we multiple the font size by the length of the text to
|
381
|
+
# Updates auto fit data.
|
382
|
+
# We store an auto_fit_data item for each column. when a row is added we multiple the font size by the length of the text to
|
307
383
|
# attempt to identify the longest cell in the column. This is not 100% accurate as it needs to take into account
|
308
|
-
# any formatting that will be applied to the data, as well as the actual rendering size when the length and size is equal
|
384
|
+
# any formatting that will be applied to the data, as well as the actual rendering size when the length and size is equal
|
309
385
|
# for two cells.
|
386
|
+
|
310
387
|
# @return [Array] of Cell objects
|
311
388
|
# @param [Array] cells an array of cells
|
312
|
-
|
389
|
+
# @param [Array] widths an array of cell widths @see Worksheet#add_row
|
390
|
+
def update_auto_fit_data(cells, widths=[])
|
313
391
|
# TODO delay this until rendering. too much work when we dont know what they are going to do to the sheet.
|
314
392
|
styles = self.workbook.styles
|
315
393
|
cellXfs, fonts = styles.cellXfs, styles.fonts
|
316
394
|
sz = 11
|
317
395
|
cells.each_with_index do |item, index|
|
318
|
-
|
319
|
-
|
396
|
+
col = @auto_fit_data[index] ||= {:longest=>"", :sz=>sz, :fixed=>nil}
|
397
|
+
width = widths[index]
|
398
|
+
# set fixed width and skip if numeric width is given
|
399
|
+
col[:fixed] = width if [Integer, Float, Fixnum].include?(width.class)
|
400
|
+
# ignore default column widths and formula
|
401
|
+
next if width == :ignore || (item.value.is_a?(String) && item.value.start_with?('='))
|
402
|
+
# make sure we can turn that fixed with off!
|
403
|
+
col[:fixed] = nil if width == :auto
|
320
404
|
|
321
|
-
col = @auto_fit_data[index] || {:longest=>"", :sz=>sz, :fixed=>nil}
|
322
405
|
cell_xf = cellXfs[item.style]
|
323
406
|
font = fonts[cell_xf.fontId || 0]
|
324
407
|
sz = item.sz || font.sz || fonts[0].sz
|
@@ -326,16 +409,15 @@ module Axlsx
|
|
326
409
|
col[:sz] = sz
|
327
410
|
col[:longest] = item.value.to_s
|
328
411
|
end
|
329
|
-
@auto_fit_data[index] = col
|
330
412
|
end
|
331
413
|
cells
|
332
414
|
end
|
333
|
-
|
415
|
+
|
334
416
|
# Determines the proper width for a column based on content.
|
335
|
-
# @note
|
417
|
+
# @note
|
336
418
|
# width = Truncate([!{Number of Characters} * !{Maximum Digit Width} + !{5 pixel padding}]/!{Maximum Digit Width}*256)/256
|
337
419
|
# @return [Float]
|
338
|
-
# @param [Hash] A hash of auto_fit_data
|
420
|
+
# @param [Hash] A hash of auto_fit_data
|
339
421
|
def auto_width(col)
|
340
422
|
return col[:fixed] unless col[:fixed] == nil
|
341
423
|
|
@@ -348,21 +430,21 @@ module Axlsx
|
|
348
430
|
end
|
349
431
|
|
350
432
|
# Something to look into:
|
351
|
-
# width calculation actually needs to be done agains the formatted value for items that apply a
|
433
|
+
# width calculation actually needs to be done agains the formatted value for items that apply a
|
352
434
|
# format
|
353
435
|
# def excel_format(cell)
|
354
436
|
# # The most common case.
|
355
437
|
# return time.value.to_s if cell.style == 0
|
356
438
|
#
|
357
|
-
# # The second most common case
|
439
|
+
# # The second most common case
|
358
440
|
# num_fmt = workbook.styles.cellXfs[items.style].numFmtId
|
359
441
|
# return value.to_s if num_fmt == 0
|
360
|
-
#
|
442
|
+
#
|
361
443
|
# format_code = workbook.styles.numFmts[num_fmt]
|
362
444
|
# # need to find some exceptionally fast way of parsing value according to
|
363
445
|
# # an excel format_code
|
364
446
|
# item.value.to_s
|
365
|
-
# end
|
447
|
+
# end
|
366
448
|
|
367
449
|
end
|
368
450
|
end
|
data/test/drawing/tc_chart.rb
CHANGED
@@ -41,9 +41,9 @@ class TestChart < Test::Unit::TestCase
|
|
41
41
|
|
42
42
|
end
|
43
43
|
|
44
|
-
def
|
44
|
+
def test_end_at
|
45
45
|
@chart.end_at 25, 90
|
46
|
-
assert_equal(@chart.graphic_frame.anchor.
|
46
|
+
assert_equal(@chart.graphic_frame.anchor.to.col, 25)
|
47
47
|
assert_equal(@chart.graphic_frame.anchor.to.row, 90)
|
48
48
|
end
|
49
49
|
|
@@ -5,8 +5,7 @@ class TestCellAlignment < Test::Unit::TestCase
|
|
5
5
|
def setup
|
6
6
|
@item = Axlsx::CellAlignment.new
|
7
7
|
end
|
8
|
-
|
9
|
-
end
|
8
|
+
|
10
9
|
def test_initialiation
|
11
10
|
assert_equal(@item.horizontal, nil)
|
12
11
|
assert_equal(@item.vertical, nil)
|
@@ -17,7 +16,13 @@ class TestCellAlignment < Test::Unit::TestCase
|
|
17
16
|
assert_equal(@item.justifyLastLine, nil)
|
18
17
|
assert_equal(@item.shrinkToFit, nil)
|
19
18
|
assert_equal(@item.readingOrder, nil)
|
20
|
-
|
19
|
+
options = { :horizontal => :left, :vertical => :top, :textRotation => 3,
|
20
|
+
:wrapText => true, :indent => 2, :relativeIndent => 5,
|
21
|
+
:justifyLastLine => true, :shrinkToFit => true, :readingOrder => 2 }
|
22
|
+
ca = Axlsx::CellAlignment.new options
|
23
|
+
options.each do |key, value|
|
24
|
+
assert_equal(ca.send(key.to_sym),value)
|
25
|
+
end
|
21
26
|
end
|
22
27
|
|
23
28
|
def test_horizontal
|
data/test/stylesheet/tc_font.rb
CHANGED
@@ -17,6 +17,7 @@ class TestFont < Test::Unit::TestCase
|
|
17
17
|
assert_equal(@item.family, nil)
|
18
18
|
assert_equal(@item.b, nil)
|
19
19
|
assert_equal(@item.i, nil)
|
20
|
+
assert_equal(@item.u, nil)
|
20
21
|
assert_equal(@item.strike, nil)
|
21
22
|
assert_equal(@item.outline, nil)
|
22
23
|
assert_equal(@item.shadow, nil)
|
@@ -61,6 +62,13 @@ class TestFont < Test::Unit::TestCase
|
|
61
62
|
assert_nothing_raised { @item.i = true }
|
62
63
|
assert_equal(@item.i, true)
|
63
64
|
end
|
65
|
+
|
66
|
+
# def u=(v) Axlsx::validate_boolean v; @u = v end
|
67
|
+
def test_u
|
68
|
+
assert_raise(ArgumentError) { @item.u = -7 }
|
69
|
+
assert_nothing_raised { @item.u = true }
|
70
|
+
assert_equal(@item.u, true)
|
71
|
+
end
|
64
72
|
|
65
73
|
# def strike=(v) Axlsx::validate_boolean v; @strike = v end
|
66
74
|
def test_strike
|
@@ -42,10 +42,14 @@ class TestStyles < Test::Unit::TestCase
|
|
42
42
|
|
43
43
|
assert(xf.alignment.is_a?(Axlsx::CellAlignment), "alignment was created")
|
44
44
|
assert_equal(xf.alignment.horizontal, :left, "horizontal alignment applied")
|
45
|
-
assert_equal(xf.applyProtection, 1, "protection applied")
|
46
45
|
assert_equal(xf.protection.hidden, true, "hidden protection set")
|
47
46
|
assert_equal(xf.protection.locked, true, "cell locking set")
|
48
|
-
assert_raise(ArgumentError, "should reject invalid borderId") { @styles.add_style :border => 2 }
|
47
|
+
assert_raise(ArgumentError, "should reject invalid borderId") { @styles.add_style :border => 2 }
|
48
|
+
|
49
|
+
|
50
|
+
assert_equal(xf.applyProtection, 1, "protection applied")
|
51
|
+
assert_equal(xf.applyBorder, true, "border applied")
|
52
|
+
assert_equal(xf.applyNumberFormat, true, "border applied")
|
49
53
|
|
50
54
|
end
|
51
55
|
|
@@ -10,7 +10,7 @@ class TestCell < Test::Unit::TestCase
|
|
10
10
|
@row = @ws.add_row
|
11
11
|
@c = @row.add_cell 1, :type=>:float, :style=>1
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def test_initialize
|
15
15
|
assert_equal(@row.cells.last, @c, "the cell was added to the row")
|
16
16
|
assert_equal(@c.type, :float, "type option is applied")
|
@@ -24,6 +24,10 @@ class TestCell < Test::Unit::TestCase
|
|
24
24
|
assert_equal(Axlsx::STYLE_DATE, c.style)
|
25
25
|
end
|
26
26
|
|
27
|
+
def test_row
|
28
|
+
assert_equal(@c.row, @row)
|
29
|
+
end
|
30
|
+
|
27
31
|
def test_index
|
28
32
|
assert_equal(@c.index, @row.cells.index(@c))
|
29
33
|
end
|
@@ -42,20 +46,22 @@ class TestCell < Test::Unit::TestCase
|
|
42
46
|
|
43
47
|
def test_style
|
44
48
|
assert_raise(ArgumentError, "must reject invalid style indexes") { @c.style=@c.row.worksheet.workbook.styles.cellXfs.size }
|
45
|
-
assert_nothing_raised("must allow valid style index changes") {@c.style=1}
|
49
|
+
assert_nothing_raised("must allow valid style index changes") {@c.style=1}
|
46
50
|
assert_equal(@c.style, 1)
|
47
51
|
end
|
48
52
|
|
49
53
|
def test_type
|
50
|
-
assert_raise(ArgumentError, "type must be :string, :integer, :float, :time") { @c.type = :array }
|
54
|
+
assert_raise(ArgumentError, "type must be :string, :integer, :float, :date, :time, :boolean") { @c.type = :array }
|
51
55
|
assert_nothing_raised("type can be changed") { @c.type = :string }
|
52
56
|
assert_equal(@c.value, "1.0", "changing type casts the value")
|
53
|
-
|
57
|
+
|
54
58
|
assert_equal(@row.add_cell(Time.now).type, :time, 'time should be time')
|
59
|
+
assert_equal(@row.add_cell(Date.today).type, :date, 'date should be date')
|
60
|
+
assert_equal(@row.add_cell(true).type, :boolean, 'boolean should be boolean')
|
55
61
|
end
|
56
62
|
|
57
63
|
def test_value
|
58
|
-
assert_raise(ArgumentError, "type must be :string, :integer, :float, :time") { @c.type = :array }
|
64
|
+
assert_raise(ArgumentError, "type must be :string, :integer, :float, :date, :time, :boolean") { @c.type = :array }
|
59
65
|
assert_nothing_raised("type can be changed") { @c.type = :string }
|
60
66
|
assert_equal(@c.value, "1.0", "changing type casts the value")
|
61
67
|
end
|
@@ -67,14 +73,17 @@ class TestCell < Test::Unit::TestCase
|
|
67
73
|
def test_cell_type_from_value
|
68
74
|
assert_equal(@c.send(:cell_type_from_value, 1.0), :float)
|
69
75
|
assert_equal(@c.send(:cell_type_from_value, 1), :integer)
|
76
|
+
assert_equal(@c.send(:cell_type_from_value, Date.today), :date)
|
70
77
|
assert_equal(@c.send(:cell_type_from_value, Time.now), :time)
|
71
78
|
assert_equal(@c.send(:cell_type_from_value, []), :string)
|
72
79
|
assert_equal(@c.send(:cell_type_from_value, "d"), :string)
|
73
80
|
assert_equal(@c.send(:cell_type_from_value, nil), :string)
|
74
81
|
assert_equal(@c.send(:cell_type_from_value, -1), :integer)
|
82
|
+
assert_equal(@c.send(:cell_type_from_value, true), :boolean)
|
83
|
+
assert_equal(@c.send(:cell_type_from_value, false), :boolean)
|
75
84
|
end
|
76
85
|
|
77
|
-
def test_cast_value
|
86
|
+
def test_cast_value
|
78
87
|
@c.type = :string
|
79
88
|
assert_equal(@c.send(:cast_value, 1.0), "1.0")
|
80
89
|
@c.type = :integer
|
@@ -83,7 +92,9 @@ class TestCell < Test::Unit::TestCase
|
|
83
92
|
assert_equal(@c.send(:cast_value, "1.0"), 1.0)
|
84
93
|
@c.type = :string
|
85
94
|
assert_equal(@c.send(:cast_value, nil), "")
|
86
|
-
|
95
|
+
@c.type = :boolean
|
96
|
+
assert_equal(@c.send(:cast_value, true), 1)
|
97
|
+
assert_equal(@c.send(:cast_value, false), 0)
|
87
98
|
end
|
88
99
|
|
89
100
|
def test_color
|
@@ -181,7 +192,7 @@ class TestCell < Test::Unit::TestCase
|
|
181
192
|
@c.row.add_cell 2
|
182
193
|
@c.row.add_cell 3
|
183
194
|
@c.merge "A2"
|
184
|
-
assert_equal(@c.row.worksheet.merged_cells.last, "A1:A2")
|
195
|
+
assert_equal(@c.row.worksheet.merged_cells.last, "A1:A2")
|
185
196
|
end
|
186
197
|
|
187
198
|
def test_merge_with_cell
|
@@ -189,7 +200,7 @@ class TestCell < Test::Unit::TestCase
|
|
189
200
|
@c.row.add_cell 2
|
190
201
|
@c.row.add_cell 3
|
191
202
|
@c.merge @row.cells.last
|
192
|
-
assert_equal(@c.row.worksheet.merged_cells.last, "A1:C1")
|
203
|
+
assert_equal(@c.row.worksheet.merged_cells.last, "A1:C1")
|
193
204
|
end
|
194
205
|
|
195
206
|
def test_equality
|
@@ -203,5 +214,24 @@ class TestCell < Test::Unit::TestCase
|
|
203
214
|
|
204
215
|
end
|
205
216
|
|
217
|
+
def test_ssti
|
218
|
+
assert_raise(ArgumentError, "ssti must be an unsigned integer!") { @c.send(:ssti=, -1) }
|
219
|
+
@c.send :ssti=, 1
|
220
|
+
assert_equal(@c.ssti, 1)
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_to_xml
|
224
|
+
# TODO This could use some much more stringent testing related to the xml content generated!
|
225
|
+
row = @ws.add_row [Time.now, Date.today, true, 1, 1.0, "text", "=sum(A1:A2)"]
|
226
|
+
schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD))
|
227
|
+
doc = Nokogiri::XML(@ws.to_xml)
|
228
|
+
errors = []
|
229
|
+
schema.validate(doc).each do |error|
|
230
|
+
errors.push error
|
231
|
+
puts error.message
|
232
|
+
end
|
233
|
+
assert(errors.empty?, "error free validation")
|
234
|
+
|
235
|
+
end
|
206
236
|
|
207
237
|
end
|