caxlsx 3.4.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/README.md +11 -12
  4. data/Rakefile +7 -5
  5. data/lib/axlsx/content_type/abstract_content_type.rb +9 -4
  6. data/lib/axlsx/content_type/content_type.rb +7 -5
  7. data/lib/axlsx/content_type/default.rb +4 -2
  8. data/lib/axlsx/content_type/override.rb +4 -2
  9. data/lib/axlsx/doc_props/app.rb +26 -24
  10. data/lib/axlsx/doc_props/core.rb +8 -6
  11. data/lib/axlsx/drawing/area_chart.rb +10 -8
  12. data/lib/axlsx/drawing/area_series.rb +12 -10
  13. data/lib/axlsx/drawing/ax_data_source.rb +2 -0
  14. data/lib/axlsx/drawing/axes.rb +6 -4
  15. data/lib/axlsx/drawing/axis.rb +21 -19
  16. data/lib/axlsx/drawing/bar_3D_chart.rb +14 -12
  17. data/lib/axlsx/drawing/bar_chart.rb +13 -11
  18. data/lib/axlsx/drawing/bar_series.rb +8 -6
  19. data/lib/axlsx/drawing/bubble_chart.rb +6 -4
  20. data/lib/axlsx/drawing/bubble_series.rb +8 -6
  21. data/lib/axlsx/drawing/cat_axis.rb +12 -10
  22. data/lib/axlsx/drawing/chart.rb +20 -18
  23. data/lib/axlsx/drawing/d_lbls.rb +7 -5
  24. data/lib/axlsx/drawing/drawing.rb +58 -56
  25. data/lib/axlsx/drawing/graphic_frame.rb +6 -4
  26. data/lib/axlsx/drawing/hyperlink.rb +10 -8
  27. data/lib/axlsx/drawing/line_3D_chart.rb +7 -5
  28. data/lib/axlsx/drawing/line_chart.rb +10 -8
  29. data/lib/axlsx/drawing/line_series.rb +12 -10
  30. data/lib/axlsx/drawing/marker.rb +9 -7
  31. data/lib/axlsx/drawing/num_data.rb +9 -7
  32. data/lib/axlsx/drawing/num_data_source.rb +9 -7
  33. data/lib/axlsx/drawing/num_val.rb +7 -5
  34. data/lib/axlsx/drawing/one_cell_anchor.rb +7 -5
  35. data/lib/axlsx/drawing/pic.rb +16 -14
  36. data/lib/axlsx/drawing/picture_locking.rb +3 -1
  37. data/lib/axlsx/drawing/pie_3D_chart.rb +5 -3
  38. data/lib/axlsx/drawing/pie_series.rb +8 -6
  39. data/lib/axlsx/drawing/scaling.rb +8 -6
  40. data/lib/axlsx/drawing/scatter_chart.rb +7 -5
  41. data/lib/axlsx/drawing/scatter_series.rb +14 -12
  42. data/lib/axlsx/drawing/ser_axis.rb +7 -5
  43. data/lib/axlsx/drawing/series.rb +6 -4
  44. data/lib/axlsx/drawing/series_title.rb +6 -4
  45. data/lib/axlsx/drawing/str_data.rb +7 -5
  46. data/lib/axlsx/drawing/str_val.rb +6 -4
  47. data/lib/axlsx/drawing/title.rb +13 -14
  48. data/lib/axlsx/drawing/two_cell_anchor.rb +4 -2
  49. data/lib/axlsx/drawing/val_axis.rb +4 -2
  50. data/lib/axlsx/drawing/view_3D.rb +9 -7
  51. data/lib/axlsx/drawing/vml_drawing.rb +18 -16
  52. data/lib/axlsx/drawing/vml_shape.rb +24 -22
  53. data/lib/axlsx/package.rb +69 -66
  54. data/lib/axlsx/rels/relationship.rb +10 -5
  55. data/lib/axlsx/rels/relationships.rb +5 -3
  56. data/lib/axlsx/stylesheet/border.rb +6 -4
  57. data/lib/axlsx/stylesheet/border_pr.rb +5 -3
  58. data/lib/axlsx/stylesheet/cell_alignment.rb +12 -10
  59. data/lib/axlsx/stylesheet/cell_protection.rb +5 -3
  60. data/lib/axlsx/stylesheet/cell_style.rb +10 -8
  61. data/lib/axlsx/stylesheet/color.rb +9 -7
  62. data/lib/axlsx/stylesheet/dxf.rb +5 -3
  63. data/lib/axlsx/stylesheet/fill.rb +3 -1
  64. data/lib/axlsx/stylesheet/font.rb +18 -16
  65. data/lib/axlsx/stylesheet/gradient_fill.rb +6 -4
  66. data/lib/axlsx/stylesheet/gradient_stop.rb +6 -4
  67. data/lib/axlsx/stylesheet/num_fmt.rb +8 -10
  68. data/lib/axlsx/stylesheet/pattern_fill.rb +5 -3
  69. data/lib/axlsx/stylesheet/styles.rb +69 -71
  70. data/lib/axlsx/stylesheet/table_style.rb +7 -5
  71. data/lib/axlsx/stylesheet/table_style_element.rb +6 -4
  72. data/lib/axlsx/stylesheet/table_styles.rb +6 -4
  73. data/lib/axlsx/stylesheet/xf.rb +18 -16
  74. data/lib/axlsx/util/accessors.rb +4 -2
  75. data/lib/axlsx/util/buffered_zip_output_stream.rb +60 -0
  76. data/lib/axlsx/util/constants.rb +117 -104
  77. data/lib/axlsx/util/mime_type_utils.rb +3 -5
  78. data/lib/axlsx/util/options_parser.rb +3 -1
  79. data/lib/axlsx/util/serialized_attributes.rb +42 -17
  80. data/lib/axlsx/util/simple_typed_list.rb +47 -47
  81. data/lib/axlsx/util/storage.rb +11 -10
  82. data/lib/axlsx/util/validators.rb +101 -41
  83. data/lib/axlsx/util/zip_command.rb +10 -10
  84. data/lib/axlsx/version.rb +3 -1
  85. data/lib/axlsx/workbook/defined_name.rb +6 -4
  86. data/lib/axlsx/workbook/defined_names.rb +3 -1
  87. data/lib/axlsx/workbook/shared_strings_table.rb +8 -6
  88. data/lib/axlsx/workbook/workbook.rb +78 -76
  89. data/lib/axlsx/workbook/workbook_view.rb +3 -1
  90. data/lib/axlsx/workbook/workbook_views.rb +3 -1
  91. data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +65 -8
  92. data/lib/axlsx/workbook/worksheet/auto_filter/filter_column.rb +7 -3
  93. data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +11 -7
  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 +5 -3
  97. data/lib/axlsx/workbook/worksheet/break.rb +3 -1
  98. data/lib/axlsx/workbook/worksheet/cell.rb +55 -48
  99. data/lib/axlsx/workbook/worksheet/cell_serializer.rb +31 -27
  100. data/lib/axlsx/workbook/worksheet/cfvo.rb +5 -3
  101. data/lib/axlsx/workbook/worksheet/cfvos.rb +3 -1
  102. data/lib/axlsx/workbook/worksheet/col.rb +5 -3
  103. data/lib/axlsx/workbook/worksheet/col_breaks.rb +5 -3
  104. data/lib/axlsx/workbook/worksheet/color_scale.rb +12 -10
  105. data/lib/axlsx/workbook/worksheet/cols.rb +3 -1
  106. data/lib/axlsx/workbook/worksheet/comment.rb +8 -6
  107. data/lib/axlsx/workbook/worksheet/comments.rb +6 -4
  108. data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +9 -4
  109. data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +18 -16
  110. data/lib/axlsx/workbook/worksheet/conditional_formattings.rb +3 -1
  111. data/lib/axlsx/workbook/worksheet/data_bar.rb +14 -13
  112. data/lib/axlsx/workbook/worksheet/data_validation.rb +30 -28
  113. data/lib/axlsx/workbook/worksheet/data_validations.rb +3 -1
  114. data/lib/axlsx/workbook/worksheet/date_time_converter.rb +7 -5
  115. data/lib/axlsx/workbook/worksheet/dimension.rb +4 -2
  116. data/lib/axlsx/workbook/worksheet/header_footer.rb +4 -2
  117. data/lib/axlsx/workbook/worksheet/icon_set.rb +23 -6
  118. data/lib/axlsx/workbook/worksheet/merged_cells.rb +5 -5
  119. data/lib/axlsx/workbook/worksheet/outline_pr.rb +6 -2
  120. data/lib/axlsx/workbook/worksheet/page_margins.rb +15 -10
  121. data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +6 -2
  122. data/lib/axlsx/workbook/worksheet/page_setup.rb +11 -9
  123. data/lib/axlsx/workbook/worksheet/pane.rb +11 -9
  124. data/lib/axlsx/workbook/worksheet/pivot_table.rb +20 -19
  125. data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +8 -6
  126. data/lib/axlsx/workbook/worksheet/pivot_tables.rb +2 -0
  127. data/lib/axlsx/workbook/worksheet/print_options.rb +3 -1
  128. data/lib/axlsx/workbook/worksheet/protected_range.rb +3 -1
  129. data/lib/axlsx/workbook/worksheet/protected_ranges.rb +5 -3
  130. data/lib/axlsx/workbook/worksheet/rich_text.rb +3 -1
  131. data/lib/axlsx/workbook/worksheet/rich_text_run.rb +16 -14
  132. data/lib/axlsx/workbook/worksheet/row.rb +6 -7
  133. data/lib/axlsx/workbook/worksheet/row_breaks.rb +6 -4
  134. data/lib/axlsx/workbook/worksheet/selection.rb +9 -7
  135. data/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb +6 -2
  136. data/lib/axlsx/workbook/worksheet/sheet_data.rb +3 -1
  137. data/lib/axlsx/workbook/worksheet/sheet_format_pr.rb +6 -2
  138. data/lib/axlsx/workbook/worksheet/sheet_pr.rb +8 -4
  139. data/lib/axlsx/workbook/worksheet/sheet_protection.rb +10 -8
  140. data/lib/axlsx/workbook/worksheet/sheet_view.rb +15 -13
  141. data/lib/axlsx/workbook/worksheet/table.rb +9 -7
  142. data/lib/axlsx/workbook/worksheet/table_style_info.rb +4 -2
  143. data/lib/axlsx/workbook/worksheet/tables.rb +3 -1
  144. data/lib/axlsx/workbook/worksheet/worksheet.rb +38 -37
  145. data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +4 -2
  146. data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +8 -2
  147. data/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +6 -4
  148. data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +4 -2
  149. data/lib/axlsx.rb +56 -42
  150. data/lib/caxlsx.rb +3 -1
  151. metadata +49 -43
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Axlsx
4
+ # This class represents a individual sort condition belonging to the sort state of an auto filter
5
+ class SortCondition
6
+ # Creates a new SortCondition object
7
+ # @param [Integer] column_index Zero-based index indicating the AutoFilter column to which the sorting should be applied to
8
+ # @param [Symbol] order The order the column should be sorted on, can only be :asc or :desc
9
+ # @param [Array] custom_list An array containg a custom sorting list in order.
10
+ def initialize(column_index:, order:, custom_list:)
11
+ Axlsx.validate_int column_index
12
+ @column_index = column_index
13
+
14
+ RestrictionValidator.validate 'SortCondition.order', [:asc, :desc], order
15
+ @order = order
16
+
17
+ DataTypeValidator.validate :sort_condition_custom_list, Array, custom_list
18
+ @custom_list = custom_list
19
+ end
20
+
21
+ attr_reader :column_index, :order, :custom_list
22
+
23
+ # converts the ref String from the sort_state to a string representing the ref of a single column
24
+ # for the xml string to be returned.
25
+ def ref_to_single_column(ref, column_index)
26
+ first_cell, last_cell = ref.split(':')
27
+
28
+ start_point = Axlsx.name_to_indices(first_cell)
29
+
30
+ first_row = first_cell[/\d+/]
31
+ last_row = last_cell[/\d+/]
32
+
33
+ first_column = Axlsx.col_ref(column_index + start_point.first)
34
+ last_column = first_column
35
+
36
+ "#{first_column}#{first_row}:#{last_column}#{last_row}"
37
+ end
38
+
39
+ # serialize the object
40
+ # @return [String]
41
+ def to_xml_string(str, ref)
42
+ ref = ref_to_single_column(ref, column_index)
43
+
44
+ str << "<sortCondition "
45
+ str << "descending='1' " if order == :desc
46
+ str << "ref='#{ref}' "
47
+ str << "customList='#{custom_list.join(',')}' " unless custom_list.empty?
48
+ str << "/>"
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'axlsx/workbook/worksheet/auto_filter/sort_condition'
4
+
5
+ module Axlsx
6
+ # This class performs sorting on a range in a worksheet
7
+ class SortState
8
+ # creates a new SortState object
9
+ # @param [AutoFilter] auto_filter the auto_filter that this sort_state belongs to
10
+ def initialize(auto_filter)
11
+ @auto_filter = auto_filter
12
+ end
13
+
14
+ # A collection of SortConditions for this sort_state
15
+ # @return [SimpleTypedList]
16
+ def sort_conditions
17
+ @sort_conditions ||= SimpleTypedList.new SortCondition
18
+ end
19
+
20
+ # Adds a SortCondition to the sort_state. This is the recommended way to add conditions to it.
21
+ # It requires a column_index for the sorting, descending and the custom order are optional.
22
+ # @param [Integer] column_index Zero-based index indicating the AutoFilter column to which the sorting should be applied to
23
+ # @param [Symbol] order The order the column should be sorted on, can only be :asc or :desc
24
+ # @param [Array] custom_list An array containg a custom sorting list in order.
25
+ # @return [SortCondition]
26
+ def add_sort_condition(column_index:, order: :asc, custom_list: [])
27
+ sort_conditions << SortCondition.new(column_index: column_index, order: order, custom_list: custom_list)
28
+ sort_conditions.last
29
+ end
30
+
31
+ # method to increment the String representing the first cell of the range of the autofilter by 1 row for the sortCondition
32
+ # xml string
33
+ def increment_cell_value(str)
34
+ letter = str[/[A-Za-z]+/]
35
+ number = str[/\d+/].to_i
36
+
37
+ incremented_number = number + 1
38
+
39
+ "#{letter}#{incremented_number}"
40
+ end
41
+
42
+ # serialize the object
43
+ # @return [String]
44
+ def to_xml_string(str = +'')
45
+ return if sort_conditions.empty?
46
+
47
+ ref = @auto_filter.range
48
+ first_cell, last_cell = ref.split(':')
49
+ ref = "#{increment_cell_value(first_cell)}:#{last_cell}"
50
+
51
+ str << "<sortState xmlns:xlrd2='http://schemas.microsoft.com/office/spreadsheetml/2017/richdata2' ref='#{ref}'>"
52
+ sort_conditions.each { |sort_condition| sort_condition.to_xml_string(str, ref) }
53
+ str << "</sortState>"
54
+ end
55
+ end
56
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Axlsx
2
4
  class BorderCreator
3
5
  def initialize(worksheet:, cells:, edges: nil, style: nil, color: nil)
@@ -11,12 +13,12 @@ module Axlsx
11
13
  if @edges == :all
12
14
  @edges = Axlsx::Border::EDGES
13
15
  elsif !@edges.is_a?(Array)
14
- raise ArgumentError.new("Invalid edges provided, #{@edges}")
16
+ raise ArgumentError, "Invalid edges provided, #{@edges}"
15
17
  else
16
18
  @edges = @edges.map { |x| x&.to_sym }.uniq
17
19
 
18
- if !(@edges - Axlsx::Border::EDGES).empty?
19
- raise ArgumentError.new("Invalid edges provided, #{edges}")
20
+ unless (@edges - Axlsx::Border::EDGES).empty?
21
+ raise ArgumentError, "Invalid edges provided, #{edges}"
20
22
  end
21
23
  end
22
24
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Axlsx
2
4
  # The Break class stores the details for row and column page breaks.
3
5
  # @see RowBreaks, ColBreaks
@@ -25,7 +27,7 @@ module Axlsx
25
27
  serializable_attributes :id, :min, :max, :man, :pt
26
28
 
27
29
  # serializes the break to xml
28
- def to_xml_string(str = '')
30
+ def to_xml_string(str = +'')
29
31
  serialized_tag('brk', str)
30
32
  end
31
33
  end
@@ -1,4 +1,5 @@
1
- require 'cgi'
1
+ # frozen_string_literal: true
2
+
2
3
  module Axlsx
3
4
  # A cell in a worksheet.
4
5
  # Cell stores inforamation requried to serialize a single worksheet cell to xml. You must provde the Row that the cell belongs to and the cells value. The data type will automatically be determed if you do not specify the :type option. The default style will be applied if you do not supply the :style option. Changing the cell's type will recast the value to the type specified. Altering the cell's value via the property accessor will also automatically cast the provided value to the cell's type.
@@ -40,12 +41,13 @@ module Axlsx
40
41
  self.type = type unless type == :string
41
42
 
42
43
  val = options.delete(:style)
43
- self.style = val unless val.nil? || val == 0
44
+ self.style = val unless val.nil? || val.zero?
44
45
  val = options.delete(:formula_value)
45
46
  self.formula_value = val unless val.nil?
47
+ val = options.delete(:escape_formulas)
48
+ self.escape_formulas = val unless val.nil?
46
49
 
47
- parse_options(options)
48
- self.escape_formulas = row.worksheet.escape_formulas if escape_formulas.nil?
50
+ parse_options(options) unless options.empty?
49
51
 
50
52
  self.value = value
51
53
  value.cell = self if contains_rich_text?
@@ -70,9 +72,8 @@ module Axlsx
70
72
  CELL_TYPES = [:date, :time, :float, :integer, :richtext,
71
73
  :string, :boolean, :iso_8601, :text].freeze
72
74
 
73
- # Leading characters that indicate a formula.
74
- # See: https://owasp.org/www-community/attacks/CSV_Injection
75
- FORMULA_PREFIXES = ['-', '=', '+', '@', '%', '|', "\r", "\t"].freeze
75
+ # A regular expression to match the alpha(column)numeric(row) reference of a cell
76
+ CELL_REFERENCE_REGEX = /([A-Z]+)([0-9]+)/.freeze
76
77
 
77
78
  # The index of the cellXfs item to be applied to this cell.
78
79
  # @return [Integer]
@@ -81,10 +82,15 @@ module Axlsx
81
82
  defined?(@style) ? @style : 0
82
83
  end
83
84
 
85
+ # Internal
86
+ def style_str
87
+ defined?(@style) ? @style.to_s : '0'
88
+ end
89
+
84
90
  attr_accessor :raw_style
85
91
 
86
92
  # The index of the cellXfs item to be applied to this cell.
87
- # @param [Hash] styles
93
+ # @param [Hash] style
88
94
  # @see Axlsx::Styles
89
95
  def add_style(style)
90
96
  self.raw_style ||= {}
@@ -116,7 +122,7 @@ module Axlsx
116
122
  # automatically determed.
117
123
  # @see Cell#cell_type_from_value
118
124
  # @return [Symbol] The type of data this cell's value is cast to.
119
- # @raise [ArgumentExeption] Cell.type must be one of [:date, time, :float, :integer, :string, :boolean]
125
+ # @raise [ArgumentError] Cell.type must be one of [:date, time, :float, :integer, :string, :boolean]
120
126
  # @note
121
127
  # If the value provided cannot be cast into the type specified, type is changed to :string and the following logic is applied.
122
128
  # :string to :integer or :float, type conversions always return 0 or 0.0
@@ -137,7 +143,9 @@ module Axlsx
137
143
  # Allowing user-generated data to be interpreted as formulas is a security risk.
138
144
  # See https://www.owasp.org/index.php/CSV_Injection for details.
139
145
  # @return [Boolean]
140
- attr_reader :escape_formulas
146
+ def escape_formulas
147
+ defined?(@escape_formulas) ? @escape_formulas : row.worksheet.escape_formulas
148
+ end
141
149
 
142
150
  # Sets whether to treat values starting with an equals sign as formulas or as literal strings.
143
151
  # @param [Boolean] value The value to set.
@@ -158,7 +166,7 @@ module Axlsx
158
166
 
159
167
  # Indicates that the cell has one or more of the custom cell styles applied.
160
168
  # @return [Boolean]
161
- def is_text_run?
169
+ def is_text_run? # rubocop:disable Naming/PredicateName
162
170
  defined?(@is_text_run) && @is_text_run && !contains_rich_text?
163
171
  end
164
172
 
@@ -168,12 +176,12 @@ module Axlsx
168
176
 
169
177
  # Indicates if the cell is good for shared string table
170
178
  def plain_string?
171
- (type == :string || type == :text) && # String typed
172
- !is_text_run? && # No inline styles
173
- !@value.nil? && # Not nil
174
- !@value.empty? && # Not empty
175
- !is_formula? && # Not a formula
176
- !is_array_formula? # Not an array formula
179
+ (type == :string || type == :text) && # String typed
180
+ !value.nil? &&
181
+ !value.empty? &&
182
+ !is_text_run? && # No inline styles
183
+ !is_formula? &&
184
+ !is_array_formula?
177
185
  end
178
186
 
179
187
  # The inline font_name property for the cell
@@ -274,15 +282,13 @@ module Axlsx
274
282
  def extend=(v) set_run_style :validate_boolean, :extend, v; end
275
283
 
276
284
  # The inline underline property for the cell.
277
- # It must be one of :none, :single, :double, :singleAccounting, :doubleAccounting, true
285
+ # It must be one of :none, :single, :double, :singleAccounting, :doubleAccounting
278
286
  # @return [Boolean]
279
287
  # @return [String]
280
- # @note true is for backwards compatability and is reassigned to :single
281
288
  attr_reader :u
282
289
 
283
290
  # @see u
284
291
  def u=(v)
285
- v = :single if (v == true || v == 1 || v == :true || v == 'true')
286
292
  set_run_style :validate_cell_u, :u, v
287
293
  end
288
294
 
@@ -292,7 +298,7 @@ module Axlsx
292
298
 
293
299
  # @param [String] v The 8 character representation for an rgb color #FFFFFFFF"
294
300
  def color=(v)
295
- @color = v.is_a?(Color) ? v : Color.new(:rgb => v)
301
+ @color = v.is_a?(Color) ? v : Color.new(rgb: v)
296
302
  @is_text_run = true
297
303
  end
298
304
 
@@ -338,20 +344,20 @@ module Axlsx
338
344
  # @example Relative Cell Reference
339
345
  # ws.rows.first.cells.first.r #=> "A1"
340
346
  def r
341
- Axlsx::cell_r index, @row.row_index
347
+ Axlsx.cell_r index, @row.row_index
342
348
  end
343
349
 
344
- # @return [String] The absolute alpha(column)numeric(row) reference for this sell.
350
+ # @return [String] The absolute alpha(column)numeric(row) reference for this cell.
345
351
  # @example Absolute Cell Reference
346
352
  # ws.rows.first.cells.first.r #=> "$A$1"
347
353
  def r_abs
348
- "$#{r.match(%r{([A-Z]+)([0-9]+)})[1, 2].join('$')}"
354
+ "$#{CELL_REFERENCE_REGEX.match(r)[1, 2].join('$')}"
349
355
  end
350
356
 
351
357
  # @return [Integer] The cellXfs item index applied to this cell.
352
358
  # @raise [ArgumentError] Invalid cellXfs id if the value provided is not within cellXfs items range.
353
359
  def style=(v)
354
- Axlsx::validate_unsigned_int(v)
360
+ Axlsx.validate_unsigned_int(v)
355
361
  count = styles.cellXfs.size
356
362
  raise ArgumentError, "Invalid cellXfs id" unless v < count
357
363
 
@@ -368,11 +374,11 @@ module Axlsx
368
374
  # @param [Cell, String] target The last cell, or str ref for the cell in the merge range
369
375
  def merge(target)
370
376
  start, stop = if target.is_a?(String)
371
- [self.r, target]
377
+ [r, target]
372
378
  elsif target.is_a?(Cell)
373
- Axlsx.sort_cells([self, target]).map { |c| c.r }
379
+ Axlsx.sort_cells([self, target]).map(&:r)
374
380
  end
375
- self.row.worksheet.merge_cells "#{start}:#{stop}" unless stop.nil?
381
+ row.worksheet.merge_cells "#{start}:#{stop}" unless stop.nil?
376
382
  end
377
383
 
378
384
  # Serializes the cell
@@ -380,20 +386,22 @@ module Axlsx
380
386
  # @param [Integer] c_index The cell index in the row.
381
387
  # @param [String] str The string index the cell content will be appended to. Defaults to empty string.
382
388
  # @return [String] xml text for the cell
383
- def to_xml_string(r_index, c_index, str = '')
389
+ def to_xml_string(r_index, c_index, str = +'')
384
390
  CellSerializer.to_xml_string r_index, c_index, self, str
385
391
  end
386
392
 
387
- def is_formula?
393
+ def is_formula? # rubocop:disable Naming/PredicateName
388
394
  return false if escape_formulas
389
395
 
390
- type == :string && @value.to_s.start_with?(*FORMULA_PREFIXES)
396
+ type == :string && @value.to_s.start_with?(FORMULA_PREFIX)
391
397
  end
392
398
 
393
- def is_array_formula?
399
+ def is_array_formula? # rubocop:disable Naming/PredicateName
394
400
  return false if escape_formulas
395
401
 
396
- type == :string && @value.to_s.start_with?('{=') && @value.to_s.end_with?('}')
402
+ type == :string &&
403
+ @value.to_s.start_with?(ARRAY_FORMULA_PREFIX) &&
404
+ @value.to_s.end_with?(ARRAY_FORMULA_SUFFIX)
397
405
  end
398
406
 
399
407
  # returns the absolute or relative string style reference for
@@ -417,7 +425,7 @@ module Axlsx
417
425
  # Attempts to determine the correct width for this cell's content
418
426
  # @return [Float]
419
427
  def autowidth
420
- return if is_formula? || value.nil?
428
+ return if value.nil? || is_formula?
421
429
 
422
430
  if contains_rich_text?
423
431
  string_width('', font_size) + value.autowidth
@@ -433,12 +441,13 @@ module Axlsx
433
441
  end
434
442
  end
435
443
 
436
- # Returns the sanatized value
437
- # TODO find a better way to do this as it accounts for 30% of
444
+ # Returns the sanitized value
445
+ # TODO: find a better way to do this as it accounts for 30% of
438
446
  # processing time in benchmarking...
447
+ # @return [String] The sanitized value
439
448
  def clean_value
440
- if (type == :string || type == :text) && !Axlsx::trust_input
441
- Axlsx::sanitize(::CGI.escapeHTML(@value.to_s))
449
+ if (type == :string || type == :text) && !Axlsx.trust_input
450
+ Axlsx.sanitize(::CGI.escapeHTML(@value.to_s))
442
451
  else
443
452
  @value.to_s
444
453
  end
@@ -473,13 +482,13 @@ module Axlsx
473
482
  return unless INLINE_STYLES.include?(attr.to_sym)
474
483
 
475
484
  Axlsx.send(validator, value) unless validator.nil?
476
- self.instance_variable_set :"@#{attr.to_s}", value
485
+ instance_variable_set :"@#{attr}", value
477
486
  @is_text_run = true
478
487
  end
479
488
 
480
489
  # @see ssti
481
490
  def ssti=(v)
482
- Axlsx::validate_unsigned_int(v)
491
+ Axlsx.validate_unsigned_int(v)
483
492
  @ssti = v
484
493
  end
485
494
 
@@ -498,13 +507,11 @@ module Axlsx
498
507
  :time
499
508
  elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
500
509
  :boolean
501
- elsif v.to_s =~ Axlsx::NUMERIC_REGEX && v.respond_to?(:to_i)
510
+ elsif v.respond_to?(:to_i) && Axlsx::NUMERIC_REGEX.match?(v.to_s)
502
511
  :integer
503
- elsif v.to_s =~ Axlsx::SAFE_FLOAT_REGEX && v.respond_to?(:to_f)
504
- :float
505
- elsif (matchdata = v.to_s.match(MAYBE_FLOAT_REGEX)) && (Float::MIN_10_EXP..Float::MAX_10_EXP).cover?(matchdata[:exp].to_i) && v.respond_to?(:to_f)
512
+ elsif v.respond_to?(:to_f) && (Axlsx::SAFE_FLOAT_REGEX.match?(v.to_s) || ((matchdata = MAYBE_FLOAT_REGEX.match(v.to_s)) && matchdata[:exp].to_i.between?(Float::MIN_10_EXP, Float::MAX_10_EXP)))
506
513
  :float
507
- elsif v.to_s =~ Axlsx::ISO_8601_REGEX
514
+ elsif Axlsx::ISO_8601_REGEX.match?(v.to_s)
508
515
  :iso_8601
509
516
  elsif v.is_a? RichText
510
517
  :richtext
@@ -518,18 +525,18 @@ module Axlsx
518
525
  # About Time - Time in OOXML is *different* from what you might expect. The history as to why is interesting, but you can safely assume that if you are generating docs on a mac, you will want to specify Workbook.1904 as true when using time typed values.
519
526
  # @see Axlsx#date1904
520
527
  def cast_value(v)
521
- return v if v.is_a?(RichText) || v.nil?
528
+ return v if v.nil? || v.is_a?(RichText)
522
529
 
523
530
  case type
524
531
  when :date
525
- self.style = STYLE_DATE if self.style == 0
532
+ self.style = STYLE_DATE if style.zero?
526
533
  if !v.is_a?(Date) && v.respond_to?(:to_date)
527
534
  v.to_date
528
535
  else
529
536
  v
530
537
  end
531
538
  when :time
532
- self.style = STYLE_DATE if self.style == 0
539
+ self.style = STYLE_DATE if style.zero?
533
540
  if !v.is_a?(Time) && v.respond_to?(:to_time)
534
541
  v.to_time
535
542
  else
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Axlsx
2
4
  # The Cell Serializer class contains the logic for serializing cells based on their type.
3
5
  class CellSerializer
@@ -7,28 +9,30 @@ module Axlsx
7
9
  # @param [Integer] column_index The index of the cell's column
8
10
  # @param [String] str The string to apend serialization to.
9
11
  # @return [String]
10
- def to_xml_string(row_index, column_index, cell, str = '')
11
- str << ('<c r="' << Axlsx::cell_r(column_index, row_index) << '" s="' << cell.style.to_s << '" ')
12
+ def to_xml_string(row_index, column_index, cell, str = +'')
13
+ str << '<c r="'
14
+ str << Axlsx.col_ref(column_index) << Axlsx.row_ref(row_index)
15
+ str << '" s="' << cell.style_str << '" '
12
16
  return str << '/>' if cell.value.nil?
13
17
 
14
18
  method = cell.type
15
- self.send(method, cell, str)
19
+ send(method, cell, str)
16
20
  str << '</c>'
17
21
  end
18
22
 
19
23
  # builds an xml text run based on this cells attributes.
20
24
  # @param [String] str The string instance this run will be concated to.
21
25
  # @return [String]
22
- def run_xml_string(cell, str = '')
26
+ def run_xml_string(cell, str = +'')
23
27
  if cell.is_text_run?
24
28
  valid = RichTextRun::INLINE_STYLES - [:value, :type]
25
- data = Hash[Axlsx.instance_values_for(cell).map { |k, v| [k.to_sym, v] }]
26
- data = data.select { |key, value| valid.include?(key) && !value.nil? }
29
+ data = Axlsx.instance_values_for(cell).transform_keys(&:to_sym)
30
+ data = data.select { |key, value| !value.nil? && valid.include?(key) }
27
31
  RichText.new(cell.value.to_s, data).to_xml_string(str)
28
32
  elsif cell.contains_rich_text?
29
33
  cell.value.to_xml_string(str)
30
34
  else
31
- str << ('<t>' << cell.clean_value << '</t>')
35
+ str << '<t>' << cell.clean_value << '</t>'
32
36
  end
33
37
  str
34
38
  end
@@ -37,7 +41,7 @@ module Axlsx
37
41
  # @param [Cell] cell The cell that is being serialized
38
42
  # @param [String] str The string the serialized content will be appended to.
39
43
  # @return [String]
40
- def iso_8601(cell, str = '')
44
+ def iso_8601(cell, str = +'')
41
45
  value_serialization 'd', cell.value, str
42
46
  end
43
47
 
@@ -45,23 +49,23 @@ module Axlsx
45
49
  # @param [Cell] cell The cell that is being serialized
46
50
  # @param [String] str The string the serialized content will be appended to.
47
51
  # @return [String]
48
- def date(cell, str = '')
49
- value_serialization false, DateTimeConverter::date_to_serial(cell.value).to_s, str
52
+ def date(cell, str = +'')
53
+ value_serialization false, DateTimeConverter.date_to_serial(cell.value).to_s, str
50
54
  end
51
55
 
52
56
  # Serializes cells that are type time
53
57
  # @param [Cell] cell The cell that is being serialized
54
58
  # @param [String] str The string the serialized content will be appended to.
55
59
  # @return [String]
56
- def time(cell, str = '')
57
- value_serialization false, DateTimeConverter::time_to_serial(cell.value).to_s, str
60
+ def time(cell, str = +'')
61
+ value_serialization false, DateTimeConverter.time_to_serial(cell.value).to_s, str
58
62
  end
59
63
 
60
64
  # Serializes cells that are type boolean
61
65
  # @param [Cell] cell The cell that is being serialized
62
66
  # @param [String] str The string the serialized content will be appended to.
63
67
  # @return [String]
64
- def boolean(cell, str = '')
68
+ def boolean(cell, str = +'')
65
69
  value_serialization 'b', cell.value.to_s, str
66
70
  end
67
71
 
@@ -69,7 +73,7 @@ module Axlsx
69
73
  # @param [Cell] cell The cell that is being serialized
70
74
  # @param [String] str The string the serialized content will be appended to.
71
75
  # @return [String]
72
- def float(cell, str = '')
76
+ def float(cell, str = +'')
73
77
  numeric cell, str
74
78
  end
75
79
 
@@ -77,7 +81,7 @@ module Axlsx
77
81
  # @param [Cell] cell The cell that is being serialized
78
82
  # @param [String] str The string the serialized content will be appended to.
79
83
  # @return [String]
80
- def integer(cell, str = '')
84
+ def integer(cell, str = +'')
81
85
  numeric cell, str
82
86
  end
83
87
 
@@ -85,25 +89,25 @@ module Axlsx
85
89
  # @param [Cell] cell The cell that is being serialized
86
90
  # @param [String] str The string the serialized content will be appended to.
87
91
  # @return [String]
88
- def formula_serialization(cell, str = '')
89
- str << ('t="str"><f>' << cell.clean_value.to_s.sub('=', '') << '</f>')
90
- str << ('<v>' << cell.formula_value.to_s << '</v>') unless cell.formula_value.nil?
92
+ def formula_serialization(cell, str = +'')
93
+ str << 't="str"><f>' << cell.clean_value.delete_prefix(FORMULA_PREFIX) << '</f>'
94
+ str << '<v>' << cell.formula_value.to_s << '</v>' unless cell.formula_value.nil?
91
95
  end
92
96
 
93
97
  # Serializes cells that are type array formula
94
98
  # @param [Cell] cell The cell that is being serialized
95
99
  # @param [String] str The string the serialized content will be appended to.
96
100
  # @return [String]
97
- def array_formula_serialization(cell, str = '')
98
- str << ('t="str">' << '<f t="array" ref="' << cell.r << '">' << cell.clean_value.to_s.sub('{=', '').sub(/}$/, '') << '</f>')
99
- str << ('<v>' << cell.formula_value.to_s << '</v>') unless cell.formula_value.nil?
101
+ def array_formula_serialization(cell, str = +'')
102
+ str << 't="str">' << '<f t="array" ref="' << cell.r << '">' << cell.clean_value.delete_prefix(ARRAY_FORMULA_PREFIX).delete_suffix(ARRAY_FORMULA_SUFFIX) << '</f>'
103
+ str << '<v>' << cell.formula_value.to_s << '</v>' unless cell.formula_value.nil?
100
104
  end
101
105
 
102
106
  # Serializes cells that are type inline_string
103
107
  # @param [Cell] cell The cell that is being serialized
104
108
  # @param [String] str The string the serialized content will be appended to.
105
109
  # @return [String]
106
- def inline_string_serialization(cell, str = '')
110
+ def inline_string_serialization(cell, str = +'')
107
111
  str << 't="inlineStr"><is>'
108
112
  run_xml_string cell, str
109
113
  str << '</is>'
@@ -113,7 +117,7 @@ module Axlsx
113
117
  # @param [Cell] cell The cell that is being serialized
114
118
  # @param [String] str The string the serialized content will be appended to.
115
119
  # @return [String]
116
- def string(cell, str = '')
120
+ def string(cell, str = +'')
117
121
  if cell.is_array_formula?
118
122
  array_formula_serialization cell, str
119
123
  elsif cell.is_formula?
@@ -151,13 +155,13 @@ module Axlsx
151
155
 
152
156
  private
153
157
 
154
- def numeric(cell, str = '')
158
+ def numeric(cell, str = +'')
155
159
  value_serialization 'n', cell.value, str
156
160
  end
157
161
 
158
- def value_serialization(serialization_type, serialization_value, str = '')
159
- str << ('t="' << serialization_type.to_s << '"') if serialization_type
160
- str << ('><v>' << serialization_value.to_s << '</v>')
162
+ def value_serialization(serialization_type, serialization_value, str = +'')
163
+ str << 't="' << serialization_type.to_s << '"' if serialization_type
164
+ str << '><v>' << serialization_value.to_s << '</v>'
161
165
  end
162
166
  end
163
167
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Axlsx
2
4
  # Conditional Format Value Object
3
5
  # Describes the values of the interpolation points in a gradient scale. This object is used by ColorScale, DataBar and IconSet classes
@@ -38,10 +40,10 @@ module Axlsx
38
40
  attr_reader :val
39
41
 
40
42
  # @see type
41
- def type=(v); Axlsx::validate_conditional_formatting_value_object_type(v); @type = v end
43
+ def type=(v); Axlsx.validate_conditional_formatting_value_object_type(v); @type = v end
42
44
 
43
45
  # @see gte
44
- def gte=(v); Axlsx::validate_boolean(v); @gte = v end
46
+ def gte=(v); Axlsx.validate_boolean(v); @gte = v end
45
47
 
46
48
  # @see val
47
49
  def val=(v)
@@ -53,7 +55,7 @@ module Axlsx
53
55
  # serialize the Csvo object
54
56
  # @param [String] str
55
57
  # @return [String]
56
- def to_xml_string(str = '')
58
+ def to_xml_string(str = +'')
57
59
  serialized_tag('cfvo', str)
58
60
  end
59
61
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Axlsx
2
4
  # A collection of Cfvo objects that initializes with the required
3
5
  # first two items
@@ -9,7 +11,7 @@ module Axlsx
9
11
  # Serialize the Cfvo object
10
12
  # @param [String] str
11
13
  # @return [String]
12
- def to_xml_string(str = '')
14
+ def to_xml_string(str = +'')
13
15
  each { |cfvo| cfvo.to_xml_string(str) }
14
16
  end
15
17
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Axlsx
2
4
  # The Col class defines column attributes for columns in sheets.
3
5
  class Col
@@ -86,7 +88,7 @@ module Axlsx
86
88
  # @see Col#outline
87
89
  def outline_level=(v)
88
90
  Axlsx.validate_unsigned_numeric(v)
89
- raise ArgumentError, 'outlineLevel must be between 0 and 7' unless 0 <= v && v <= 7
91
+ raise ArgumentError, 'outlineLevel must be between 0 and 7' unless v >= 0 && v <= 7
90
92
 
91
93
  @outline_level = v
92
94
  end
@@ -112,7 +114,7 @@ module Axlsx
112
114
  # current @width value.
113
115
  # TODO!!!
114
116
  # Axlsx.validate_unsigned_numeric(v) unless v == nil
115
- @custom_width = @best_fit = v != nil
117
+ @custom_width = @best_fit = !v.nil?
116
118
  @width = v.nil? ? v : [v, MAX_WIDTH].min
117
119
  end
118
120
 
@@ -135,7 +137,7 @@ module Axlsx
135
137
  # Serialize this columns data to an xml string
136
138
  # @param [String] str
137
139
  # @return [String]
138
- def to_xml_string(str = '')
140
+ def to_xml_string(str = +'')
139
141
  serialized_tag('col', str)
140
142
  end
141
143
  end