axlsx 1.0.17 → 1.0.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 sheet.
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.drawing :"r:id"=>"rId1" if @drawing
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
- def update_auto_fit_data(cells)
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
- # ignore formula - there is no way for us to know the result
319
- next if item.value.is_a?(String) && item.value.start_with?('=')
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
@@ -41,9 +41,9 @@ class TestChart < Test::Unit::TestCase
41
41
 
42
42
  end
43
43
 
44
- def end_at
44
+ def test_end_at
45
45
  @chart.end_at 25, 90
46
- assert_equal(@chart.graphic_frame.anchor.from.col, 25)
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
- def teardown
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
@@ -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