axlsx 2.0.1 → 2.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -3
  3. data/Rakefile +9 -10
  4. data/examples/IMAGE1UP.JPEG +0 -0
  5. data/examples/auto_filter.rb +10 -1
  6. data/examples/conditional_formatting/example_conditional_formatting.rb +3 -3
  7. data/examples/example.rb +72 -4
  8. data/examples/merge_cells.rb +17 -0
  9. data/examples/no_grid_with_borders.rb +18 -0
  10. data/examples/pivot_test.rb +63 -0
  11. data/examples/split.rb +16 -0
  12. data/lib/axlsx.rb +30 -16
  13. data/lib/axlsx/content_type/abstract_content_type.rb +1 -1
  14. data/lib/axlsx/content_type/content_type.rb +1 -1
  15. data/lib/axlsx/doc_props/app.rb +1 -1
  16. data/lib/axlsx/doc_props/core.rb +5 -5
  17. data/lib/axlsx/drawing/axes.rb +1 -1
  18. data/lib/axlsx/drawing/axis.rb +12 -9
  19. data/lib/axlsx/drawing/bar_3D_chart.rb +13 -13
  20. data/lib/axlsx/drawing/bar_series.rb +9 -9
  21. data/lib/axlsx/drawing/bubble_chart.rb +59 -0
  22. data/lib/axlsx/drawing/bubble_series.rb +63 -0
  23. data/lib/axlsx/drawing/cat_axis.rb +5 -5
  24. data/lib/axlsx/drawing/chart.rb +44 -7
  25. data/lib/axlsx/drawing/drawing.rb +3 -1
  26. data/lib/axlsx/drawing/graphic_frame.rb +3 -3
  27. data/lib/axlsx/drawing/hyperlink.rb +1 -3
  28. data/lib/axlsx/drawing/line_3D_chart.rb +2 -2
  29. data/lib/axlsx/drawing/line_chart.rb +10 -10
  30. data/lib/axlsx/drawing/line_series.rb +14 -2
  31. data/lib/axlsx/drawing/marker.rb +1 -1
  32. data/lib/axlsx/drawing/num_data.rb +4 -4
  33. data/lib/axlsx/drawing/num_data_source.rb +6 -6
  34. data/lib/axlsx/drawing/num_val.rb +1 -1
  35. data/lib/axlsx/drawing/one_cell_anchor.rb +1 -1
  36. data/lib/axlsx/drawing/pic.rb +2 -3
  37. data/lib/axlsx/drawing/picture_locking.rb +1 -3
  38. data/lib/axlsx/drawing/pie_3D_chart.rb +5 -6
  39. data/lib/axlsx/drawing/pie_series.rb +6 -6
  40. data/lib/axlsx/drawing/scaling.rb +4 -4
  41. data/lib/axlsx/drawing/scatter_chart.rb +10 -10
  42. data/lib/axlsx/drawing/scatter_series.rb +26 -7
  43. data/lib/axlsx/drawing/ser_axis.rb +2 -2
  44. data/lib/axlsx/drawing/series.rb +3 -3
  45. data/lib/axlsx/drawing/series_title.rb +2 -2
  46. data/lib/axlsx/drawing/str_data.rb +3 -3
  47. data/lib/axlsx/drawing/str_val.rb +1 -1
  48. data/lib/axlsx/drawing/title.rb +3 -3
  49. data/lib/axlsx/drawing/val_axis.rb +1 -1
  50. data/lib/axlsx/drawing/vml_drawing.rb +1 -1
  51. data/lib/axlsx/package.rb +39 -28
  52. data/lib/axlsx/rels/relationship.rb +1 -1
  53. data/lib/axlsx/rels/relationships.rb +2 -2
  54. data/lib/axlsx/stylesheet/border_pr.rb +2 -2
  55. data/lib/axlsx/stylesheet/cell_alignment.rb +1 -3
  56. data/lib/axlsx/stylesheet/cell_protection.rb +1 -3
  57. data/lib/axlsx/stylesheet/cell_style.rb +1 -3
  58. data/lib/axlsx/stylesheet/color.rb +1 -3
  59. data/lib/axlsx/stylesheet/font.rb +1 -1
  60. data/lib/axlsx/stylesheet/gradient_stop.rb +1 -1
  61. data/lib/axlsx/stylesheet/num_fmt.rb +1 -3
  62. data/lib/axlsx/stylesheet/pattern_fill.rb +1 -1
  63. data/lib/axlsx/stylesheet/styles.rb +6 -6
  64. data/lib/axlsx/stylesheet/table_style_element.rb +1 -3
  65. data/lib/axlsx/util/accessors.rb +6 -6
  66. data/lib/axlsx/util/constants.rb +106 -101
  67. data/lib/axlsx/util/options_parser.rb +2 -1
  68. data/lib/axlsx/util/parser.rb +4 -4
  69. data/lib/axlsx/util/serialized_attributes.rb +16 -6
  70. data/lib/axlsx/util/simple_typed_list.rb +28 -52
  71. data/lib/axlsx/util/storage.rb +4 -4
  72. data/lib/axlsx/util/string.rb +7 -0
  73. data/lib/axlsx/util/validators.rb +20 -13
  74. data/lib/axlsx/version.rb +1 -1
  75. data/lib/axlsx/workbook/defined_name.rb +11 -12
  76. data/lib/axlsx/workbook/defined_names.rb +2 -2
  77. data/lib/axlsx/workbook/shared_strings_table.rb +5 -5
  78. data/lib/axlsx/workbook/workbook.rb +19 -12
  79. data/lib/axlsx/workbook/workbook_view.rb +78 -0
  80. data/lib/axlsx/workbook/workbook_views.rb +22 -0
  81. data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +2 -2
  82. data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +1 -3
  83. data/lib/axlsx/workbook/worksheet/break.rb +1 -3
  84. data/lib/axlsx/workbook/worksheet/cell.rb +128 -73
  85. data/lib/axlsx/workbook/worksheet/cell_serializer.rb +50 -40
  86. data/lib/axlsx/workbook/worksheet/cfvo.rb +1 -3
  87. data/lib/axlsx/workbook/worksheet/cfvos.rb +1 -1
  88. data/lib/axlsx/workbook/worksheet/col.rb +7 -10
  89. data/lib/axlsx/workbook/worksheet/col_breaks.rb +2 -2
  90. data/lib/axlsx/workbook/worksheet/comment.rb +5 -6
  91. data/lib/axlsx/workbook/worksheet/comments.rb +9 -12
  92. data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +1 -1
  93. data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +1 -1
  94. data/lib/axlsx/workbook/worksheet/data_bar.rb +4 -6
  95. data/lib/axlsx/workbook/worksheet/data_validation.rb +6 -4
  96. data/lib/axlsx/workbook/worksheet/dimension.rb +2 -2
  97. data/lib/axlsx/workbook/worksheet/header_footer.rb +6 -8
  98. data/lib/axlsx/workbook/worksheet/icon_set.rb +3 -5
  99. data/lib/axlsx/workbook/worksheet/merged_cells.rb +2 -2
  100. data/lib/axlsx/workbook/worksheet/page_margins.rb +1 -3
  101. data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +1 -1
  102. data/lib/axlsx/workbook/worksheet/page_setup.rb +21 -23
  103. data/lib/axlsx/workbook/worksheet/pane.rb +1 -3
  104. data/lib/axlsx/workbook/worksheet/pivot_table.rb +17 -24
  105. data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +4 -4
  106. data/lib/axlsx/workbook/worksheet/print_options.rb +1 -3
  107. data/lib/axlsx/workbook/worksheet/protected_range.rb +1 -3
  108. data/lib/axlsx/workbook/worksheet/protected_ranges.rb +1 -1
  109. data/lib/axlsx/workbook/worksheet/rich_text.rb +35 -0
  110. data/lib/axlsx/workbook/worksheet/rich_text_run.rb +254 -0
  111. data/lib/axlsx/workbook/worksheet/row.rb +33 -51
  112. data/lib/axlsx/workbook/worksheet/row_breaks.rb +2 -2
  113. data/lib/axlsx/workbook/worksheet/selection.rb +1 -3
  114. data/lib/axlsx/workbook/worksheet/sheet_data.rb +3 -1
  115. data/lib/axlsx/workbook/worksheet/sheet_protection.rb +1 -3
  116. data/lib/axlsx/workbook/worksheet/table.rb +6 -6
  117. data/lib/axlsx/workbook/worksheet/table_style_info.rb +1 -3
  118. data/lib/axlsx/workbook/worksheet/tables.rb +1 -1
  119. data/lib/axlsx/workbook/worksheet/worksheet.rb +59 -30
  120. data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +3 -3
  121. data/test/drawing/tc_axis.rb +27 -0
  122. data/test/drawing/tc_bubble_chart.rb +44 -0
  123. data/test/drawing/tc_bubble_series.rb +21 -0
  124. data/test/drawing/tc_data_source.rb +6 -0
  125. data/test/drawing/tc_line_chart.rb +5 -5
  126. data/test/drawing/tc_line_series.rb +10 -2
  127. data/test/drawing/tc_pic.rb +4 -0
  128. data/test/drawing/tc_scatter_series.rb +25 -1
  129. data/test/tc_helper.rb +1 -1
  130. data/test/tc_package.rb +7 -1
  131. data/test/util/tc_simple_typed_list.rb +1 -2
  132. data/test/workbook/tc_defined_name.rb +12 -4
  133. data/test/workbook/tc_workbook.rb +16 -2
  134. data/test/workbook/tc_workbook_view.rb +50 -0
  135. data/test/workbook/worksheet/auto_filter/tc_filters.rb +1 -1
  136. data/test/workbook/worksheet/tc_break.rb +1 -1
  137. data/test/workbook/worksheet/tc_cell.rb +30 -4
  138. data/test/workbook/worksheet/tc_col.rb +2 -2
  139. data/test/workbook/worksheet/tc_conditional_formatting.rb +2 -2
  140. data/test/workbook/worksheet/tc_data_bar.rb +1 -1
  141. data/test/workbook/worksheet/tc_data_validation.rb +11 -11
  142. data/test/workbook/worksheet/tc_header_footer.rb +2 -2
  143. data/test/workbook/worksheet/tc_icon_set.rb +1 -1
  144. data/test/workbook/worksheet/tc_page_setup.rb +3 -3
  145. data/test/workbook/worksheet/tc_print_options.rb +1 -1
  146. data/test/workbook/worksheet/tc_rich_text.rb +44 -0
  147. data/test/workbook/worksheet/tc_rich_text_run.rb +172 -0
  148. data/test/workbook/worksheet/tc_row.rb +2 -2
  149. data/test/workbook/worksheet/tc_sheet_calc_pr.rb +1 -1
  150. data/test/workbook/worksheet/tc_sheet_format_pr.rb +4 -4
  151. data/test/workbook/worksheet/tc_sheet_protection.rb +5 -5
  152. data/test/workbook/worksheet/tc_sheet_view.rb +4 -4
  153. data/test/workbook/worksheet/tc_worksheet.rb +49 -10
  154. metadata +81 -55
  155. data/test/axlsx.qcachegrind +0 -2226
@@ -3,10 +3,10 @@ module Axlsx
3
3
  # A Row is a single row in a worksheet.
4
4
  # @note The recommended way to manage rows and cells is to use Worksheet#add_row
5
5
  # @see Worksheet#add_row
6
- class Row
7
-
6
+ class Row < SimpleTypedList
8
7
  include SerializedAttributes
9
8
  include Accessors
9
+
10
10
  # No support is provided for the following attributes
11
11
  # spans
12
12
  # thickTop
@@ -28,11 +28,10 @@ module Axlsx
28
28
  # @see Row#array_to_cells
29
29
  # @see Cell
30
30
  def initialize(worksheet, values=[], options={})
31
- @ht = nil
32
31
  self.worksheet = worksheet
33
- @cells = SimpleTypedList.new Cell
34
- @worksheet.rows << self
35
- self.height = options.delete(:height) if options[:height]
32
+ super(Cell, nil, values.size)
33
+ self.height = options.delete(:height)
34
+ worksheet.rows << self
36
35
  array_to_cells(values, options)
37
36
  end
38
37
 
@@ -46,14 +45,10 @@ module Axlsx
46
45
  # @return [Worksheet]
47
46
  attr_reader :worksheet
48
47
 
49
- # The cells this row holds
50
- # @return [SimpleTypedList]
51
- attr_reader :cells
52
-
53
48
  # Row height measured in point size. There is no margin padding on row height.
54
49
  # @return [Float]
55
50
  def height
56
- @ht
51
+ defined?(@ht) ? @ht : nil
57
52
  end
58
53
 
59
54
  # Outlining level of the row, when outlining is on
@@ -77,11 +72,12 @@ module Axlsx
77
72
  Axlsx.validate_unsigned_numeric(v)
78
73
  @outline_level = v
79
74
  end
75
+
80
76
  alias :outlineLevel= :outline_level=
81
77
 
82
78
  # The index of this row in the worksheet
83
79
  # @return [Integer]
84
- def index
80
+ def row_index
85
81
  worksheet.rows.index(self)
86
82
  end
87
83
 
@@ -90,50 +86,48 @@ module Axlsx
90
86
  # @param [String] str The string this rows xml will be appended to.
91
87
  # @return [String]
92
88
  def to_xml_string(r_index, str = '')
93
- str << '<row '
94
- serialized_attributes(str, { :r => r_index + 1 })
95
- str << '>'
96
- @cells.each_with_index { |cell, c_index| cell.to_xml_string(r_index, c_index, str) }
97
- str << '</row>'
89
+ serialized_tag('row', str, :r => r_index + 1) do
90
+ tmp = '' # time / memory tradeoff, lots of calls to rubyzip costs more
91
+ # time..
92
+ each_with_index { |cell, c_index| cell.to_xml_string(r_index, c_index, tmp) }
93
+ str << tmp
94
+ end
98
95
  end
99
96
 
100
- # Adds a single sell to the row based on the data provided and updates the worksheet's autofit data.
97
+ # Adds a single cell to the row based on the data provided and updates the worksheet's autofit data.
101
98
  # @return [Cell]
102
- def add_cell(value="", options={})
99
+ def add_cell(value = '', options = {})
103
100
  c = Cell.new(self, value, options)
104
- worksheet.send(:update_column_info, self.cells, [])
101
+ self << c
102
+ worksheet.send(:update_column_info, self, [])
105
103
  c
106
104
  end
107
105
 
108
106
  # sets the style for every cell in this row
109
107
  def style=(style)
110
- cells.each_with_index do | cell, index |
111
- s = style.is_a?(Array) ? style[index] : style
112
- cell.style = s
108
+ each_with_index do | cell, index |
109
+ cell.style = style.is_a?(Array) ? style[index] : style
113
110
  end
114
111
  end
115
112
 
116
- # returns the cells in this row as an array
117
- # This lets us transpose the rows into columns
118
- # @return [Array]
119
- def to_ary
120
- @cells.to_ary
121
- end
122
-
123
113
  # @see height
124
114
  def height=(v)
125
- Axlsx::validate_unsigned_numeric(v)
126
115
  unless v.nil?
127
- @ht = v
116
+ Axlsx::validate_unsigned_numeric(v)
128
117
  @custom_height = true
118
+ @ht = v
129
119
  end
130
- @ht
120
+ end
121
+
122
+ # return cells
123
+ def cells
124
+ self
131
125
  end
132
126
 
133
127
  private
134
128
 
135
129
  # assigns the owning worksheet for this row
136
- def worksheet=(v) DataTypeValidator.validate "Row.worksheet", Worksheet, v; @worksheet=v; end
130
+ def worksheet=(v) DataTypeValidator.validate :row_worksheet, Worksheet, v; @worksheet=v; end
137
131
 
138
132
  # Converts values, types, and style options into cells and associates them with this row.
139
133
  # A new cell is created for each item in the values array.
@@ -145,26 +139,14 @@ module Axlsx
145
139
  # @option options [Array, Symbol] types
146
140
  # @option options [Array, Integer] style
147
141
  def array_to_cells(values, options={})
148
- values = values
149
- DataTypeValidator.validate 'Row.array_to_cells', Array, values
142
+ DataTypeValidator.validate :array_to_cells, Array, values
150
143
  types, style, formula_values = options.delete(:types), options.delete(:style), options.delete(:formula_values)
151
144
  values.each_with_index do |value, index|
145
+ options[:style] = style.is_a?(Array) ? style[index] : style if style
146
+ options[:type] = types.is_a?(Array) ? types[index] : types if types
147
+ options[:formula_value] = formula_values[index] if formula_values.is_a?(Array)
152
148
 
153
- #WTF IS THIS PAP?
154
- cell_style = style.is_a?(Array) ? style[index] : style
155
- options[:style] = cell_style if cell_style
156
-
157
- cell_type = types.is_a?(Array)? types[index] : types
158
- options[:type] = cell_type if cell_type
159
-
160
- formula_value = formula_values[index] if formula_values.is_a?(Array)
161
- options[:formula_value] = formula_value if formula_value
162
-
163
- Cell.new(self, value, options)
164
-
165
- options.delete(:style)
166
- options.delete(:type)
167
- options.delete(:formula_value)
149
+ self[index] = Cell.new(self, value, options)
168
150
  end
169
151
  end
170
152
  end
@@ -14,7 +14,7 @@ module Axlsx
14
14
  # @see Break
15
15
  def add_break(options)
16
16
  # force feed the excel default
17
- @list << Break.new(options.merge(:max => 16383, :man => true))
17
+ self << Break.new(options.merge(:max => 16383, :man => true))
18
18
  last
19
19
  end
20
20
 
@@ -25,7 +25,7 @@ module Axlsx
25
25
  # </rowBreaks>
26
26
  def to_xml_string(str='')
27
27
  return if empty?
28
- str << '<rowBreaks count="' << @list.size.to_s << '" manualBreakCount="' << @list.size.to_s << '">'
28
+ str << ('<rowBreaks count="' << self.size.to_s << '" manualBreakCount="' << self.size.to_s << '">')
29
29
  each { |brk| brk.to_xml_string(str) }
30
30
  str << '</rowBreaks>'
31
31
  end
@@ -95,9 +95,7 @@ module Axlsx
95
95
  # @param [String] str
96
96
  # @return [String]
97
97
  def to_xml_string(str = '')
98
- str << '<selection '
99
- serialized_attributes str
100
- str << '/>'
98
+ serialized_tag 'selection', str
101
99
  end
102
100
  end
103
101
  end
@@ -17,7 +17,9 @@ module Axlsx
17
17
  # @return [String]
18
18
  def to_xml_string(str = '')
19
19
  str << '<sheetData>'
20
- worksheet.rows.each_with_index{ |row, index| row.to_xml_string(index, str) }
20
+ worksheet.rows.each_with_index do |row, index|
21
+ row.to_xml_string(index, str)
22
+ end
21
23
  str << '</sheetData>'
22
24
  end
23
25
 
@@ -76,9 +76,7 @@ module Axlsx
76
76
  # @param [String] str
77
77
  # @return [String]
78
78
  def to_xml_string(str = '')
79
- str << '<sheetProtection '
80
- serialized_attributes str
81
- str << '/>'
79
+ serialized_tag('sheetProtection', str)
82
80
  end
83
81
 
84
82
  private
@@ -58,7 +58,7 @@ module Axlsx
58
58
  # @param [String, Cell] v
59
59
  # @return [Title]
60
60
  def name=(v)
61
- DataTypeValidator.validate "#{self.class}.name", [String], v
61
+ DataTypeValidator.validate :table_name, [String], v
62
62
  if v.is_a?(String)
63
63
  @name = v
64
64
  end
@@ -75,12 +75,12 @@ module Axlsx
75
75
  # @return [String]
76
76
  def to_xml_string(str = '')
77
77
  str << '<?xml version="1.0" encoding="UTF-8"?>'
78
- str << '<table xmlns="' << XML_NS << '" id="' << (index+1).to_s << '" name="' << @name << '" displayName="' << @name.gsub(/\s/,'_') << '" '
79
- str << 'ref="' << @ref << '" totalsRowShown="0">'
80
- str << '<autoFilter ref="' << @ref << '"/>'
81
- str << '<tableColumns count="' << header_cells.length.to_s << '">'
78
+ str << ('<table xmlns="' << XML_NS << '" id="' << (index+1).to_s << '" name="' << @name << '" displayName="' << @name.gsub(/\s/,'_') << '" ')
79
+ str << ('ref="' << @ref << '" totalsRowShown="0">')
80
+ str << ('<autoFilter ref="' << @ref << '"/>')
81
+ str << ('<tableColumns count="' << header_cells.length.to_s << '">')
82
82
  header_cells.each_with_index do |cell,index|
83
- str << '<tableColumn id ="' << (index+1).to_s << '" name="' << cell.value << '"/>'
83
+ str << ('<tableColumn id ="' << (index+1).to_s << '" name="' << cell.value << '"/>')
84
84
  end
85
85
  str << '</tableColumns>'
86
86
  table_style_info.to_xml_string(str)
@@ -43,9 +43,7 @@ module Axlsx
43
43
  # seralizes this object to an xml string
44
44
  # @param [String] str the string to contact this objects serialization to.
45
45
  def to_xml_string(str = '')
46
- str << '<tableStyleInfo '
47
- serialized_attributes str
48
- str << '/>'
46
+ serialized_tag('tableStyleInfo', str)
49
47
  end
50
48
  end
51
49
  end
@@ -23,7 +23,7 @@ module Axlsx
23
23
  def to_xml_string(str = "")
24
24
  return if empty?
25
25
  str << "<tableParts count='#{size}'>"
26
- @list.each { |table| str << "<tablePart r:id='#{table.rId}'/>" }
26
+ each { |table| str << "<tablePart r:id='#{table.rId}'/>" }
27
27
  str << '</tableParts>'
28
28
  end
29
29
  end
@@ -4,15 +4,11 @@ module Axlsx
4
4
  # The Worksheet class represents a worksheet in the workbook.
5
5
  class Worksheet
6
6
  include Axlsx::OptionsParser
7
-
7
+ include Axlsx::SerializedAttributes
8
8
  # definition of characters which are less than the maximum width of 0-9 in the default font for use in String#count.
9
9
  # This is used for autowidth calculations
10
- # @return [String]
11
- def self.thin_chars
12
- # removed 'e' and 'y' from this list - as a GUESS
13
- @thin_chars ||= "^.acfijklrstxzFIJL()-"
14
- end
15
-
10
+ THIN_CHARS = '^.acfijklrstxzFIJL()-'.freeze
11
+
16
12
  # Creates a new worksheet.
17
13
  # @note the recommended way to manage worksheets is Workbook#add_worksheet
18
14
  # @see Workbook#add_worksheet
@@ -24,12 +20,15 @@ module Axlsx
24
20
  def initialize(wb, options={})
25
21
  self.workbook = wb
26
22
  @sheet_protection = nil
27
-
28
23
  initialize_page_options(options)
29
24
  parse_options options
30
25
  @workbook.worksheets << self
26
+ @sheet_id = index + 1
27
+ yield self if block_given?
31
28
  end
32
29
 
30
+ serializable_attributes :sheet_id, :name, :state
31
+
33
32
  # Initalizes page margin, setup and print options
34
33
  # @param [Hash] options Options passed in from the initializer
35
34
  def initialize_page_options(options)
@@ -44,7 +43,23 @@ module Axlsx
44
43
  # The name of the worksheet
45
44
  # @return [String]
46
45
  def name
47
- @name ||= "Sheet" + (index+1).to_s
46
+ @name ||= "Sheet" + (index+1).to_s
47
+ end
48
+
49
+ # Specifies the visible state of this sheet. Allowed states are
50
+ # :visible, :hidden or :very_hidden. The default value is :visible.
51
+ #
52
+ # Worksheets in the :hidden state can be shown using the sheet formatting properties in excel.
53
+ # :very_hidden sheets should be inaccessible to end users.
54
+ # @param [Symbol] sheet_state The visible state for this sheet.
55
+ def state=(sheet_state)
56
+ RestrictionValidator.validate :worksheet_state, [:visible, :hidden, :very_hidden], sheet_state
57
+ @state = sheet_state
58
+ end
59
+
60
+ # The visibility of this sheet
61
+ def state
62
+ @state ||= :visible
48
63
  end
49
64
 
50
65
  # The sheet calculation properties
@@ -129,7 +144,7 @@ module Axlsx
129
144
  # @return [SimpleTypedList]
130
145
  # @see Worksheet#add_row
131
146
  def rows
132
- @rows ||= SimpleTypedList.new Row
147
+ @rows ||= SimpleTypedList.new Row
133
148
  end
134
149
 
135
150
  # returns the sheet data as columns
@@ -142,7 +157,7 @@ module Axlsx
142
157
  @rows.transpose(&block)
143
158
  end
144
159
 
145
- # An range that excel will apply an auto-filter to "A1:B3"
160
+ # A range that excel will apply an auto-filter to "A1:B3"
146
161
  # This will turn filtering on for the cells in the range.
147
162
  # The first row is considered the header, while subsequent rows are considered to be data.
148
163
  # @return String
@@ -346,7 +361,7 @@ module Axlsx
346
361
  # @param [String] v
347
362
  # @see auto_filter
348
363
  def auto_filter=(v)
349
- DataTypeValidator.validate "Worksheet.auto_filter", String, v
364
+ DataTypeValidator.validate :worksheet_auto_filter, String, v
350
365
  auto_filter.range = v
351
366
  end
352
367
 
@@ -427,10 +442,10 @@ module Axlsx
427
442
  # @option options [Array] widths each member of the widths array will affect how auto_fit behavies.
428
443
  # @option options [Float] height the row's height (in points)
429
444
  def add_row(values=[], options={})
430
- Row.new(self, values, options)
431
- update_column_info @rows.last.cells, options.delete(:widths) || []
432
- yield @rows.last if block_given?
433
- @rows.last
445
+ row = Row.new(self, values, options)
446
+ update_column_info row, options.delete(:widths)
447
+ yield row if block_given?
448
+ row
434
449
  end
435
450
 
436
451
  alias :<< :add_row
@@ -522,7 +537,7 @@ module Axlsx
522
537
  # @example
523
538
  # ws.add_page_break("A4")
524
539
  def add_page_break(cell)
525
- DataTypeValidator.validate "Worksheet#add_page_break cell", [String, Cell], cell
540
+ DataTypeValidator.validate :worksheet_page_break, [String, Cell], cell
526
541
  column_index, row_index = if cell.is_a?(String)
527
542
  Axlsx.name_to_indices(cell)
528
543
  else
@@ -535,7 +550,7 @@ module Axlsx
535
550
  end
536
551
 
537
552
  # This is a helper method that Lets you specify a fixed width for multiple columns in a worksheet in one go.
538
- # Axlsx is sparse, so if you have not set data for a column, you cannot set the width.
553
+ # Note that you must call column_widths AFTER adding data, otherwise the width will not be set successfully.
539
554
  # Setting a fixed column width to nil will revert the behaviour back to calculating the width for you on the next call to add_row.
540
555
  # @example This would set the first and third column widhts but leave the second column in autofit state.
541
556
  # ws.column_widths 7.2, nil, 3
@@ -559,7 +574,7 @@ module Axlsx
559
574
  # @see README.md for an example
560
575
  def col_style(index, style, options={})
561
576
  offset = options.delete(:row_offset) || 0
562
- cells = @rows[(offset..-1)].map { |row| row.cells[index] }.flatten.compact
577
+ cells = @rows[(offset..-1)].map { |row| row[index] }.flatten.compact
563
578
  cells.each { |cell| cell.style = style }
564
579
  end
565
580
 
@@ -577,18 +592,26 @@ module Axlsx
577
592
  cells.each { |cell| cell.style = style }
578
593
  end
579
594
 
595
+ # Returns a sheet node serialization for this sheet in the workbook.
596
+ def to_sheet_node_xml_string(str='')
597
+ add_autofilter_defined_name_to_workbook
598
+ str << '<sheet '
599
+ serialized_attributes str
600
+ str << ('r:id="' << rId << '"></sheet>')
601
+ end
602
+
580
603
  # Serializes the worksheet object to an xml string
581
604
  # This intentionally does not use nokogiri for performance reasons
582
605
  # @return [String]
583
- def to_xml_string
606
+ def to_xml_string str=''
607
+ add_autofilter_defined_name_to_workbook
584
608
  auto_filter.apply if auto_filter.range
585
- str = '<?xml version="1.0" encoding="UTF-8"?>'
609
+ str << '<?xml version="1.0" encoding="UTF-8"?>'
586
610
  str << worksheet_node
587
611
  serializable_parts.each do |item|
588
612
  item.to_xml_string(str) if item
589
613
  end
590
614
  str << '</worksheet>'
591
- Axlsx::sanitize(str)
592
615
  end
593
616
 
594
617
  # The worksheet relationships. This is managed automatically by the worksheet
@@ -622,7 +645,7 @@ module Axlsx
622
645
  def name_to_cell(name)
623
646
  col_index, row_index = *Axlsx::name_to_indices(name)
624
647
  r = rows[row_index]
625
- r.cells[col_index] if r
648
+ r[col_index] if r
626
649
  end
627
650
 
628
651
  # shortcut method to access styles direclty from the worksheet
@@ -675,7 +698,7 @@ module Axlsx
675
698
  end
676
699
 
677
700
  def validate_sheet_name(name)
678
- DataTypeValidator.validate "Worksheet.name", String, name
701
+ DataTypeValidator.validate :worksheet_name, String, name
679
702
  raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG % name) if name.size > 31
680
703
  raise ArgumentError, (ERR_SHEET_NAME_CHARACTER_FORBIDDEN % name) if '[]*/\?:'.chars.any? { |char| name.include? char }
681
704
  name = Axlsx::coder.encode(name)
@@ -695,8 +718,8 @@ module Axlsx
695
718
  def range(*cell_def)
696
719
  first, last = cell_def
697
720
  cells = []
698
- rows[(first.row.index..last.row.index)].each do |r|
699
- r.cells[(first.index..last.index)].each do |c|
721
+ rows[(first.row.row_index..last.row.row_index)].each do |r|
722
+ r[(first.index..last.index)].each do |c|
700
723
  cells << c
701
724
  end
702
725
  end
@@ -734,7 +757,7 @@ module Axlsx
734
757
  # Helper method for parsingout the root node for worksheet
735
758
  # @return [String]
736
759
  def worksheet_node
737
- "<worksheet xmlns=\"%s\" xmlns:r=\"%s\" xml:space=\"#{xml_space}\">" % [XML_NS, XML_NS_R]
760
+ "<worksheet xmlns=\"#{XML_NS}\" xmlns:r=\"#{XML_NS_R}\" xml:space=\"#{xml_space}\">"
738
761
  end
739
762
 
740
763
  def sheet_data
@@ -753,11 +776,12 @@ module Axlsx
753
776
 
754
777
  def workbook=(v) DataTypeValidator.validate "Worksheet.workbook", Workbook, v; @workbook = v; end
755
778
 
756
- def update_column_info(cells, widths=[])
779
+ def update_column_info(cells, widths=nil)
757
780
  cells.each_with_index do |cell, index|
781
+ width = widths ? widths[index] : nil
758
782
  col = find_or_create_column_info(index)
759
- next if widths[index] == :ignore
760
- col.update_width(cell, widths[index], workbook.use_autowidth)
783
+ next if width == :ignore
784
+ col.update_width(cell, width, workbook.use_autowidth)
761
785
  end
762
786
  end
763
787
 
@@ -765,5 +789,10 @@ module Axlsx
765
789
  column_info[index] ||= Col.new(index + 1, index + 1)
766
790
  end
767
791
 
792
+ def add_autofilter_defined_name_to_workbook
793
+ return if !auto_filter.range
794
+ workbook.add_defined_name auto_filter.defined_name, name: '_xlnm._FilterDatabase', local_sheet_id: index, hidden: 1
795
+ end
796
+
768
797
  end
769
798
  end