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,10 +1,10 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
+
2
3
  module Axlsx
3
4
  # Table
4
5
  # @note Worksheet#add_table is the recommended way to create tables for your worksheets.
5
6
  # @see README for examples
6
7
  class Table
7
-
8
8
  include Axlsx::OptionsParser
9
9
 
10
10
  # Creates a new Table object
@@ -12,13 +12,13 @@ module Axlsx
12
12
  # @param [Worksheet] sheet The sheet containing the table data.
13
13
  # @option options [Cell, String] name
14
14
  # @option options [TableStyle] style
15
- def initialize(ref, sheet, options={})
15
+ def initialize(ref, sheet, options = {})
16
16
  @ref = ref
17
17
  @sheet = sheet
18
18
  @style = nil
19
19
  @sheet.workbook.tables << self
20
20
  @table_style_info = TableStyleInfo.new(options[:style_info]) if options[:style_info]
21
- @name = "Table#{index+1}"
21
+ @name = "Table#{index + 1}"
22
22
  parse_options options
23
23
  yield self if block_given?
24
24
  end
@@ -44,7 +44,7 @@ module Axlsx
44
44
  # The part name for this table
45
45
  # @return [String]
46
46
  def pn
47
- "#{TABLE_PN % (index+1)}"
47
+ format(TABLE_PN, index + 1)
48
48
  end
49
49
 
50
50
  # The relationship id for this table.
@@ -64,7 +64,7 @@ module Axlsx
64
64
  end
65
65
  end
66
66
 
67
- # TableStyleInfo for the table.
67
+ # TableStyleInfo for the table.
68
68
  # initialization can be fed via the :style_info option
69
69
  def table_style_info
70
70
  @table_style_info ||= TableStyleInfo.new
@@ -73,14 +73,14 @@ module Axlsx
73
73
  # Serializes the object
74
74
  # @param [String] str
75
75
  # @return [String]
76
- def to_xml_string(str = '')
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 << '">')
82
- header_cells.each_with_index do |cell,index|
83
- str << ('<tableColumn id ="' << (index+1).to_s << '" name="' << cell.clean_value << '"/>')
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
+ header_cells.each_with_index do |cell, index|
83
+ str << '<tableColumn id ="' << (index + 1).to_s << '" name="' << cell.clean_value << '"/>'
84
84
  end
85
85
  str << '</tableColumns>'
86
86
  table_style_info.to_xml_string(str)
@@ -1,5 +1,6 @@
1
- module Axlsx
1
+ # frozen_string_literal: true
2
2
 
3
+ module Axlsx
3
4
  # The table style info class manages style attributes for defined tables in
4
5
  # a worksheet
5
6
  class TableStyleInfo
@@ -15,7 +16,7 @@ module Axlsx
15
16
  # @option [Boolean] show_column_stripes indicates if column stripes should
16
17
  # be shown
17
18
  # @option [Boolean] show_row_stripes indicates if row stripes should be shown
18
- # @option [String] name The name of the style to apply to your table.
19
+ # @option [String] name The name of the style to apply to your table.
19
20
  # Only predefined styles are currently supported.
20
21
  # @see Annex G. (normative) Predefined SpreadsheetML Style Definitions in part 1 of the specification.
21
22
  def initialize(options = {})
@@ -27,13 +28,13 @@ module Axlsx
27
28
  # boolean attributes for this object
28
29
  boolean_attr_accessor :show_first_column, :show_last_column, :show_row_stripes, :show_column_stripes
29
30
  serializable_attributes :show_first_column, :show_last_column, :show_row_stripes, :show_column_stripes,
30
- :name
31
+ :name
31
32
 
32
33
  # Initialize all the values to false as Excel requires them to
33
34
  # explicitly be disabled or all will show.
34
35
  def initialize_defaults
35
36
  %w(show_first_column show_last_column show_row_stripes show_column_stripes).each do |attr|
36
- self.send("#{attr}=", 0)
37
+ send("#{attr}=", 0)
37
38
  end
38
39
  end
39
40
 
@@ -42,7 +43,7 @@ module Axlsx
42
43
 
43
44
  # seralizes this object to an xml string
44
45
  # @param [String] str the string to contact this objects serialization to.
45
- def to_xml_string(str = '')
46
+ def to_xml_string(str = +'')
46
47
  serialized_tag('tableStyleInfo', str)
47
48
  end
48
49
  end
@@ -1,11 +1,12 @@
1
- module Axlsx
1
+ # frozen_string_literal: true
2
2
 
3
+ module Axlsx
3
4
  # A simple, self serializing class for storing tables
4
5
  class Tables < SimpleTypedList
5
-
6
6
  # creates a new Tables object
7
7
  def initialize(worksheet)
8
8
  raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet)
9
+
9
10
  super Table
10
11
  @worksheet = worksheet
11
12
  end
@@ -17,18 +18,19 @@ module Axlsx
17
18
  # returns the relationships required by this collection
18
19
  def relationships
19
20
  return [] if empty?
20
- map{ |table| Relationship.new(table, TABLE_R, "../#{table.pn}") }
21
+
22
+ map { |table| Relationship.new(table, TABLE_R, "../#{table.pn}") }
21
23
  end
22
24
 
23
25
  # renders the tables xml
24
26
  # @param [String] str
25
27
  # @return [String]
26
- def to_xml_string(str = "")
28
+ def to_xml_string(str = +'')
27
29
  return if empty?
30
+
28
31
  str << "<tableParts count='#{size}'>"
29
32
  each { |table| str << "<tablePart r:id='#{table.rId}'/>" }
30
33
  str << '</tableParts>'
31
34
  end
32
35
  end
33
-
34
36
  end
@@ -1,9 +1,8 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  require_relative "border_creator"
4
4
 
5
5
  module Axlsx
6
-
7
6
  # The Worksheet class represents a worksheet in the workbook.
8
7
  class Worksheet
9
8
  include Axlsx::OptionsParser
@@ -16,12 +15,15 @@ module Axlsx
16
15
  # @option options [Hash] page_margins A hash containing page margins for this worksheet. @see PageMargins
17
16
  # @option options [Hash] print_options A hash containing print options for this worksheet. @see PrintOptions
18
17
  # @option options [Hash] header_footer A hash containing header/footer options for this worksheet. @see HeaderFooter
19
- # @option options [Boolean] show_gridlines indicates if gridlines should be shown for this sheet.
20
- def initialize(wb, options={})
18
+ # @option options [Boolean] show_gridlines Whether gridlines should be shown for this sheet.
19
+ # @option options [Boolean] escape_formulas Whether formulas should be escaped by default. Can be overridden at a
20
+ # row/cell level.
21
+ def initialize(wb, options = {})
21
22
  self.workbook = wb
22
23
  @sheet_protection = nil
23
24
  initialize_page_options(options)
24
25
  parse_options options
26
+ self.escape_formulas = wb.escape_formulas unless defined? @escape_formulas
25
27
  @workbook.worksheets << self
26
28
  @sheet_id = index + 1
27
29
  yield self if block_given?
@@ -43,13 +45,27 @@ module Axlsx
43
45
  # The name of the worksheet
44
46
  # @return [String]
45
47
  def name
46
- @name ||= "Sheet" + (index+1).to_s
48
+ @name ||= "Sheet#{index + 1}"
49
+ end
50
+
51
+ # Whether to treat values starting with an equals sign as formulas or as literal strings.
52
+ # Allowing user-generated data to be interpreted as formulas is a security risk.
53
+ # See https://www.owasp.org/index.php/CSV_Injection for details.
54
+ # @return [Boolean]
55
+ attr_reader :escape_formulas
56
+
57
+ # Sets whether to treat values starting with an equals sign as formulas or as literal strings.
58
+ # @param [Boolean] value The value to set.
59
+ # @return [Boolean]
60
+ def escape_formulas=(value)
61
+ Axlsx.validate_boolean(value)
62
+ @escape_formulas = value
47
63
  end
48
64
 
49
65
  # Specifies the visible state of this sheet. Allowed states are
50
66
  # :visible, :hidden or :very_hidden. The default value is :visible.
51
67
  #
52
- # Worksheets in the :hidden state can be shown using the sheet formatting properties in excel.
68
+ # Worksheets in the :hidden state can be shown using the sheet formatting properties in Excel.
53
69
  # :very_hidden sheets should be inaccessible to end users.
54
70
  # @param [Symbol] sheet_state The visible state for this sheet.
55
71
  def state=(sheet_state)
@@ -102,13 +118,13 @@ module Axlsx
102
118
  # The tables in this worksheet
103
119
  # @return [Array] of Table
104
120
  def tables
105
- @tables ||= Tables.new self
121
+ @tables ||= Tables.new self
106
122
  end
107
123
 
108
124
  # The pivot tables in this worksheet
109
125
  # @return [Array] of Table
110
126
  def pivot_tables
111
- @pivot_tables ||= PivotTables.new self
127
+ @pivot_tables ||= PivotTables.new self
112
128
  end
113
129
 
114
130
  # A collection of column breaks added to this worksheet
@@ -157,7 +173,7 @@ module Axlsx
157
173
  @rows.transpose(&block)
158
174
  end
159
175
 
160
- # A range that excel will apply an auto-filter to "A1:B3"
176
+ # A range that Excel will apply an auto-filter to "A1:B3"
161
177
  # This will turn filtering on for the cells in the range.
162
178
  # The first row is considered the header, while subsequent rows are considered to be data.
163
179
  # @return String
@@ -171,11 +187,11 @@ module Axlsx
171
187
  # @return Boolean
172
188
  # @see #page_setup
173
189
  def fit_to_page?
174
- return false unless Axlsx.instance_values_for(self).keys.include?('page_setup')
190
+ return false unless Axlsx.instance_values_for(self).key?('page_setup')
191
+
175
192
  page_setup.fit_to_page?
176
193
  end
177
194
 
178
-
179
195
  # Column info for the sheet
180
196
  # @return [SimpleTypedList]
181
197
  def column_info
@@ -311,7 +327,7 @@ module Axlsx
311
327
  # @param [String] name
312
328
  def name=(name)
313
329
  validate_sheet_name name
314
- @name=Axlsx::coder.encode(name)
330
+ @name = Axlsx.coder.encode(name)
315
331
  end
316
332
 
317
333
  # The auto filter range for the worksheet
@@ -329,13 +345,13 @@ module Axlsx
329
345
  # The part name of this worksheet
330
346
  # @return [String]
331
347
  def pn
332
- "#{WORKSHEET_PN % (index+1)}"
348
+ format(WORKSHEET_PN, index + 1)
333
349
  end
334
350
 
335
351
  # The relationship part name of this worksheet
336
352
  # @return [String]
337
353
  def rels_pn
338
- "#{WORKSHEET_RELS_PN % (index+1)}"
354
+ format(WORKSHEET_RELS_PN, index + 1)
339
355
  end
340
356
 
341
357
  # The relationship id of this worksheet.
@@ -412,7 +428,7 @@ module Axlsx
412
428
  # sign as formula (default) or as simple string.
413
429
  # Allowing user generated data to be interpreted as formulas can be dangerous
414
430
  # (see https://www.owasp.org/index.php/CSV_Injection for details).
415
- def add_row(values=[], options={})
431
+ def add_row(values = [], options = {})
416
432
  row = Row.new(self, values, options)
417
433
  update_column_info row, options.delete(:widths)
418
434
  yield row if block_given?
@@ -432,7 +448,7 @@ module Axlsx
432
448
  # @see ConditionalFormattingRule#initialize
433
449
  # @see file:examples/example_conditional_formatting.rb
434
450
  def add_conditional_formatting(cells, rules)
435
- cf = ConditionalFormatting.new( :sqref => cells )
451
+ cf = ConditionalFormatting.new(sqref: cells)
436
452
  cf.add_rules rules
437
453
  conditional_formattings << cf
438
454
  conditional_formattings
@@ -453,7 +469,7 @@ module Axlsx
453
469
  # @param [Hash] options for the hyperlink
454
470
  # @see WorksheetHyperlink for a list of options
455
471
  # @return [WorksheetHyperlink]
456
- def add_hyperlink(options={})
472
+ def add_hyperlink(options = {})
457
473
  hyperlinks.add(options)
458
474
  end
459
475
 
@@ -470,54 +486,54 @@ module Axlsx
470
486
  # @see Bar3DChart
471
487
  # @see Line3DChart
472
488
  # @see README for examples
473
- def add_chart(chart_type, options={})
489
+ def add_chart(chart_type, options = {})
474
490
  chart = worksheet_drawing.add_chart(chart_type, options)
475
491
  yield chart if block_given?
476
492
  chart
477
493
  end
478
494
 
479
495
  # needs documentation
480
- def add_table(ref, options={})
496
+ def add_table(ref, options = {})
481
497
  tables << Table.new(ref, self, options)
482
498
  yield tables.last if block_given?
483
499
  tables.last
484
500
  end
485
501
 
486
- def add_pivot_table(ref, range, options={})
502
+ def add_pivot_table(ref, range, options = {})
487
503
  pivot_tables << PivotTable.new(ref, range, self, options)
488
504
  yield pivot_tables.last if block_given?
489
505
  pivot_tables.last
490
506
  end
491
507
 
492
508
  # Shortcut to worsksheet_comments#add_comment
493
- def add_comment(options={})
509
+ def add_comment(options = {})
494
510
  worksheet_comments.add_comment(options)
495
511
  end
496
512
 
497
513
  # Adds a media item to the worksheets drawing
498
514
  # @option [Hash] options options passed to drawing.add_image
499
- def add_image(options={})
515
+ def add_image(options = {})
500
516
  image = worksheet_drawing.add_image(options)
501
517
  yield image if block_given?
502
518
  image
503
519
  end
504
520
 
505
521
  # Adds a page break (row break) to the worksheet
506
- # @param cell A Cell object or excel style string reference indicating where the break
522
+ # @param cell A Cell object or Excel style string reference indicating where the break
507
523
  # should be added to the sheet.
508
524
  # @example
509
525
  # ws.add_page_break("A4")
510
526
  def add_page_break(cell)
511
527
  DataTypeValidator.validate :worksheet_page_break, [String, Cell], cell
512
528
  column_index, row_index = if cell.is_a?(String)
513
- Axlsx.name_to_indices(cell)
514
- else
515
- cell.pos
516
- end
529
+ Axlsx.name_to_indices(cell)
530
+ else
531
+ cell.pos
532
+ end
517
533
  if column_index > 0
518
- col_breaks.add_break(:id => column_index)
534
+ col_breaks.add_break(id: column_index)
519
535
  end
520
- row_breaks.add_break(:id => row_index)
536
+ row_breaks.add_break(id: row_index)
521
537
  end
522
538
 
523
539
  # This is a helper method that Lets you specify a fixed width for multiple columns in a worksheet in one go.
@@ -529,8 +545,9 @@ module Axlsx
529
545
  # @param [Integer|Float|nil] widths
530
546
  def column_widths(*widths)
531
547
  widths.each_with_index do |value, index|
532
- next if value == nil
533
- Axlsx::validate_unsigned_numeric(value) unless value == nil
548
+ next if value.nil?
549
+
550
+ Axlsx.validate_unsigned_numeric(value) unless value.nil?
534
551
  find_or_create_column_info(index).width = value
535
552
  end
536
553
  end
@@ -543,7 +560,7 @@ module Axlsx
543
560
  # @note You can also specify the style for specific columns in the call to add_row by using an array for the :styles option
544
561
  # @see Worksheet#add_row
545
562
  # @see README.md for an example
546
- def col_style(index, style, options={})
563
+ def col_style(index, style, options = {})
547
564
  offset = options.delete(:row_offset) || 0
548
565
  cells = @rows[(offset..-1)].map { |row| row[index] }.flatten.compact
549
566
  cells.each { |cell| cell.style = style }
@@ -557,17 +574,17 @@ module Axlsx
557
574
  # @note You can also specify the style in the add_row call
558
575
  # @see Worksheet#add_row
559
576
  # @see README.md for an example
560
- def row_style(index, style, options={})
577
+ def row_style(index, style, options = {})
561
578
  offset = options.delete(:col_offset) || 0
562
579
  cells = cols[(offset..-1)].map { |column| column[index] }.flatten.compact
563
580
  cells.each { |cell| cell.style = style }
564
581
  end
565
582
 
566
583
  # Set the style for cells in a specific column
567
- # @param [String|Array] cell references
584
+ # @param [String|Array] cell_refs Cell references
568
585
  # @param [Hash] styles
569
586
  def add_style(cell_refs, *styles)
570
- if !cell_refs.is_a?(Array)
587
+ unless cell_refs.is_a?(Array)
571
588
  cell_refs = [cell_refs]
572
589
  end
573
590
 
@@ -585,32 +602,43 @@ module Axlsx
585
602
  end
586
603
 
587
604
  # Set the style for cells in a specific column
588
- # @param [String|Array] cell references
589
- # @param [Hash|Array|Symbol] border options
590
- def add_border(cell_refs, options = Axlsx::Border::EDGES)
591
- if !cell_refs.is_a?(Array)
605
+ # @param [String|Array] cell_refs Cell references
606
+ # @param [Hash|Array|Symbol] options border options
607
+ def add_border(cell_refs, options = nil)
608
+ if options.is_a?(Hash)
609
+ border_edges = options[:edges]
610
+ border_style = options[:style]
611
+ border_color = options[:color]
612
+ else
613
+ border_edges = options
614
+ end
615
+
616
+ unless cell_refs.is_a?(Array)
592
617
  cell_refs = [cell_refs]
593
618
  end
594
619
 
595
620
  cell_refs.each do |cell_ref|
596
- cells = self[cell_ref]
597
- Axlsx::BorderCreator.new(self, cells, options).draw
621
+ item = self[cell_ref]
622
+
623
+ cells = item.is_a?(Array) ? item : [item]
624
+
625
+ Axlsx::BorderCreator.new(worksheet: self, cells: cells, edges: border_edges, style: border_style, color: border_color).draw
598
626
  end
599
627
  end
600
628
 
601
629
  # Returns a sheet node serialization for this sheet in the workbook.
602
- def to_sheet_node_xml_string(str='')
630
+ def to_sheet_node_xml_string(str = +'')
603
631
  add_autofilter_defined_name_to_workbook
604
632
  str << '<sheet '
605
633
  serialized_attributes str
606
- str << ('name="' << name << '" ')
607
- str << ('r:id="' << rId << '"></sheet>')
634
+ str << 'name="' << name << '" '
635
+ str << 'r:id="' << rId << '"></sheet>'
608
636
  end
609
637
 
610
638
  # Serializes the worksheet object to an xml string
611
639
  # This intentionally does not use nokogiri for performance reasons
612
640
  # @return [String]
613
- def to_xml_string str=''
641
+ def to_xml_string(str = +'')
614
642
  add_autofilter_defined_name_to_workbook
615
643
  auto_filter.apply if auto_filter.range
616
644
  str << '<?xml version="1.0" encoding="UTF-8"?>'
@@ -633,23 +661,23 @@ module Axlsx
633
661
  r
634
662
  end
635
663
 
636
- # Returns the cell or cells defined using excel style A1:B3 references.
664
+ # Returns the cell or cells defined using Excel style A1:B3 references.
637
665
  # @param [String|Integer] cell_def the string defining the cell or range of cells, or the rownumber
638
666
  # @return [Cell, Array]
639
667
  def [](cell_def)
640
668
  return rows[cell_def] if cell_def.is_a?(Integer)
641
669
 
642
- parts = cell_def.split(':').map{ |part| name_to_cell part }
670
+ parts = cell_def.split(':').map { |part| name_to_cell part }
643
671
 
644
672
  if parts.size == 1
645
673
  parts.first
646
674
  else
647
675
  if parts.size > 2
648
- raise ArgumentError, (ERR_CELL_REFERENCE_INVALID % cell_def)
676
+ raise ArgumentError, format(ERR_CELL_REFERENCE_INVALID, cell_def)
649
677
  elsif parts.first.nil?
650
- raise ArgumentError, (ERR_CELL_REFERENCE_MISSING_CELL % [cell_def.split(":").first, cell_def])
678
+ raise ArgumentError, format(ERR_CELL_REFERENCE_MISSING_CELL, cell_def.split(":").first, cell_def)
651
679
  elsif parts.last.nil?
652
- raise ArgumentError, (ERR_CELL_REFERENCE_MISSING_CELL % [cell_def.split(":").last, cell_def])
680
+ raise ArgumentError, format(ERR_CELL_REFERENCE_MISSING_CELL, cell_def.split(":").last, cell_def)
653
681
  end
654
682
 
655
683
  range(*parts)
@@ -660,12 +688,12 @@ module Axlsx
660
688
  # @param [String] name The cell or cell range to return. "A1" will return the first cell of the first row.
661
689
  # @return [Cell]
662
690
  def name_to_cell(name)
663
- col_index, row_index = *Axlsx::name_to_indices(name)
691
+ col_index, row_index = *Axlsx.name_to_indices(name)
664
692
 
665
693
  r = rows[row_index]
666
694
 
667
695
  if r
668
- return r[col_index]
696
+ r[col_index]
669
697
  end
670
698
  end
671
699
 
@@ -683,7 +711,7 @@ module Axlsx
683
711
  # @note The XLSX format does not support worksheet-specific styles. Even when using this method
684
712
  # you're still working with the single global {Axlsx::Styles} object in the workbook.
685
713
  def styles
686
- @styles ||= self.workbook.styles
714
+ @styles ||= workbook.styles
687
715
  end
688
716
 
689
717
  # shortcut level to specify the outline level for a series of rows
@@ -713,7 +741,7 @@ module Axlsx
713
741
  end
714
742
 
715
743
  def outline(collection, range, level = 1, collapsed = true)
716
- range.each do |index|
744
+ range.each do |index|
717
745
  unless (item = collection[index]).nil?
718
746
  item.outline_level = level
719
747
  item.hidden = collapsed
@@ -725,13 +753,15 @@ module Axlsx
725
753
  def validate_sheet_name(name)
726
754
  DataTypeValidator.validate :worksheet_name, String, name
727
755
  # ignore first character (BOM) after encoding to utf16 because Excel does so, too.
728
- raise ArgumentError, (ERR_SHEET_NAME_EMPTY) if name.empty?
756
+ raise ArgumentError, ERR_SHEET_NAME_EMPTY if name.empty?
757
+
729
758
  character_length = name.encode("utf-16")[1..-1].encode("utf-16").bytesize / 2
730
- raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG % name) if character_length > WORKSHEET_MAX_NAME_LENGTH
731
- raise ArgumentError, (ERR_SHEET_NAME_CHARACTER_FORBIDDEN % name) if WORKSHEET_NAME_FORBIDDEN_CHARS.any? { |char| name.include? char }
732
- name = Axlsx::coder.encode(name)
733
- sheet_names = @workbook.worksheets.reject { |s| s == self }.map { |s| s.name }
734
- raise ArgumentError, (ERR_DUPLICATE_SHEET_NAME % name) if sheet_names.include?(name)
759
+ raise ArgumentError, format(ERR_SHEET_NAME_TOO_LONG, name) if character_length > WORKSHEET_MAX_NAME_LENGTH
760
+ raise ArgumentError, format(ERR_SHEET_NAME_CHARACTER_FORBIDDEN, name) if WORKSHEET_NAME_FORBIDDEN_CHARS.any? { |char| name.include? char }
761
+
762
+ name = Axlsx.coder.encode(name)
763
+ sheet_names = @workbook.worksheets.reject { |s| s == self }.map(&:name)
764
+ raise ArgumentError, format(ERR_DUPLICATE_SHEET_NAME, name) if sheet_names.include?(name)
735
765
  end
736
766
 
737
767
  def serializable_parts
@@ -783,7 +813,6 @@ module Axlsx
783
813
  @merged_cells ||= MergedCells.new self
784
814
  end
785
815
 
786
-
787
816
  # Helper method for parsingout the root node for worksheet
788
817
  # @return [String]
789
818
  def worksheet_node
@@ -821,9 +850,9 @@ module Axlsx
821
850
  end
822
851
 
823
852
  def add_autofilter_defined_name_to_workbook
824
- return if !auto_filter.range
853
+ return unless auto_filter.range
854
+
825
855
  workbook.add_defined_name auto_filter.defined_name, name: '_xlnm._FilterDatabase', local_sheet_id: index, hidden: 1
826
856
  end
827
-
828
857
  end
829
858
  end
@@ -1,13 +1,14 @@
1
- module Axlsx
1
+ # frozen_string_literal: true
2
2
 
3
+ module Axlsx
3
4
  # A wraper class for comments that defines its on worksheet
4
5
  # serailization
5
6
  class WorksheetComments
6
-
7
7
  # Creates a new WorksheetComments object
8
8
  # param [Worksheet] worksheet The worksheet comments in thes object belong to
9
9
  def initialize(worksheet)
10
10
  raise ArugumentError, 'You must provide a worksheet' unless worksheet.is_a?(Worksheet)
11
+
11
12
  @worksheet = worksheet
12
13
  end
13
14
 
@@ -22,21 +23,21 @@ module Axlsx
22
23
  # Adds a comment
23
24
  # @param [Hash] options
24
25
  # @see Comments#add_comment
25
- def add_comment(options={})
26
+ def add_comment(options = {})
26
27
  comments.add_comment(options)
27
- end
28
+ end
28
29
 
29
30
  # The relationships defined by this objects comments collection
30
31
  # @return [Relationships]
31
32
  def relationships
32
33
  return [] unless has_comments?
34
+
33
35
  comments.relationships
34
36
  end
35
37
 
36
-
37
38
  # Helper method to tell us if there are comments in the comments collection
38
39
  # @return [Boolean]
39
- def has_comments?
40
+ def has_comments? # rubocop:disable Naming/PredicateName
40
41
  !comments.empty?
41
42
  end
42
43
 
@@ -44,14 +45,15 @@ module Axlsx
44
45
  # @see Relationship#Id
45
46
  # @return [String]
46
47
  def drawing_rId
47
- comments.relationships.find{ |r| r.Type == VML_DRAWING_R }.Id
48
+ comments.relationships.find { |r| r.Type == VML_DRAWING_R }.Id
48
49
  end
49
50
 
50
51
  # Seraalize the object
51
52
  # @param [String] str
52
53
  # @return [String]
53
- def to_xml_string(str = '')
54
+ def to_xml_string(str = +'')
54
55
  return unless has_comments?
56
+
55
57
  str << "<legacyDrawing r:id='#{drawing_rId}' />"
56
58
  end
57
59
  end
@@ -1,21 +1,26 @@
1
- module Axlsx
1
+ # frozen_string_literal: true
2
2
 
3
+ module Axlsx
3
4
  # This is a utility class for serialing the drawing node in a
4
5
  # worksheet. Drawing objects have their own serialization that exports
5
6
  # a drawing document. This is only for the single node in the
6
7
  # worksheet
7
8
  class WorksheetDrawing
8
-
9
9
  # Creates a new WorksheetDrawing
10
10
  # @param [Worksheet] worksheet
11
11
  def initialize(worksheet)
12
12
  raise ArgumentError, 'you must provide a worksheet' unless worksheet.is_a?(Worksheet)
13
+
13
14
  @worksheet = worksheet
14
15
  @drawing = nil
15
16
  end
16
17
 
18
+ # The worksheet that owns the drawing
19
+ # @return [Worksheet]
17
20
  attr_reader :worksheet
18
21
 
22
+ # The drawing object
23
+ # @return [Drawing]
19
24
  attr_reader :drawing
20
25
 
21
26
  # adds a chart to the drawing object
@@ -37,7 +42,7 @@ module Axlsx
37
42
 
38
43
  # helper method to tell us if the drawing has something in it or not
39
44
  # @return [Boolean]
40
- def has_drawing?
45
+ def has_drawing? # rubocop:disable Naming/PredicateName
41
46
  @drawing.is_a? Drawing
42
47
  end
43
48
 
@@ -45,13 +50,15 @@ module Axlsx
45
50
  # @return [Relationship]
46
51
  def relationship
47
52
  return unless has_drawing?
53
+
48
54
  Relationship.new(self, DRAWING_R, "../#{drawing.pn}")
49
55
  end
50
56
 
51
57
  # Serialize the drawing for the worksheet
52
58
  # @param [String] str
53
- def to_xml_string(str = '')
59
+ def to_xml_string(str = +'')
54
60
  return unless has_drawing?
61
+
55
62
  str << "<drawing r:id='#{relationship.Id}'/>"
56
63
  end
57
64
  end