axlsx 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. data/.yardopts +3 -2
  2. data/CHANGELOG.md +34 -1
  3. data/README.md +36 -30
  4. data/Rakefile +1 -1
  5. data/examples/auto_filter.rb +16 -0
  6. data/examples/auto_filter.xlsx +0 -0
  7. data/examples/basic_charts.rb +4 -0
  8. data/examples/example.rb +41 -13
  9. data/examples/example.xlsx +0 -0
  10. data/examples/example_streamed.xlsx +0 -0
  11. data/examples/extractive.xlsx +0 -0
  12. data/examples/hyperlinks.rb +23 -0
  13. data/examples/hyperlinks.xlsx +0 -0
  14. data/examples/no-use_autowidth.xlsx +0 -0
  15. data/examples/page_setup.rb +11 -0
  16. data/examples/page_setup.xlsx +0 -0
  17. data/examples/shared_strings_example.xlsx +0 -0
  18. data/examples/skydrive/axlsx.csv +1 -0
  19. data/examples/skydrive/axlsx.xlsx +0 -0
  20. data/examples/skydrive/real_example.rb +8 -8
  21. data/examples/sprk2012/Screen Shot 2012-09-11 at 10.42.06 PM.png +0 -0
  22. data/examples/sprk2012/Screen Shot 2012-09-11 at 11.07.48 PM.png +0 -0
  23. data/examples/sprk2012/Screen Shot 2012-09-11 at 8.31.50 PM.png +0 -0
  24. data/examples/sprk2012/Screen Shot 2012-09-11 at 9.23.27 PM.png +0 -0
  25. data/examples/sprk2012/Screen Shot 2012-09-11 at 9.32.06 PM.png +0 -0
  26. data/examples/sprk2012/Screen Shot 2012-09-11 at 9.33.35 PM.png +0 -0
  27. data/examples/sprk2012/Screen Shot 2012-09-11 at 9.46.44 PM.png +0 -0
  28. data/examples/sprk2012/Screen Shot 2012-09-12 at 5.07.23 PM.png +0 -0
  29. data/examples/sprk2012/basics.rb +11 -0
  30. data/examples/sprk2012/basics.xlsx +0 -0
  31. data/examples/sprk2012/gravatar.jpeg +0 -0
  32. data/examples/sprk2012/hair_club.jpg +0 -0
  33. data/examples/sprk2012/images.rb +9 -0
  34. data/examples/sprk2012/images.xlsx +0 -0
  35. data/examples/sprk2012/line_chart.rb +56 -0
  36. data/examples/sprk2012/line_chart.xlsx +0 -0
  37. data/examples/sprk2012/sprk2012.key +0 -0
  38. data/examples/sprk2012/styles.rb +20 -0
  39. data/examples/sprk2012/styles.xlsx +0 -0
  40. data/examples/styles.rb +62 -0
  41. data/examples/styles.xlsx +0 -0
  42. data/lib/axlsx/doc_props/app.rb +3 -3
  43. data/lib/axlsx/drawing/axis.rb +1 -1
  44. data/lib/axlsx/drawing/view_3D.rb +1 -1
  45. data/lib/axlsx/package.rb +0 -1
  46. data/lib/axlsx/stylesheet/styles.rb +10 -1
  47. data/lib/axlsx/util/constants.rb +105 -4
  48. data/lib/axlsx/util/simple_typed_list.rb +3 -1
  49. data/lib/axlsx/util/validators.rb +26 -8
  50. data/lib/axlsx/version.rb +2 -2
  51. data/lib/axlsx/workbook/workbook.rb +6 -1
  52. data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +77 -0
  53. data/lib/axlsx/workbook/worksheet/auto_filter/filter_column.rb +102 -0
  54. data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +253 -0
  55. data/lib/axlsx/workbook/worksheet/cell.rb +10 -5
  56. data/lib/axlsx/workbook/worksheet/date_time_converter.rb +1 -1
  57. data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +47 -0
  58. data/lib/axlsx/workbook/worksheet/page_setup.rb +135 -7
  59. data/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb +49 -0
  60. data/lib/axlsx/workbook/worksheet/sheet_pr.rb +87 -4
  61. data/lib/axlsx/workbook/worksheet/table.rb +8 -1
  62. data/lib/axlsx/workbook/worksheet/table_style_info.rb +68 -0
  63. data/lib/axlsx/workbook/worksheet/worksheet.rb +45 -7
  64. data/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +101 -0
  65. data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +38 -0
  66. data/lib/axlsx.rb +8 -1
  67. data/test/stylesheet/tc_styles.rb +13 -0
  68. data/test/tc_package.rb +1 -0
  69. data/test/util/tc_validators.rb +8 -1
  70. data/test/workbook/worksheet/auto_filter/tc_auto_filter.rb +38 -0
  71. data/test/workbook/worksheet/auto_filter/tc_filter_column.rb +76 -0
  72. data/test/workbook/worksheet/auto_filter/tc_filters.rb +50 -0
  73. data/test/workbook/worksheet/tc_cell.rb +23 -1
  74. data/test/workbook/worksheet/tc_page_set_up_pr.rb +15 -0
  75. data/test/workbook/worksheet/tc_page_setup.rb +6 -1
  76. data/test/workbook/worksheet/tc_sheet_calc_pr.rb +18 -0
  77. data/test/workbook/worksheet/tc_sheet_pr.rb +27 -0
  78. data/test/workbook/worksheet/{table/tc_table.rb → tc_table.rb} +6 -1
  79. data/test/workbook/worksheet/tc_table_style_info.rb +53 -0
  80. data/test/workbook/worksheet/tc_worksheet.rb +17 -3
  81. data/test/workbook/worksheet/tc_worksheet_hyperlink.rb +64 -0
  82. metadata +59 -6
  83. data/lib/axlsx/workbook/worksheet/auto_filter.rb +0 -34
@@ -28,6 +28,7 @@ module Axlsx
28
28
  @sheet = sheet
29
29
  @style = nil
30
30
  @sheet.workbook.tables << self
31
+ @table_style_info = TableStyleInfo.new(options[:style_info]) if options[:style_info]
31
32
  @name = "Table#{index+1}"
32
33
  options.each do |o|
33
34
  self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
@@ -62,6 +63,12 @@ module Axlsx
62
63
  @name = v
63
64
  end
64
65
  end
66
+
67
+ # TableStyleInfo for the table.
68
+ # initialization can be fed via the :style_info option
69
+ def table_style_info
70
+ @table_style_info ||= TableStyleInfo.new
71
+ end
65
72
 
66
73
  # Serializes the object
67
74
  # @param [String] str
@@ -77,7 +84,7 @@ module Axlsx
77
84
  end
78
85
  str << '</tableColumns>'
79
86
  #TODO implement tableStyleInfo
80
- str << '<tableStyleInfo showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0" name="TableStyleMedium9" />'
87
+ table_style_info.to_xml_string(str) # '<tableStyleInfo showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0" name="TableStyleMedium9" />'
81
88
  str << '</table>'
82
89
  end
83
90
 
@@ -0,0 +1,68 @@
1
+ module Axlsx
2
+
3
+ # The table style info class manages style attributes for defined tables in
4
+ # a worksheet
5
+ class TableStyleInfo
6
+
7
+ # boolean attributes for this object
8
+ BOOLEAN_ATTRIBUTES = %w(show_first_column show_last_column show_row_stripes show_column_stripes)
9
+
10
+ # creates a new TableStyleInfo instance
11
+ # @param [Hash] options
12
+ # @option [Boolean] show_first_column indicates if the first column should
13
+ # be shown
14
+ # @option [Boolean] show_last_column indicates if the last column should
15
+ # be shown
16
+ # @option [Boolean] show_column_stripes indicates if column stripes should
17
+ # be shown
18
+ # @option [Boolean] show_row_stripes indicates if row stripes should be shown
19
+ # @option [String] name The name of the style to apply to your table.
20
+ # Only predefined styles are currently supported.
21
+ # @see Annex G. (normative) Predefined SpreadsheetML Style Definitions in part 1 of the specification.
22
+ def initialize(options = {})
23
+ initialize_defaults
24
+ @name = 'TableStyleMedium9'
25
+ options.each do |k, v|
26
+ send("#{k}=", v) if respond_to? "#{k}="
27
+ end
28
+ end
29
+
30
+ # Dynamically create accessors for boolean attriubtes
31
+ BOOLEAN_ATTRIBUTES.each do |attr|
32
+ class_eval %{
33
+ # The #{attr} attribute reader
34
+ # @return [Boolean]
35
+ attr_reader :#{attr}
36
+
37
+ # The #{attr} writer
38
+ # @param [Boolean] value The value to assign to #{attr}
39
+ # @return [Boolean]
40
+ def #{attr}=(value)
41
+ Axlsx::validate_boolean(value)
42
+ @#{attr} = value
43
+ end
44
+ }
45
+ end
46
+
47
+ # Initialize all the values to false as Excel requires them to
48
+ # explicitly be disabled or all will show.
49
+ def initialize_defaults
50
+ BOOLEAN_ATTRIBUTES.each do |attr|
51
+ self.send("#{attr}=", 0)
52
+ end
53
+ end
54
+
55
+ # The name of the table style.
56
+ attr_accessor :name
57
+
58
+ # seralizes this object to an xml string
59
+ # @param [String] str the string to contact this objects serialization to.
60
+ def to_xml_string(str = '')
61
+ str << '<tableStyleInfo '
62
+ instance_values.each do |key, value|
63
+ str << Axlsx::camel(key, false) << "='#{value}' "
64
+ end
65
+ str << '/>'
66
+ end
67
+ end
68
+ end
@@ -42,6 +42,12 @@ module Axlsx
42
42
  def name
43
43
  @name ||= "Sheet" + (index+1).to_s
44
44
  end
45
+
46
+ # The sheet calculation properties
47
+ # @return [SheetCalcPr]
48
+ def sheet_calc_pr
49
+ @sheet_calc_pr ||= SheetCalcPr.new
50
+ end
45
51
 
46
52
  # The sheet protection object for this workbook
47
53
  # @return [SheetProtection]
@@ -70,7 +76,13 @@ module Axlsx
70
76
  def tables
71
77
  @tables ||= Tables.new self
72
78
  end
73
-
79
+
80
+ # A typed collection of hyperlinks associated with this worksheet
81
+ # @return [WorksheetHyperlinks]
82
+ def hyperlinks
83
+ @hyperlinks ||= WorksheetHyperlinks.new self
84
+ end
85
+
74
86
  # The a shortcut to the worksheet_comments list of comments
75
87
  # @return [Array|SimpleTypedList]
76
88
  def comments
@@ -391,6 +403,14 @@ module Axlsx
391
403
  data_validations << dv
392
404
  end
393
405
 
406
+ # Adds a new hyperlink to the worksheet
407
+ # @param [Hash] options for the hyperlink
408
+ # @see WorksheetHyperlink for a list of options
409
+ # @return [WorksheetHyperlink]
410
+ def add_hyperlink(options={})
411
+ hyperlinks.add(options)
412
+ end
413
+
394
414
  # 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.
395
415
  # @param [Class] chart_type
396
416
  # @option options [Array] start_at
@@ -477,25 +497,43 @@ module Axlsx
477
497
  # This intentionally does not use nokogiri for performance reasons
478
498
  # @return [String]
479
499
  def to_xml_string
500
+ auto_filter.apply if auto_filter.range
480
501
  str = '<?xml version="1.0" encoding="UTF-8"?>'
481
502
  str << worksheet_node
482
503
  serializable_parts.each do |item|
483
504
  item.to_xml_string(str) if item
484
505
  end
485
506
  str << '</worksheet>'
486
- str.gsub(/[[:cntrl:]]/,'')
507
+ sanitize(str)
487
508
  end
488
509
 
510
+ # returns the provided string with all invalid control charaters
511
+ # removed.
512
+ # @param [String] str The sting to process
513
+ # @return [String]
514
+ def sanitize(str)
515
+ str.gsub(CONTROL_CHAR_REGEX, '')
516
+ end
517
+
489
518
  # The worksheet relationships. This is managed automatically by the worksheet
490
519
  # @return [Relationships]
491
520
  def relationships
492
521
  r = Relationships.new
493
- r + [tables.relationships,
494
- worksheet_comments.relationships,
522
+ r + [tables.relationships,
523
+ worksheet_comments.relationships,
524
+ hyperlinks.relationships,
495
525
  worksheet_drawing.relationship].flatten.compact || []
496
526
  r
497
527
  end
498
528
 
529
+ # identifies the index of an object withing the collections used in generating relationships for the worksheet
530
+ # @param [Any] object the object to search for
531
+ # @return [Integer] The index of the object
532
+ def relationships_index_of(object)
533
+ objects = [tables.to_a, worksheet_comments.comments.to_a, hyperlinks.to_a, worksheet_drawing.drawing].flatten.compact || []
534
+ objects.index(object)
535
+ end
536
+
499
537
  # Returns the cell or cells defined using excel style A1:B3 references.
500
538
  # @param [String|Integer] cell_def the string defining the cell or range of cells, or the rownumber
501
539
  # @return [Cell, Array]
@@ -533,7 +571,7 @@ module Axlsx
533
571
 
534
572
 
535
573
  private
536
-
574
+
537
575
  def validate_sheet_name(name)
538
576
  DataTypeValidator.validate "Worksheet.name", String, name
539
577
  raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG % name) if name.size > 31
@@ -546,9 +584,9 @@ module Axlsx
546
584
 
547
585
  def serializable_parts
548
586
  [sheet_pr, dimension, sheet_view, column_info,
549
- sheet_data, @sheet_protection, protected_ranges,
587
+ sheet_data, sheet_calc_pr, @sheet_protection, protected_ranges,
550
588
  auto_filter, merged_cells, conditional_formattings,
551
- data_validations, print_options, page_margins,
589
+ data_validations, hyperlinks, print_options, page_margins,
552
590
  page_setup, worksheet_drawing, worksheet_comments,
553
591
  tables]
554
592
  end
@@ -0,0 +1,101 @@
1
+ module Axlsx
2
+
3
+ # A worksheet hyperlink object. Note that this is not the same as a drawing hyperlink object.
4
+ class WorksheetHyperlink
5
+
6
+ # Creates a new hyperlink object.
7
+ # @note the preferred way to add hyperlinks to your worksheet is the Worksheet#add_hyperlink method
8
+ # @param [Worksheet] worksheet the Worksheet that owns this hyperlink
9
+ # @param [Hash] options options to use when creating this hyperlink
10
+ # @option [String] display Display string, if different from string in string table. This is a property on the hyperlink object, but does not need to appear in the spreadsheet application UI.
11
+ # @option [String] location Location within target. If target is a workbook (or this workbook) this shall refer to a sheet and cell or a defined name. Can also be an HTML anchor if target is HTML file.
12
+ # @option [String] tooltip The tip to display when the user positions the mouse cursor over this hyperlink
13
+ # @option [Symbol] target This is :external by default. If you set it to anything else, the location is interpreted to be the current workbook.
14
+ # @option [String|Cell] ref The location of this hyperlink in the worksheet
15
+ def initialize(worksheet, options={})
16
+ DataTypeValidator.validate "Hyperlink.worksheet", [Worksheet], worksheet
17
+ @worksheet = worksheet
18
+ @target = :external
19
+ options.each do |o|
20
+ self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
21
+ end
22
+ yield self if block_given?
23
+ end
24
+
25
+ # String attributes for this object
26
+ STRING_ATTRIBUTES = %w(display location tooltip)
27
+
28
+ #Cell location of hyperlink on worksheet.
29
+ # @return [String]
30
+ attr_reader :ref
31
+
32
+ # Sets the target for this hyperlink. Anything other than :external instructs the library to treat the location as an in-workbook reference.
33
+ # @param [Symbol] target
34
+ def target=(target)
35
+ @target = target
36
+ end
37
+
38
+ # Sets the cell location of this hyperlink in the worksheet
39
+ # @param [String|Cell] cell_reference The string reference or cell that defines where this hyperlink shows in the worksheet.
40
+ def ref=(cell_reference)
41
+ cell_reference = cell_reference.r if cell_reference.is_a?(Cell)
42
+
43
+ Axlsx::validate_string cell_reference
44
+ @ref = cell_reference
45
+ end
46
+
47
+ # Dynamically create string attribute accessors
48
+ STRING_ATTRIBUTES.each do |attr|
49
+ class_eval %{
50
+ # The #{attr} attribute reader
51
+ # @return [String]
52
+ attr_reader :#{attr}
53
+
54
+ # The #{attr} writer
55
+ # @param [String] value The value to assign to #{attr}
56
+ # @return [String]
57
+ def #{attr}=(value)
58
+ Axlsx::validate_string(value)
59
+ @#{attr}= value
60
+ end
61
+ }
62
+ end
63
+
64
+ # The relationship required by this hyperlink when the taget is :external
65
+ # @return [Relationship]
66
+ def relationship
67
+ return unless @target == :external
68
+ Relationship.new HYPERLINK_R, location, :target_mode => :External
69
+ end
70
+
71
+ # The id of the relationship for this object
72
+ # @return [String]
73
+ def id
74
+ return unless @target == :external
75
+ "rId#{(@worksheet.relationships_index_of(self)+1)}"
76
+ end
77
+
78
+ # Seralize the object
79
+ # @param [String] str
80
+ # @return [String]
81
+ def to_xml_string(str='')
82
+ str << '<hyperlink '
83
+ serialization_values.map { |key, value| str << key.to_s << '="' << value.to_s << '" ' }
84
+ str << '/>'
85
+ end
86
+
87
+ # The values to be used in serialization based on the target.
88
+ # location should only be specified for non-external targets.
89
+ # r:id should only be specified for external targets.
90
+ # @return [Hash]
91
+ def serialization_values
92
+ h = instance_values.reject { |key, value| !%w(display ref tooltip).include?(key) }
93
+ if @target == :external
94
+ h['r:id'] = id
95
+ else
96
+ h['location'] = location
97
+ end
98
+ h
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,38 @@
1
+ module Axlsx
2
+
3
+ #A collection of hyperlink objects for a worksheet
4
+ class WorksheetHyperlinks < SimpleTypedList
5
+
6
+ # Creates a new Hyperlinks collection
7
+ # @param [Worksheet] worksheet the worksheet that owns these hyperlinks
8
+ def initialize(worksheet)
9
+ DataTypeValidator.validate "Hyperlinks.worksheet", [Worksheet], worksheet
10
+ @worksheet = worksheet
11
+ super WorksheetHyperlink
12
+ end
13
+
14
+ # Creates and adds a new hyperlink based on the options provided
15
+ # @see WorksheetHyperlink#initialize
16
+ # @return [WorksheetHyperlink]
17
+ def add(options)
18
+ @list << WorksheetHyperlink.new(@worksheet, options)
19
+ @list.last
20
+ end
21
+
22
+ # The relationships required by this collection's hyperlinks
23
+ # @return Array
24
+ def relationships
25
+ return [] if empty?
26
+ map { |hyperlink| hyperlink.relationship }
27
+ end
28
+
29
+ # seralize the collection of hyperlinks
30
+ # @return [String]
31
+ def to_xml_string(str='')
32
+ return if empty?
33
+ str << '<hyperlinks>'
34
+ @list.each { |hyperlink| hyperlink.to_xml_string(str) }
35
+ str << '</hyperlinks>'
36
+ end
37
+ end
38
+ end
data/lib/axlsx.rb CHANGED
@@ -37,7 +37,12 @@ if !Object.respond_to?(:instance_values)
37
37
  end
38
38
  end
39
39
 
40
- # xlsx generation with charts, images, automated column width, customizable styles and full schema validation. Axlsx excels at helping you generate beautiful Office Open XML Spreadsheet documents without having to understand the entire ECMA specification. Check out the README for some examples of how easy it is. Best of all, you can validate your xlsx file before serialization so you know for sure that anything generated is going to load on your client's machine.
40
+ # xlsx generation with charts, images, automated column width, customizable styles
41
+ # and full schema validation. Axlsx excels at helping you generate beautiful
42
+ # Office Open XML Spreadsheet documents without having to understand the entire
43
+ # ECMA specification. Check out the README for some examples of how easy it is.
44
+ # Best of all, you can validate your xlsx file before serialization so you know
45
+ # for sure that anything generated is going to load on your client's machine.
41
46
  module Axlsx
42
47
 
43
48
  # determines the cell range for the items provided
@@ -65,6 +70,7 @@ module Axlsx
65
70
  # returns the x, y position of a cell
66
71
  def self.name_to_indices(name)
67
72
  raise ArgumentError, 'invalid cell name' unless name.size > 1
73
+ # capitalization?!?
68
74
  v = name[/[A-Z]+/].reverse.chars.reduce({:base=>1, :i=>0}) do |val, c|
69
75
  val[:i] += ((c.bytes.first - 64) * val[:base]); val[:base] *= 26; val
70
76
  end
@@ -95,6 +101,7 @@ module Axlsx
95
101
  # @param [String] s The snake case string to camelize
96
102
  # @return [String]
97
103
  def self.camel(s="", all_caps = true)
104
+ s = s.to_s
98
105
  s = s.capitalize if all_caps
99
106
  s.gsub(/_(.)/){ $1.upcase }
100
107
  end
@@ -105,6 +105,19 @@ class TestStyles < Test::Unit::TestCase
105
105
  assert(@styles.parse_alignment_options(:alignment => {}).is_a?(Axlsx::CellAlignment))
106
106
  end
107
107
 
108
+ def test_parse_font_using_defaults
109
+ original = @styles.fonts.first
110
+ @styles.add_style :b => 1, :sz => 99
111
+ created = @styles.fonts.last
112
+ original_attributes = original.instance_values
113
+ assert_equal(1, created.b)
114
+ assert_equal(99, created.sz)
115
+ copied = original_attributes.reject{ |key, value| %w(b sz).include? key }
116
+ copied.each do |key, value|
117
+ assert_equal(created.instance_values[key], value)
118
+ end
119
+ end
120
+
108
121
  def test_parse_font_options
109
122
  options = {
110
123
  :fg_color => "FF050505",
data/test/tc_package.rb CHANGED
@@ -7,6 +7,7 @@ class TestPackage < Test::Unit::TestCase
7
7
  ws = @package.workbook.add_worksheet
8
8
  ws.add_row ['Can', 'we', 'build it?']
9
9
  ws.add_row ['Yes!', 'We', 'can!']
10
+ ws.add_hyperlink :ref => ws.rows.first.cells.last, :location => 'https://github.com/randym'
10
11
  ws.workbook.add_defined_name("#{ws.name}!A1:C2", :name => '_xlnm.Print_Titles', :hidden => true)
11
12
  ws.protect_range('A1:C1')
12
13
  ws.protect_range(ws.rows.last.cells)
@@ -158,4 +158,11 @@ class TestValidators < Test::Unit::TestCase
158
158
  assert_raise(ArgumentError) { Axlsx.validate_split_state_type 'frozen_split' }
159
159
  assert_raise(ArgumentError) { Axlsx.validate_split_state_type 0 }
160
160
  end
161
- end
161
+
162
+ def test_range_validation
163
+ # exclusive
164
+ assert_raise(ArgumentError) { Axlsx::RangeValidator.validate('foo', 1, 10, 10, false) }
165
+ # inclusive by default
166
+ assert_nothing_raised { Axlsx::RangeValidator.validate('foo', 1, 10, 10) }
167
+ end
168
+ end
@@ -0,0 +1,38 @@
1
+ require 'tc_helper.rb'
2
+
3
+ class TestAutoFilter < Test::Unit::TestCase
4
+
5
+ def setup
6
+ ws = Axlsx::Package.new.workbook.add_worksheet
7
+ 3.times { |index| ws.add_row [1*index,2*index,3*index] }
8
+ @auto_filter = ws.auto_filter
9
+ @auto_filter.range = 'A1:C3'
10
+ @auto_filter.add_column 0, :filters, :filter_items => [1]
11
+ end
12
+
13
+ def test_defined_name
14
+ assert_equal("'Sheet1'!$A$1:$C$3", @auto_filter.defined_name)
15
+ end
16
+
17
+ def test_to_xml_string
18
+ doc = Nokogiri::XML(@auto_filter.to_xml_string)
19
+ assert(doc.xpath("autoFilter[@ref='#{@auto_filter.range}']"))
20
+ end
21
+
22
+ def test_columns
23
+ assert @auto_filter.columns.is_a?(Axlsx::SimpleTypedList)
24
+ assert_equal @auto_filter.columns.allowed_types, [Axlsx::FilterColumn]
25
+ end
26
+
27
+ def test_add_column
28
+ @auto_filter.add_column(0, :filters) do |column|
29
+ assert column.is_a? FilterColumn
30
+ end
31
+ end
32
+
33
+ def test_applya
34
+ assert_equal nil, @auto_filter.worksheet.rows.last.hidden
35
+ @auto_filter.apply
36
+ assert_equal true, @auto_filter.worksheet.rows.last.hidden
37
+ end
38
+ end
@@ -0,0 +1,76 @@
1
+ require 'tc_helper.rb'
2
+
3
+ class TestFilterColumn < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @filter_column = Axlsx::FilterColumn.new(0, :filters, :filter_items => [200])
7
+ end
8
+
9
+
10
+ def test_initialize_col_id
11
+ assert_raise ArgumentError do
12
+ Axlsx::FilterColumn.new(0, :bobs_house_of_filter)
13
+ end
14
+ assert_raise ArgumentError do
15
+ Axlsx::FilterColumn.new(:penut, :filters)
16
+ end
17
+ end
18
+
19
+ def test_initailize_filter_type
20
+ assert @filter_column.filter.is_a?(Axlsx::Filters)
21
+ assert_equal 1, @filter_column.filter.filter_items.size
22
+ end
23
+
24
+ def test_initialize_filter_type_filters_with_options
25
+ assert_equal 200, @filter_column.filter.filter_items.first.val
26
+ end
27
+
28
+ def test_initialize_with_block
29
+ filter_column = Axlsx::FilterColumn.new(0, :filters) do |filters|
30
+ filters.filter_items = [700, 100, 5]
31
+ end
32
+ assert_equal 3, filter_column.filter.filter_items.size
33
+ assert_equal 700, filter_column.filter.filter_items.first.val
34
+ assert_equal 5, filter_column.filter.filter_items.last.val
35
+ end
36
+
37
+ def test_default_show_button
38
+ assert_equal true, @filter_column.show_button
39
+ end
40
+
41
+ def test_default_hidden_button
42
+ assert_equal false, @filter_column.hidden_button
43
+ end
44
+
45
+ def test_show_button
46
+ assert_raise ArgumentError do
47
+ @filter_column.show_button = :foo
48
+ end
49
+ assert_nothing_raised { @filter_column.show_button = false }
50
+ end
51
+
52
+ def test_hidden_button
53
+ assert_raise ArgumentError do
54
+ @filter_column.hidden_button = :hoge
55
+ end
56
+ assert_nothing_raised { @filter_column.hidden_button = true }
57
+ end
58
+
59
+ def test_col_id=
60
+ assert_raise ArgumentError do
61
+ @filter_column.col_id = :bar
62
+ end
63
+ assert_nothing_raised { @filter_column.col_id = 7 }
64
+ end
65
+
66
+ def test_to_xml_string
67
+ doc = Nokogiri::XML(@filter_column.to_xml_string)
68
+ assert doc.xpath("//filterColumn[@colId=#{@filter_column.col_id}]")
69
+ assert doc.xpath("//filterColumn[@hiddenButton=#{@filter_column.hidden_button}]")
70
+ assert doc.xpath("//filterColumn[@showButton=#{@filter_column.show_button}]")
71
+
72
+
73
+
74
+ assert doc.xpath("//filterColumn/filters")
75
+ end
76
+ end
@@ -0,0 +1,50 @@
1
+ require 'tc_helper.rb'
2
+
3
+ class TestFilters < Test::Unit::TestCase
4
+ def setup
5
+ @filters = Axlsx::Filters.new(:filter_items => [1, 'a'],
6
+ :date_group_items =>[ { :date_time_grouping => :year, :year => 2011, :month => 11, :day => 11, :hour => 0, :minute => 0, :second => 0 } ] ,
7
+ :blank => true)
8
+ end
9
+
10
+ def test_blank
11
+ assert_equal true, @filters.blank
12
+ assert_raise(ArgumentError) { @filters.blank = :only_if_you_want_it }
13
+ @filters.blank = true
14
+ assert_equal true, @filters.blank
15
+ end
16
+
17
+ def test_calendar_type
18
+ assert_raise(ArgumentError) { @filters.calendar_type = 'monkey calendar' }
19
+ @filters.calendar_type = 'japan'
20
+ assert_equal('japan', @filters.calendar_type)
21
+ end
22
+
23
+ def test_filters_items
24
+ assert @filters.filter_items.is_a?(Array)
25
+ assert_equal 2, @filters.filter_items.size
26
+ end
27
+
28
+ def test_date_group_items
29
+ assert @filters.date_group_items.is_a?(Array)
30
+ assert_equal 1, @filters.date_group_items.size
31
+ end
32
+
33
+ def test_apply_is_false_for_matching_values
34
+ keeper = Object.new
35
+ def keeper.value; 'a'; end
36
+ assert_equal false, @filters.apply(keeper)
37
+ end
38
+
39
+ def test_apply_is_true_for_non_matching_values
40
+ hidden = Object.new
41
+ def hidden.value; 'b'; end
42
+ assert_equal true, @filters.apply(hidden)
43
+ end
44
+
45
+ def test_to_xml_string
46
+ doc = Nokogiri::XML(@filters.to_xml_string)
47
+ assert_equal(1, doc.xpath('//filters[@blank="true"]').size)
48
+ end
49
+ end
50
+
@@ -60,7 +60,7 @@ class TestCell < Test::Unit::TestCase
60
60
  assert_raise(ArgumentError, "type must be :string, :integer, :float, :date, :time, :boolean") { @c.type = :array }
61
61
  assert_nothing_raised("type can be changed") { @c.type = :string }
62
62
  assert_equal(@c.value, "1.0", "changing type casts the value")
63
-
63
+ assert_equal(:float, @row.add_cell(1.0/10**7).type, 'properly identify exponential floats as float type')
64
64
  assert_equal(@row.add_cell(Time.now).type, :time, 'time should be time')
65
65
  assert_equal(@row.add_cell(Date.today).type, :date, 'date should be date')
66
66
  assert_equal(@row.add_cell(true).type, :boolean, 'boolean should be boolean')
@@ -88,6 +88,7 @@ class TestCell < Test::Unit::TestCase
88
88
  assert_equal(@c.send(:cell_type_from_value, -1), :integer)
89
89
  assert_equal(@c.send(:cell_type_from_value, true), :boolean)
90
90
  assert_equal(@c.send(:cell_type_from_value, false), :boolean)
91
+ assert_equal(@c.send(:cell_type_from_value, 1.0/10**6), :float)
91
92
  end
92
93
 
93
94
  def test_cast_value
@@ -268,6 +269,27 @@ class TestCell < Test::Unit::TestCase
268
269
 
269
270
  end
270
271
 
272
+ def test_font_size_with_custom_style_and_no_sz
273
+ @c.style = @c.row.worksheet.workbook.styles.add_style :bg_color => 'FF00FF'
274
+ sz = @c.send(:font_size)
275
+ assert_equal(sz, @c.row.worksheet.workbook.styles.fonts.first.sz)
276
+ end
277
+
278
+ def test_font_size_with_bolding
279
+ @c.style = @c.row.worksheet.workbook.styles.add_style :b => true
280
+ assert_equal(@c.row.worksheet.workbook.styles.fonts.first.sz * 1.5, @c.send(:font_size))
281
+ end
282
+
283
+ def test_font_size_with_custom_sz
284
+ @c.style = @c.row.worksheet.workbook.styles.add_style :sz => 52
285
+ sz = @c.send(:font_size)
286
+ assert_equal(sz, 52)
287
+ end
288
+
289
+ def test_cell_with_sz
290
+ @c.sz = 25
291
+ assert_equal(25, @c.send(:font_size))
292
+ end
271
293
  def test_to_xml
272
294
  # TODO This could use some much more stringent testing related to the xml content generated!
273
295
  @ws.add_row [Time.now, Date.today, true, 1, 1.0, "text", "=sum(A1:A2)"]
@@ -0,0 +1,15 @@
1
+ require 'tc_helper.rb'
2
+
3
+ class TestPageSetUpPr < Test::Unit::TestCase
4
+ def setup
5
+ @page_setup_pr = Axlsx::PageSetUpPr.new(:fit_to_page => true, :auto_page_breaks => true)
6
+ end
7
+
8
+ def test_fit_to_page
9
+ assert_equal true, @page_setup_pr.fit_to_page
10
+ end
11
+
12
+ def test_auto_page_breaks
13
+ assert_equal true, @page_setup_pr.auto_page_breaks
14
+ end
15
+ end
@@ -44,6 +44,11 @@ class TestPageSetup < Test::Unit::TestCase
44
44
  assert_equal(50, @ps.scale)
45
45
  end
46
46
 
47
+ def test_paper_size
48
+ assert_raise(ArgumentError) { @ps.paper_size = 119 }
49
+ assert_nothing_raised { @ps.paper_size = 10 }
50
+ end
51
+
47
52
  def test_set_some_values
48
53
  @ps.set(:fit_to_width => 2, :orientation => :portrait)
49
54
  assert_equal(2, @ps.fit_to_width)
@@ -58,7 +63,7 @@ class TestPageSetup < Test::Unit::TestCase
58
63
  assert(@ps.fit_to_width == nil && @ps.fit_to_height == nil)
59
64
  assert(@ps.fit_to_page? == false)
60
65
  end
61
-
66
+
62
67
  def test_with_height_fit_to_page?
63
68
  assert(@ps.fit_to_width == nil && @ps.fit_to_height == nil)
64
69
  @ps.set(:fit_to_height => 1)