caxlsx 3.3.0 → 4.0.0

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 (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +25 -7
  4. data/Rakefile +7 -6
  5. data/lib/axlsx/content_type/abstract_content_type.rb +11 -9
  6. data/lib/axlsx/content_type/content_type.rb +7 -9
  7. data/lib/axlsx/content_type/default.rb +4 -6
  8. data/lib/axlsx/content_type/override.rb +3 -5
  9. data/lib/axlsx/doc_props/app.rb +27 -30
  10. data/lib/axlsx/doc_props/core.rb +9 -12
  11. data/lib/axlsx/drawing/area_chart.rb +13 -14
  12. data/lib/axlsx/drawing/area_series.rb +13 -14
  13. data/lib/axlsx/drawing/ax_data_source.rb +3 -6
  14. data/lib/axlsx/drawing/axes.rb +10 -9
  15. data/lib/axlsx/drawing/axis.rb +27 -30
  16. data/lib/axlsx/drawing/bar_3D_chart.rb +17 -18
  17. data/lib/axlsx/drawing/bar_chart.rb +16 -17
  18. data/lib/axlsx/drawing/bar_series.rb +9 -13
  19. data/lib/axlsx/drawing/bubble_chart.rb +8 -9
  20. data/lib/axlsx/drawing/bubble_series.rb +9 -10
  21. data/lib/axlsx/drawing/cat_axis.rb +14 -17
  22. data/lib/axlsx/drawing/chart.rb +25 -28
  23. data/lib/axlsx/drawing/d_lbls.rb +29 -26
  24. data/lib/axlsx/drawing/drawing.rb +60 -62
  25. data/lib/axlsx/drawing/graphic_frame.rb +6 -7
  26. data/lib/axlsx/drawing/hyperlink.rb +12 -13
  27. data/lib/axlsx/drawing/line_3D_chart.rb +13 -15
  28. data/lib/axlsx/drawing/line_chart.rb +13 -14
  29. data/lib/axlsx/drawing/line_series.rb +13 -14
  30. data/lib/axlsx/drawing/marker.rb +14 -16
  31. data/lib/axlsx/drawing/num_data.rb +13 -16
  32. data/lib/axlsx/drawing/num_data_source.rb +11 -13
  33. data/lib/axlsx/drawing/num_val.rb +9 -10
  34. data/lib/axlsx/drawing/one_cell_anchor.rb +10 -10
  35. data/lib/axlsx/drawing/pic.rb +57 -22
  36. data/lib/axlsx/drawing/picture_locking.rb +6 -7
  37. data/lib/axlsx/drawing/pie_3D_chart.rb +6 -9
  38. data/lib/axlsx/drawing/pie_series.rb +9 -12
  39. data/lib/axlsx/drawing/scaling.rb +9 -10
  40. data/lib/axlsx/drawing/scatter_chart.rb +9 -10
  41. data/lib/axlsx/drawing/scatter_series.rb +15 -16
  42. data/lib/axlsx/drawing/ser_axis.rb +9 -11
  43. data/lib/axlsx/drawing/series.rb +8 -8
  44. data/lib/axlsx/drawing/series_title.rb +6 -6
  45. data/lib/axlsx/drawing/str_data.rb +10 -13
  46. data/lib/axlsx/drawing/str_val.rb +8 -9
  47. data/lib/axlsx/drawing/title.rb +23 -27
  48. data/lib/axlsx/drawing/two_cell_anchor.rb +8 -8
  49. data/lib/axlsx/drawing/val_axis.rb +5 -6
  50. data/lib/axlsx/drawing/view_3D.rb +32 -30
  51. data/lib/axlsx/drawing/vml_drawing.rb +19 -20
  52. data/lib/axlsx/drawing/vml_shape.rb +25 -26
  53. data/lib/axlsx/package.rb +81 -79
  54. data/lib/axlsx/rels/relationship.rb +30 -28
  55. data/lib/axlsx/rels/relationships.rb +7 -8
  56. data/lib/axlsx/stylesheet/border.rb +7 -8
  57. data/lib/axlsx/stylesheet/border_pr.rb +8 -8
  58. data/lib/axlsx/stylesheet/cell_alignment.rb +14 -20
  59. data/lib/axlsx/stylesheet/cell_protection.rb +6 -7
  60. data/lib/axlsx/stylesheet/cell_style.rb +12 -14
  61. data/lib/axlsx/stylesheet/color.rb +15 -12
  62. data/lib/axlsx/stylesheet/dxf.rb +7 -9
  63. data/lib/axlsx/stylesheet/fill.rb +3 -5
  64. data/lib/axlsx/stylesheet/font.rb +24 -21
  65. data/lib/axlsx/stylesheet/gradient_fill.rb +9 -9
  66. data/lib/axlsx/stylesheet/gradient_stop.rb +7 -6
  67. data/lib/axlsx/stylesheet/num_fmt.rb +9 -14
  68. data/lib/axlsx/stylesheet/pattern_fill.rb +8 -8
  69. data/lib/axlsx/stylesheet/styles.rb +104 -98
  70. data/lib/axlsx/stylesheet/table_style.rb +8 -9
  71. data/lib/axlsx/stylesheet/table_style_element.rb +7 -8
  72. data/lib/axlsx/stylesheet/table_styles.rb +8 -10
  73. data/lib/axlsx/stylesheet/xf.rb +21 -22
  74. data/lib/axlsx/util/accessors.rb +6 -6
  75. data/lib/axlsx/util/buffered_zip_output_stream.rb +60 -0
  76. data/lib/axlsx/util/constants.rb +119 -108
  77. data/lib/axlsx/util/mime_type_utils.rb +11 -0
  78. data/lib/axlsx/util/options_parser.rb +4 -3
  79. data/lib/axlsx/util/serialized_attributes.rb +45 -21
  80. data/lib/axlsx/util/simple_typed_list.rb +58 -57
  81. data/lib/axlsx/util/storage.rb +38 -41
  82. data/lib/axlsx/util/validators.rb +107 -44
  83. data/lib/axlsx/util/zip_command.rb +10 -12
  84. data/lib/axlsx/version.rb +3 -2
  85. data/lib/axlsx/workbook/defined_name.rb +11 -8
  86. data/lib/axlsx/workbook/defined_names.rb +4 -3
  87. data/lib/axlsx/workbook/shared_strings_table.rb +10 -11
  88. data/lib/axlsx/workbook/workbook.rb +121 -114
  89. data/lib/axlsx/workbook/workbook_view.rb +8 -11
  90. data/lib/axlsx/workbook/workbook_views.rb +4 -4
  91. data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +72 -14
  92. data/lib/axlsx/workbook/worksheet/auto_filter/filter_column.rb +11 -7
  93. data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +24 -21
  94. data/lib/axlsx/workbook/worksheet/auto_filter/sort_condition.rb +51 -0
  95. data/lib/axlsx/workbook/worksheet/auto_filter/sort_state.rb +56 -0
  96. data/lib/axlsx/workbook/worksheet/border_creator.rb +30 -25
  97. data/lib/axlsx/workbook/worksheet/break.rb +4 -5
  98. data/lib/axlsx/workbook/worksheet/cell.rb +92 -65
  99. data/lib/axlsx/workbook/worksheet/cell_serializer.rb +32 -28
  100. data/lib/axlsx/workbook/worksheet/cfvo.rb +7 -5
  101. data/lib/axlsx/workbook/worksheet/cfvos.rb +5 -5
  102. data/lib/axlsx/workbook/worksheet/col.rb +9 -10
  103. data/lib/axlsx/workbook/worksheet/col_breaks.rb +8 -7
  104. data/lib/axlsx/workbook/worksheet/color_scale.rb +16 -16
  105. data/lib/axlsx/workbook/worksheet/cols.rb +9 -7
  106. data/lib/axlsx/workbook/worksheet/comment.rb +12 -11
  107. data/lib/axlsx/workbook/worksheet/comments.rb +10 -12
  108. data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +12 -8
  109. data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +19 -21
  110. data/lib/axlsx/workbook/worksheet/conditional_formattings.rb +5 -5
  111. data/lib/axlsx/workbook/worksheet/data_bar.rb +29 -30
  112. data/lib/axlsx/workbook/worksheet/data_validation.rb +34 -33
  113. data/lib/axlsx/workbook/worksheet/data_validations.rb +5 -6
  114. data/lib/axlsx/workbook/worksheet/date_time_converter.rb +8 -8
  115. data/lib/axlsx/workbook/worksheet/dimension.rb +9 -6
  116. data/lib/axlsx/workbook/worksheet/header_footer.rb +4 -3
  117. data/lib/axlsx/workbook/worksheet/icon_set.rb +24 -8
  118. data/lib/axlsx/workbook/worksheet/merged_cells.rb +10 -10
  119. data/lib/axlsx/workbook/worksheet/outline_pr.rb +6 -3
  120. data/lib/axlsx/workbook/worksheet/page_margins.rb +17 -12
  121. data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +6 -4
  122. data/lib/axlsx/workbook/worksheet/page_setup.rb +128 -129
  123. data/lib/axlsx/workbook/worksheet/pane.rb +27 -26
  124. data/lib/axlsx/workbook/worksheet/pivot_table.rb +23 -25
  125. data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +12 -13
  126. data/lib/axlsx/workbook/worksheet/pivot_tables.rb +5 -4
  127. data/lib/axlsx/workbook/worksheet/print_options.rb +3 -2
  128. data/lib/axlsx/workbook/worksheet/protected_range.rb +6 -5
  129. data/lib/axlsx/workbook/worksheet/protected_ranges.rb +12 -10
  130. data/lib/axlsx/workbook/worksheet/rich_text.rb +6 -6
  131. data/lib/axlsx/workbook/worksheet/rich_text_run.rb +35 -17
  132. data/lib/axlsx/workbook/worksheet/row.rb +30 -22
  133. data/lib/axlsx/workbook/worksheet/row_breaks.rb +8 -7
  134. data/lib/axlsx/workbook/worksheet/selection.rb +16 -16
  135. data/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb +10 -7
  136. data/lib/axlsx/workbook/worksheet/sheet_data.rb +7 -7
  137. data/lib/axlsx/workbook/worksheet/sheet_format_pr.rb +23 -19
  138. data/lib/axlsx/workbook/worksheet/sheet_pr.rb +11 -7
  139. data/lib/axlsx/workbook/worksheet/sheet_protection.rb +21 -20
  140. data/lib/axlsx/workbook/worksheet/sheet_view.rb +48 -53
  141. data/lib/axlsx/workbook/worksheet/table.rb +13 -13
  142. data/lib/axlsx/workbook/worksheet/table_style_info.rb +6 -5
  143. data/lib/axlsx/workbook/worksheet/tables.rb +7 -5
  144. data/lib/axlsx/workbook/worksheet/worksheet.rb +92 -63
  145. data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +10 -8
  146. data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +11 -4
  147. data/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +9 -8
  148. data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +7 -5
  149. data/lib/axlsx.rb +75 -47
  150. data/lib/caxlsx.rb +3 -2
  151. metadata +50 -44
@@ -1,4 +1,5 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
+
2
3
  module Axlsx
3
4
  # Validate a value against a specific list of allowed values.
4
5
  class RestrictionValidator
@@ -9,7 +10,8 @@ module Axlsx
9
10
  # @raise [ArgumentError] Raised if the value provided is not in the list of choices.
10
11
  # @return [Boolean] true if validation succeeds.
11
12
  def self.validate(name, choices, v)
12
- raise ArgumentError, (ERR_RESTRICTION % [v.to_s, name, choices.inspect]) unless choices.include?(v)
13
+ raise ArgumentError, format(ERR_RESTRICTION, v.to_s, name, choices.inspect) unless choices.include?(v)
14
+
13
15
  true
14
16
  end
15
17
  end
@@ -29,16 +31,17 @@ module Axlsx
29
31
  else
30
32
  min < value && value < max
31
33
  end
32
- raise ArgumentError, (ERR_RANGE % [value.inspect, min.to_s, max.to_s, inclusive]) unless passes
34
+ raise ArgumentError, format(ERR_RANGE, value.inspect, min.to_s, max.to_s, inclusive) unless passes
33
35
  end
34
36
  end
37
+
35
38
  # Validates the value against the regular expression provided.
36
39
  class RegexValidator
37
40
  # @param [String] name The name of what is being validated. This is included in the output when the value is invalid
38
41
  # @param [Regexp] regex The regular expression to evaluate
39
42
  # @param [Any] v The value to validate.
40
43
  def self.validate(name, regex, v)
41
- raise ArgumentError, (ERR_REGEX % [v.inspect, regex.to_s]) unless (v.respond_to?(:to_s) && v.to_s.match(regex))
44
+ raise ArgumentError, format(ERR_REGEX, v.inspect, regex.to_s) unless v.respond_to?(:to_s) && regex.match?(v.to_s)
42
45
  end
43
46
  end
44
47
 
@@ -51,24 +54,23 @@ module Axlsx
51
54
  # @raise [ArugumentError] Raised if the class of the value provided is not in the specified array of types or the block passed returns false
52
55
  # @return [Boolean] true if validation succeeds.
53
56
  # @see validate_boolean
54
- def self.validate(name, types, v, other=false)
55
- if other.is_a?(Proc)
56
- raise ArgumentError, (ERR_TYPE % [v.inspect, name, types.inspect]) unless other.call(v)
57
+ def self.validate(name, types, v, other = false)
58
+ if other.is_a?(Proc) && !other.call(v)
59
+ raise ArgumentError, format(ERR_TYPE, v.inspect, name, types.inspect)
57
60
  end
61
+
58
62
  v_class = v.is_a?(Class) ? v : v.class
59
- Array(types).each do |t|
60
- return if v_class <= t
61
- end
62
- raise ArgumentError, (ERR_TYPE % [v.inspect, name, types.inspect])
63
+ return if Array(types).any? { |t| v_class <= t }
64
+
65
+ raise ArgumentError, format(ERR_TYPE, v.inspect, name, types.inspect)
63
66
  end
64
67
  end
65
68
 
66
-
67
69
  # Requires that the value can be converted to an integer
68
70
  # @para, [Any] v the value to validate
69
71
  # @raise [ArgumentError] raised if the value cannot be converted to an integer
70
72
  def self.validate_integerish(v)
71
- raise ArgumentError, (ERR_INTEGERISH % v.inspect) unless (v.respond_to?(:to_i) && v.to_i.is_a?(Integer))
73
+ raise ArgumentError, format(ERR_INTEGERISH, v.inspect) unless v.respond_to?(:to_i) && v.to_i.is_a?(Integer)
72
74
  end
73
75
 
74
76
  # Requires that the value is between -54000000 and 54000000
@@ -76,11 +78,11 @@ module Axlsx
76
78
  # @raise [ArgumentError] raised if the value cannot be converted to an integer between the allowed angle values for chart label rotation.
77
79
  # @return [Boolean] true if the data is valid
78
80
  def self.validate_angle(v)
79
- raise ArgumentError, (ERR_ANGLE % v.inspect) unless (v.to_i >= -5400000 && v.to_i <= 5400000)
81
+ raise ArgumentError, format(ERR_ANGLE, v.inspect) unless v.to_i >= -5400000 && v.to_i <= 5400000
80
82
  end
81
83
 
82
84
  # Validates an unsigned intger
83
- UINT_VALIDATOR = lambda { |arg| arg.respond_to?(:>=) && arg >= 0 }
85
+ UINT_VALIDATOR = ->(arg) { arg.respond_to?(:>=) && arg >= 0 }
84
86
 
85
87
  # Requires that the value is a Integer and is greater or equal to 0
86
88
  # @param [Any] v The value validated
@@ -104,12 +106,16 @@ module Axlsx
104
106
  DataTypeValidator.validate :signed_int, Integer, v
105
107
  end
106
108
 
109
+ VALID_BOOLEAN_CLASSES = [TrueClass, FalseClass, Integer, String, Symbol].freeze
110
+ VALID_BOOLEAN_VALUES = [true, false, 1, 0, '1', '0', 'true', 'false', :true, :false].freeze
111
+ BOOLEAN_VALIDATOR = ->(arg) { VALID_BOOLEAN_VALUES.include?(arg) }
112
+
107
113
  # Requires that the value is a form that can be evaluated as a boolean in an xml document.
108
114
  # The value must be an instance of String, Integer, Symbol, TrueClass or FalseClass and
109
115
  # it must be one of 0, 1, "true", "false", :true, :false, true, false, "0", or "1"
110
116
  # @param [Any] v The value validated
111
117
  def self.validate_boolean(v)
112
- DataTypeValidator.validate(:boolean, [String, Integer, Symbol, TrueClass, FalseClass], v, lambda { |arg| [0, 1, "true", "false", :true, :false, true, false, "0", "1"].include?(arg) })
118
+ DataTypeValidator.validate(:boolean, VALID_BOOLEAN_CLASSES, v, BOOLEAN_VALIDATOR)
113
119
  end
114
120
 
115
121
  # Requires that the value is a String
@@ -130,51 +136,71 @@ module Axlsx
130
136
  RegexValidator.validate "number_with_unit", /\A[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)\Z/, v
131
137
  end
132
138
 
139
+ SCALE_10_400_VALIDATOR = ->(arg) { arg >= 10 && arg <= 400 }
140
+
133
141
  # Requires that the value is an integer ranging from 10 to 400.
134
142
  def self.validate_scale_10_400(v)
135
- DataTypeValidator.validate "page_scale", Integer, v, lambda { |arg| arg >= 10 && arg <= 400 }
143
+ DataTypeValidator.validate "page_scale", Integer, v, SCALE_10_400_VALIDATOR
136
144
  end
137
145
 
146
+ SCALE_0_10_400_VALIDATOR = ->(arg) { arg == 0 || (arg >= 10 && arg <= 400) }
147
+
138
148
  # Requires that the value is an integer ranging from 10 to 400 or 0.
139
149
  def self.validate_scale_0_10_400(v)
140
- DataTypeValidator.validate "page_scale", Integer, v, lambda { |arg| arg == 0 || (arg >= 10 && arg <= 400) }
150
+ DataTypeValidator.validate "page_scale", Integer, v, SCALE_0_10_400_VALIDATOR
141
151
  end
142
152
 
153
+ VALID_PAGE_ORIENTATION_VALUES = [:default, :landscape, :portrait].freeze
154
+
143
155
  # Requires that the value is one of :default, :landscape, or :portrait.
144
156
  def self.validate_page_orientation(v)
145
- RestrictionValidator.validate "page_orientation", [:default, :landscape, :portrait], v
157
+ RestrictionValidator.validate "page_orientation", VALID_PAGE_ORIENTATION_VALUES, v
146
158
  end
159
+
160
+ VALID_CELL_U_VALUES = [:none, :single, :double, :singleAccounting, :doubleAccounting].freeze
161
+
147
162
  # Requires that the value is one of :none, :single, :double, :singleAccounting, :doubleAccounting
148
163
  def self.validate_cell_u(v)
149
- RestrictionValidator.validate "cell run style u", [:none, :single, :double, :singleAccounting, :doubleAccounting], v
164
+ RestrictionValidator.validate "cell run style u", VALID_CELL_U_VALUES, v
150
165
  end
151
166
 
167
+ VALID_FAMILY_VALUES = (1..5).freeze
168
+
152
169
  # validates cell style family which must be between 1 and 5
153
170
  def self.validate_family(v)
154
- RestrictionValidator.validate "cell run style family", 1..5, v
171
+ RestrictionValidator.validate "cell run style family", VALID_FAMILY_VALUES, v
155
172
  end
173
+
174
+ VALID_PATTERN_TYPE_VALUES = [:none, :solid, :mediumGray, :darkGray, :lightGray, :darkHorizontal, :darkVertical, :darkDown, :darkUp, :darkGrid,
175
+ :darkTrellis, :lightHorizontal, :lightVertical, :lightDown, :lightUp, :lightGrid, :lightTrellis, :gray125, :gray0625].freeze
176
+
156
177
  # Requires that the value is valid pattern type.
157
178
  # valid pattern types must be one of :none, :solid, :mediumGray, :darkGray, :lightGray, :darkHorizontal, :darkVertical, :darkDown,
158
179
  # :darkUp, :darkGrid, :darkTrellis, :lightHorizontal, :lightVertical, :lightDown, :lightUp, :lightGrid, :lightTrellis, :gray125, or :gray0625.
159
180
  # @param [Any] v The value validated
160
181
  def self.validate_pattern_type(v)
161
- RestrictionValidator.validate :pattern_type, [:none, :solid, :mediumGray, :darkGray, :lightGray, :darkHorizontal, :darkVertical, :darkDown, :darkUp, :darkGrid,
162
- :darkTrellis, :lightHorizontal, :lightVertical, :lightDown, :lightUp, :lightGrid, :lightTrellis, :gray125, :gray0625], v
182
+ RestrictionValidator.validate :pattern_type, VALID_PATTERN_TYPE_VALUES, v
163
183
  end
164
184
 
185
+ VALID_TIME_PERIOD_TYPE_VALUES = [:today, :yesterday, :tomorrow, :last7Days, :thisMonth, :lastMonth, :nextMonth, :thisWeek, :lastWeek, :nextWeek].freeze
186
+
165
187
  # Requires that the value is one of the ST_TimePeriod types
166
188
  # valid time period types are today, yesterday, tomorrow, last7Days,
167
189
  # thisMonth, lastMonth, nextMonth, thisWeek, lastWeek, nextWeek
168
190
  def self.validate_time_period_type(v)
169
- RestrictionValidator.validate :time_period_type, [:today, :yesterday, :tomorrow, :last7Days, :thisMonth, :lastMonth, :nextMonth, :thisWeek, :lastWeek, :nextWeek], v
191
+ RestrictionValidator.validate :time_period_type, VALID_TIME_PERIOD_TYPE_VALUES, v
170
192
  end
171
193
 
194
+ VALID_ICON_SET_VALUES = ["3Arrows", "3ArrowsGray", "3Flags", "3TrafficLights1", "3TrafficLights2", "3Signs", "3Symbols", "3Symbols2", "4Arrows", "4ArrowsGray", "4RedToBlack", "4Rating", "4TrafficLights", "5Arrows", "5ArrowsGray", "5Rating", "5Quarters"].freeze
195
+
172
196
  # Requires that the value is one of the valid ST_IconSet types
173
197
  # Allowed values are: 3Arrows, 3ArrowsGray, 3Flags, 3TrafficLights1, 3TrafficLights2, 3Signs, 3Symbols, 3Symbols2, 4Arrows, 4ArrowsGray, 4RedToBlack, 4Rating, 4TrafficLights, 5Arrows, 5ArrowsGray, 5Rating, 5Quarters
174
198
  def self.validate_icon_set(v)
175
- RestrictionValidator.validate :iconSet, ["3Arrows", "3ArrowsGray", "3Flags", "3TrafficLights1", "3TrafficLights2", "3Signs", "3Symbols", "3Symbols2", "4Arrows", "4ArrowsGray", "4RedToBlack", "4Rating", "4TrafficLights", "5Arrows", "5ArrowsGray", "5Rating", "5Quarters"], v
199
+ RestrictionValidator.validate :iconSet, VALID_ICON_SET_VALUES, v
176
200
  end
177
201
 
202
+ VALID_CONDITIONAL_FORMATTING_TYPE_VALUES = [:expression, :cellIs, :colorScale, :dataBar, :iconSet, :top10, :uniqueValues, :duplicateValues, :containsText, :notContainsText, :beginsWith, :endsWith, :containsBlanks, :notContainsBlanks, :containsErrors, :notContainsErrors, :timePeriod, :aboveAverage].freeze
203
+
178
204
  # Requires that the value is valid conditional formatting type.
179
205
  # valid types must be one of expression, cellIs, colorScale,
180
206
  # dataBar, iconSet, top10, uniqueValues, duplicateValues,
@@ -183,130 +209,167 @@ module Axlsx
183
209
  # notContainsErrors, timePeriod, aboveAverage
184
210
  # @param [Any] v The value validated
185
211
  def self.validate_conditional_formatting_type(v)
186
- RestrictionValidator.validate :conditional_formatting_type, [:expression, :cellIs, :colorScale, :dataBar, :iconSet, :top10, :uniqueValues, :duplicateValues, :containsText, :notContainsText, :beginsWith, :endsWith, :containsBlanks, :notContainsBlanks, :containsErrors, :notContainsErrors, :timePeriod, :aboveAverage], v
212
+ RestrictionValidator.validate :conditional_formatting_type, VALID_CONDITIONAL_FORMATTING_TYPE_VALUES, v
187
213
  end
188
214
 
215
+ VALID_CONDITION_FORMATTING_VALUE_OBJECT_TYPE_VALUES = [:num, :percent, :max, :min, :formula, :percentile].freeze
216
+
189
217
  # Requires thatt he value is a valid conditional formatting value object type.
190
218
  # valid types must be one of num, percent, max, min, formula and percentile
191
219
  def self.validate_conditional_formatting_value_object_type(v)
192
- RestrictionValidator.validate :conditional_formatting_value_object_type, [:num, :percent, :max, :min, :formula, :percentile], v
220
+ RestrictionValidator.validate :conditional_formatting_value_object_type, VALID_CONDITION_FORMATTING_VALUE_OBJECT_TYPE_VALUES, v
193
221
  end
194
222
 
223
+ VALID_CONDITIONAL_FORMATTING_OPERATOR_VALUES = [:lessThan, :lessThanOrEqual, :equal, :notEqual, :greaterThanOrEqual, :greaterThan, :between, :notBetween, :containsText, :notContains, :beginsWith, :endsWith].freeze
224
+
195
225
  # Requires that the value is valid conditional formatting operator.
196
226
  # valid operators must be one of lessThan, lessThanOrEqual, equal,
197
227
  # notEqual, greaterThanOrEqual, greaterThan, between, notBetween,
198
228
  # containsText, notContains, beginsWith, endsWith
199
229
  # @param [Any] v The value validated
200
230
  def self.validate_conditional_formatting_operator(v)
201
- RestrictionValidator.validate :conditional_formatting_type, [:lessThan, :lessThanOrEqual, :equal, :notEqual, :greaterThanOrEqual, :greaterThan, :between, :notBetween, :containsText, :notContains, :beginsWith, :endsWith], v
231
+ RestrictionValidator.validate :conditional_formatting_type, VALID_CONDITIONAL_FORMATTING_OPERATOR_VALUES, v
202
232
  end
203
233
 
234
+ VALID_GRADIENT_TYPE_VALUES = [:linear, :path].freeze
235
+
204
236
  # Requires that the value is a gradient_type.
205
237
  # valid types are :linear and :path
206
238
  # @param [Any] v The value validated
207
239
  def self.validate_gradient_type(v)
208
- RestrictionValidator.validate :gradient_type, [:linear, :path], v
240
+ RestrictionValidator.validate :gradient_type, VALID_GRADIENT_TYPE_VALUES, v
209
241
  end
210
242
 
243
+ VALID_SCATTER_STYLE_VALUES = [:none, :line, :lineMarker, :marker, :smooth, :smoothMarker].freeze
244
+
211
245
  # Requires that the value is a valid scatterStyle
212
246
  # must be one of :none | :line | :lineMarker | :marker | :smooth | :smoothMarker
213
247
  # must be one of "none" | "line" | "lineMarker" | "marker" | "smooth" | "smoothMarker"
214
248
  # @param [Symbol|String] v the value to validate
215
249
  def self.validate_scatter_style(v)
216
- Axlsx::RestrictionValidator.validate "ScatterChart.scatterStyle", [:none, :line, :lineMarker, :marker, :smooth, :smoothMarker], v.to_sym
250
+ Axlsx::RestrictionValidator.validate "ScatterChart.scatterStyle", VALID_SCATTER_STYLE_VALUES, v.to_sym
217
251
  end
252
+
253
+ VALID_HORIZONTAL_ALIGNMENT_VALUES = [:general, :left, :center, :right, :fill, :justify, :centerContinuous, :distributed].freeze
254
+
218
255
  # Requires that the value is a valid horizontal_alignment
219
256
  # :general, :left, :center, :right, :fill, :justify, :centerContinuous, :distributed are allowed
220
257
  # @param [Any] v The value validated
221
258
  def self.validate_horizontal_alignment(v)
222
- RestrictionValidator.validate :horizontal_alignment, [:general, :left, :center, :right, :fill, :justify, :centerContinuous, :distributed], v
259
+ RestrictionValidator.validate :horizontal_alignment, VALID_HORIZONTAL_ALIGNMENT_VALUES, v
223
260
  end
224
261
 
262
+ VALID_VERTICAL_ALIGNMENT_VALUES = [:top, :center, :bottom, :justify, :distributed].freeze
263
+
225
264
  # Requires that the value is a valid vertical_alignment
226
265
  # :top, :center, :bottom, :justify, :distributed are allowed
227
266
  # @param [Any] v The value validated
228
267
  def self.validate_vertical_alignment(v)
229
- RestrictionValidator.validate :vertical_alignment, [:top, :center, :bottom, :justify, :distributed], v
268
+ RestrictionValidator.validate :vertical_alignment, VALID_VERTICAL_ALIGNMENT_VALUES, v
230
269
  end
231
270
 
271
+ VALID_CONTENT_TYPE_VALUES = [TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, JPEG_CT, GIF_CT, PNG_CT, DRAWING_CT, COMMENT_CT, VML_DRAWING_CT, PIVOT_TABLE_CT, PIVOT_TABLE_CACHE_DEFINITION_CT].freeze
272
+
232
273
  # Requires that the value is a valid content_type
233
274
  # TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, DRAWING_CT, COMMENT_CT are allowed
234
275
  # @param [Any] v The value validated
235
276
  def self.validate_content_type(v)
236
- RestrictionValidator.validate :content_type, [TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, JPEG_CT, GIF_CT, PNG_CT, DRAWING_CT, COMMENT_CT, VML_DRAWING_CT, PIVOT_TABLE_CT, PIVOT_TABLE_CACHE_DEFINITION_CT], v
277
+ RestrictionValidator.validate :content_type, VALID_CONTENT_TYPE_VALUES, v
237
278
  end
238
279
 
280
+ VALID_RELATIONSHIP_TYPE_VALUES = [XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R, COMMENT_R, VML_DRAWING_R, COMMENT_R_NULL, PIVOT_TABLE_R, PIVOT_TABLE_CACHE_DEFINITION_R].freeze
281
+
239
282
  # Requires that the value is a valid relationship_type
240
283
  # XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R are allowed
241
284
  # @param [Any] v The value validated
242
285
  def self.validate_relationship_type(v)
243
- RestrictionValidator.validate :relationship_type, [XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R, COMMENT_R, VML_DRAWING_R, COMMENT_R_NULL, PIVOT_TABLE_R, PIVOT_TABLE_CACHE_DEFINITION_R], v
286
+ RestrictionValidator.validate :relationship_type, VALID_RELATIONSHIP_TYPE_VALUES, v
244
287
  end
245
288
 
289
+ VALID_TABLE_ELEMENT_TYPE_VALUES = [:wholeTable, :headerRow, :totalRow, :firstColumn, :lastColumn, :firstRowStripe, :secondRowStripe, :firstColumnStripe, :secondColumnStripe, :firstHeaderCell, :lastHeaderCell, :firstTotalCell, :lastTotalCell, :firstSubtotalColumn, :secondSubtotalColumn, :thirdSubtotalColumn, :firstSubtotalRow, :secondSubtotalRow, :thirdSubtotalRow, :blankRow, :firstColumnSubheading, :secondColumnSubheading, :thirdColumnSubheading, :firstRowSubheading, :secondRowSubheading, :thirdRowSubheading, :pageFieldLabels, :pageFieldValues].freeze
290
+
246
291
  # Requires that the value is a valid table element type
247
292
  # :wholeTable, :headerRow, :totalRow, :firstColumn, :lastColumn, :firstRowStripe, :secondRowStripe, :firstColumnStripe, :secondColumnStripe, :firstHeaderCell, :lastHeaderCell, :firstTotalCell, :lastTotalCell, :firstSubtotalColumn, :secondSubtotalColumn, :thirdSubtotalColumn, :firstSubtotalRow, :secondSubtotalRow, :thirdSubtotalRow, :blankRow, :firstColumnSubheading, :secondColumnSubheading, :thirdColumnSubheading, :firstRowSubheading, :secondRowSubheading, :thirdRowSubheading, :pageFieldLabels, :pageFieldValues are allowed
248
293
  # @param [Any] v The value validated
249
294
  def self.validate_table_element_type(v)
250
- RestrictionValidator.validate :table_element_type, [:wholeTable, :headerRow, :totalRow, :firstColumn, :lastColumn, :firstRowStripe, :secondRowStripe, :firstColumnStripe, :secondColumnStripe, :firstHeaderCell, :lastHeaderCell, :firstTotalCell, :lastTotalCell, :firstSubtotalColumn, :secondSubtotalColumn, :thirdSubtotalColumn, :firstSubtotalRow, :secondSubtotalRow, :thirdSubtotalRow, :blankRow, :firstColumnSubheading, :secondColumnSubheading, :thirdColumnSubheading, :firstRowSubheading, :secondRowSubheading, :thirdRowSubheading, :pageFieldLabels, :pageFieldValues], v
295
+ RestrictionValidator.validate :table_element_type, VALID_TABLE_ELEMENT_TYPE_VALUES, v
251
296
  end
252
297
 
298
+ VALID_DATA_VALIDATION_ERROR_STYLE_VALUES = [:information, :stop, :warning].freeze
299
+
253
300
  # Requires that the value is a valid data_validation_error_style
254
301
  # :information, :stop, :warning
255
302
  # @param [Any] v The value validated
256
303
  def self.validate_data_validation_error_style(v)
257
- RestrictionValidator.validate :validate_data_validation_error_style, [:information, :stop, :warning], v
304
+ RestrictionValidator.validate :validate_data_validation_error_style, VALID_DATA_VALIDATION_ERROR_STYLE_VALUES, v
258
305
  end
259
306
 
307
+ VALID_DATA_VALIDATION_OPERATOR_VALUES = [:lessThan, :lessThanOrEqual, :equal, :notEqual, :greaterThanOrEqual, :greaterThan, :between, :notBetween].freeze
308
+
260
309
  # Requires that the value is valid data validation operator.
261
310
  # valid operators must be one of lessThan, lessThanOrEqual, equal,
262
311
  # notEqual, greaterThanOrEqual, greaterThan, between, notBetween
263
312
  # @param [Any] v The value validated
264
313
  def self.validate_data_validation_operator(v)
265
- RestrictionValidator.validate :data_validation_operator, [:lessThan, :lessThanOrEqual, :equal, :notEqual, :greaterThanOrEqual, :greaterThan, :between, :notBetween], v
314
+ RestrictionValidator.validate :data_validation_operator, VALID_DATA_VALIDATION_OPERATOR_VALUES, v
266
315
  end
267
316
 
317
+ VALID_DATA_VALIDATION_TYPE_VALUES = [:custom, :data, :decimal, :list, :none, :textLength, :date, :time, :whole].freeze
318
+
268
319
  # Requires that the value is valid data validation type.
269
320
  # valid types must be one of custom, data, decimal, list, none, textLength, time, whole
270
321
  # @param [Any] v The value validated
271
322
  def self.validate_data_validation_type(v)
272
- RestrictionValidator.validate :data_validation_type, [:custom, :data, :decimal, :list, :none, :textLength, :date, :time, :whole], v
323
+ RestrictionValidator.validate :data_validation_type, VALID_DATA_VALIDATION_TYPE_VALUES, v
273
324
  end
274
325
 
326
+ VALID_SHEET_VIEW_TYPE_VALUES = [:normal, :page_break_preview, :page_layout].freeze
327
+
275
328
  # Requires that the value is a valid sheet view type.
276
329
  # valid types must be one of normal, page_break_preview, page_layout
277
330
  # @param [Any] v The value validated
278
331
  def self.validate_sheet_view_type(v)
279
- RestrictionValidator.validate :sheet_view_type, [:normal, :page_break_preview, :page_layout], v
332
+ RestrictionValidator.validate :sheet_view_type, VALID_SHEET_VIEW_TYPE_VALUES, v
280
333
  end
281
334
 
335
+ VALID_PANE_TYPE_VALUES = [:bottom_left, :bottom_right, :top_left, :top_right].freeze
336
+
282
337
  # Requires that the value is a valid active pane type.
283
338
  # valid types must be one of bottom_left, bottom_right, top_left, top_right
284
339
  # @param [Any] v The value validated
285
340
  def self.validate_pane_type(v)
286
- RestrictionValidator.validate :active_pane_type, [:bottom_left, :bottom_right, :top_left, :top_right], v
341
+ RestrictionValidator.validate :active_pane_type, VALID_PANE_TYPE_VALUES, v
287
342
  end
288
343
 
344
+ VALID_SPLIT_STATE_TYPE_VALUES = [:frozen, :frozen_split, :split].freeze
345
+
289
346
  # Requires that the value is a valid split state type.
290
347
  # valid types must be one of frozen, frozen_split, split
291
348
  # @param [Any] v The value validated
292
349
  def self.validate_split_state_type(v)
293
- RestrictionValidator.validate :split_state_type, [:frozen, :frozen_split, :split], v
350
+ RestrictionValidator.validate :split_state_type, VALID_SPLIT_STATE_TYPE_VALUES, v
294
351
  end
295
352
 
353
+ VALID_DISPLAY_BLANK_AS_VALUES = [:gap, :span, :zero].freeze
354
+
296
355
  # Requires that the value is a valid "display blanks as" type.
297
356
  # valid types must be one of gap, span, zero
298
357
  # @param [Any] v The value validated
299
358
  def self.validate_display_blanks_as(v)
300
- RestrictionValidator.validate :display_blanks_as, [:gap, :span, :zero], v
359
+ RestrictionValidator.validate :display_blanks_as, VALID_DISPLAY_BLANK_AS_VALUES, v
301
360
  end
302
361
 
362
+ VALID_VIEW_VISIBILITY_VALUES = [:visible, :hidden, :very_hidden].freeze
363
+
303
364
  # Requires that the value is one of :visible, :hidden, :very_hidden
304
365
  def self.validate_view_visibility(v)
305
- RestrictionValidator.validate :visibility, [:visible, :hidden, :very_hidden], v
366
+ RestrictionValidator.validate :visibility, VALID_VIEW_VISIBILITY_VALUES, v
306
367
  end
307
368
 
369
+ VALID_MARKER_SYMBOL_VALUES = [:default, :circle, :dash, :diamond, :dot, :picture, :plus, :square, :star, :triangle, :x].freeze
370
+
308
371
  # Requires that the value is one of :default, :circle, :dash, :diamond, :dot, :picture, :plus, :square, :star, :triangle, :x
309
372
  def self.validate_marker_symbol(v)
310
- RestrictionValidator.validate :marker_symbol, [:default, :circle, :dash, :diamond, :dot, :picture, :plus, :square, :star, :triangle, :x], v
373
+ RestrictionValidator.validate :marker_symbol, VALID_MARKER_SYMBOL_VALUES, v
311
374
  end
312
375
  end
@@ -1,9 +1,9 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
+
2
3
  require 'open3'
3
4
  require 'shellwords'
4
5
 
5
6
  module Axlsx
6
-
7
7
  # The ZipCommand class supports zipping the Excel file contents using
8
8
  # a binary zip program instead of RubyZip's `Zip::OutputStream`.
9
9
  #
@@ -25,10 +25,10 @@ module Axlsx
25
25
  # Create a temporary directory for writing files to.
26
26
  #
27
27
  # The directory and its contents are removed at the end of the block.
28
- def open(output, &block)
28
+ def open(output)
29
29
  Dir.mktmpdir do |dir|
30
30
  @dir = dir
31
- block.call(self)
31
+ yield(self)
32
32
  write_file
33
33
  zip_parts(output)
34
34
  end
@@ -40,23 +40,21 @@ module Axlsx
40
40
  @current_file = "#{@dir}/#{entry.name}"
41
41
  @files << entry.name
42
42
  FileUtils.mkdir_p(File.dirname(@current_file))
43
+ @io = File.open(@current_file, "wb")
43
44
  end
44
45
 
45
46
  # Write to a buffer that will be written to the current entry
46
47
  def write(content)
47
- @buffer << content
48
+ @io << content
48
49
  end
49
50
  alias << write
50
51
 
51
52
  private
52
53
 
53
54
  def write_file
54
- if @current_file
55
- @buffer.rewind
56
- File.open(@current_file, "wb") { |f| f.write @buffer.read }
57
- end
55
+ @io.close if @current_file
58
56
  @current_file = nil
59
- @buffer = StringIO.new
57
+ @io = nil
60
58
  end
61
59
 
62
60
  def zip_parts(output)
@@ -65,8 +63,8 @@ module Axlsx
65
63
  escaped_dir = Shellwords.shellescape(@dir)
66
64
  command = "cd #{escaped_dir} && #{@zip_command} #{output} #{inputs}"
67
65
  stdout_and_stderr, status = Open3.capture2e(command)
68
- if !status.success?
69
- raise(ZipError.new(stdout_and_stderr))
66
+ unless status.success?
67
+ raise ZipError, stdout_and_stderr
70
68
  end
71
69
  end
72
70
  end
data/lib/axlsx/version.rb CHANGED
@@ -1,5 +1,6 @@
1
- module Axlsx
1
+ # frozen_string_literal: true
2
2
 
3
+ module Axlsx
3
4
  # The current version
4
- VERSION = "3.3.0"
5
+ VERSION = "4.0.0"
5
6
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # <definedNames>
2
4
  # <definedName name="_xlnm.Print_Titles" localSheetId="0">Sheet1!$1:$1</definedName>
3
5
  # </definedNames>
4
6
 
5
- #<xsd:complexType name="CT_DefinedName">
7
+ # <xsd:complexType name="CT_DefinedName">
6
8
  # <xsd:simpleContent>
7
- # <xsd:extension base="ST_Formula">
9
+ #  <xsd:extension base="ST_Formula">
8
10
  # <xsd:attribute name="name" type="s:ST_Xstring" use="required"/>
9
11
  # <xsd:attribute name="comment" type="s:ST_Xstring" use="optional"/>
10
12
  # <xsd:attribute name="customMenu" type="s:ST_Xstring" use="optional"/>
@@ -97,7 +99,7 @@ module Axlsx
97
99
  # version of the workbook that is published to or rendered on a Web or application server.
98
100
  # @option [Boolean] workbook_parameter - Specifies a boolean value that indicates that the name is used as a workbook parameter on a
99
101
  # version of the workbook that is published to or rendered on a Web or application server.
100
- def initialize(formula, options={})
102
+ def initialize(formula, options = {})
101
103
  @formula = formula
102
104
  parse_options options
103
105
  end
@@ -107,7 +109,7 @@ module Axlsx
107
109
  # The local sheet index (0-based)
108
110
  # @param [Integer] value the unsigned integer index of the sheet this defined_name applies to.
109
111
  def local_sheet_id=(value)
110
- Axlsx::validate_unsigned_int(value)
112
+ Axlsx.validate_unsigned_int(value)
111
113
  @local_sheet_id = value
112
114
  end
113
115
 
@@ -116,13 +118,14 @@ module Axlsx
116
118
  boolean_attr_accessor :workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden
117
119
 
118
120
  serializable_attributes :short_cut_key, :status_bar, :help, :description, :custom_menu, :comment,
119
- :workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden, :local_sheet_id
121
+ :workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden, :local_sheet_id
120
122
 
121
- def to_xml_string(str='')
123
+ def to_xml_string(str = +'')
122
124
  raise ArgumentError, 'you must specify the name for this defined name. Please read the documentation for Axlsx::DefinedName for more details' unless name
123
- str << ('<definedName ' << 'name="' << name << '" ')
125
+
126
+ str << '<definedName ' << 'name="' << name << '" '
124
127
  serialized_attributes str
125
- str << ('>' << @formula << '</definedName>')
128
+ str << '>' << @formula << '</definedName>'
126
129
  end
127
130
  end
128
131
  end
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Axlsx
2
4
  # a simple types list of DefinedName objects
3
5
  class DefinedNames < SimpleTypedList
4
-
5
6
  # creates the DefinedNames object
6
7
  def initialize
7
8
  super DefinedName
@@ -10,12 +11,12 @@ module Axlsx
10
11
  # Serialize to xml
11
12
  # @param [String] str
12
13
  # @return [String]
13
- def to_xml_string(str = '')
14
+ def to_xml_string(str = +'')
14
15
  return if empty?
16
+
15
17
  str << '<definedNames>'
16
18
  each { |defined_name| defined_name.to_xml_string(str) }
17
19
  str << '</definedNames>'
18
20
  end
19
21
  end
20
22
  end
21
-
@@ -1,6 +1,6 @@
1
- # encoding: UTF-8
2
- module Axlsx
1
+ # frozen_string_literal: true
3
2
 
3
+ module Axlsx
4
4
  # The Shared String Table class is responsible for managing and serializing common strings in a workbook.
5
5
  # While the ECMA-376 spec allows for both inline and shared strings it seems that at least some applications like iWorks Numbers
6
6
  # and Google Docs require that the shared string table is populated in order to interoperate properly.
@@ -9,7 +9,6 @@ module Axlsx
9
9
  # @note Serialization performance is affected by using this serialization method so if you do not need interoperability
10
10
  # it is recomended that you use the default inline string method of serialization.
11
11
  class SharedStringsTable
12
-
13
12
  # The total number of strings in the workbook including duplicates
14
13
  # Empty cells are treated as blank strings
15
14
  # @return [Integer]
@@ -33,12 +32,12 @@ module Axlsx
33
32
  # Creates a new Shared Strings Table agains an array of cells
34
33
  # @param [Array] cells This is an array of all of the cells in the workbook
35
34
  # @param [Symbol] xml_space The xml:space behavior for the shared string table.
36
- def initialize(cells, xml_space=:preserve)
35
+ def initialize(cells, xml_space = :preserve)
37
36
  @index = 0
38
37
  @xml_space = xml_space
39
38
  @unique_cells = {}
40
- @shared_xml_string = ""
41
- shareable_cells = cells.flatten.select{ |cell| cell.plain_string? || cell.contains_rich_text? }
39
+ @shared_xml_string = +''
40
+ shareable_cells = cells.flatten.select { |cell| cell.plain_string? || cell.contains_rich_text? }
42
41
  @count = shareable_cells.size
43
42
  resolve(shareable_cells)
44
43
  end
@@ -46,11 +45,11 @@ module Axlsx
46
45
  # Serializes the object
47
46
  # @param [String] str
48
47
  # @return [String]
49
- def to_xml_string(str='')
50
- Axlsx::sanitize(@shared_xml_string)
51
- str << ('<?xml version="1.0" encoding="UTF-8"?><sst xmlns="' << XML_NS << '"')
52
- str << (' count="' << @count.to_s << '" uniqueCount="' << unique_count.to_s << '"')
53
- str << (' xml:space="' << xml_space.to_s << '">' << @shared_xml_string << '</sst>')
48
+ def to_xml_string(str = +'')
49
+ Axlsx.sanitize(@shared_xml_string)
50
+ str << '<?xml version="1.0" encoding="UTF-8"?><sst xmlns="' << XML_NS << '"'
51
+ str << ' count="' << @count.to_s << '" uniqueCount="' << unique_count.to_s << '"'
52
+ str << ' xml:space="' << xml_space.to_s << '">' << @shared_xml_string << '</sst>'
54
53
  end
55
54
 
56
55
  private