write_xlsx 1.12.3 → 1.15.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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +22 -0
  3. data/Changes +23 -0
  4. data/README.md +1 -1
  5. data/lib/write_xlsx/chart/area.rb +2 -2
  6. data/lib/write_xlsx/chart/axis.rb +55 -32
  7. data/lib/write_xlsx/chart/axis_writer.rb +528 -0
  8. data/lib/write_xlsx/chart/bar.rb +2 -2
  9. data/lib/write_xlsx/chart/caption.rb +16 -9
  10. data/lib/write_xlsx/chart/chart_area.rb +121 -0
  11. data/lib/write_xlsx/chart/column.rb +2 -2
  12. data/lib/write_xlsx/chart/d_pt_point_writer.rb +14 -0
  13. data/lib/write_xlsx/chart/doughnut.rb +0 -3
  14. data/lib/write_xlsx/chart/formatting_writer.rb +652 -0
  15. data/lib/write_xlsx/chart/initialization.rb +100 -0
  16. data/lib/write_xlsx/chart/line.rb +4 -3
  17. data/lib/write_xlsx/chart/pie.rb +6 -2
  18. data/lib/write_xlsx/chart/radar.rb +2 -2
  19. data/lib/write_xlsx/chart/scatter.rb +4 -3
  20. data/lib/write_xlsx/chart/series.rb +35 -15
  21. data/lib/write_xlsx/chart/series_data.rb +132 -0
  22. data/lib/write_xlsx/chart/series_writer.rb +318 -0
  23. data/lib/write_xlsx/chart/settings.rb +226 -0
  24. data/lib/write_xlsx/chart/stock.rb +2 -2
  25. data/lib/write_xlsx/chart/table.rb +50 -0
  26. data/lib/write_xlsx/chart/xml_writer.rb +305 -0
  27. data/lib/write_xlsx/chart.rb +286 -2477
  28. data/lib/write_xlsx/chartsheet.rb +35 -83
  29. data/lib/write_xlsx/constants.rb +11 -0
  30. data/lib/write_xlsx/drawing.rb +5 -3
  31. data/lib/write_xlsx/format/alignment_state.rb +39 -0
  32. data/lib/write_xlsx/format/alignment_style.rb +92 -0
  33. data/lib/write_xlsx/format/border_state.rb +47 -0
  34. data/lib/write_xlsx/format/border_style.rb +116 -0
  35. data/lib/write_xlsx/format/fill_state.rb +26 -0
  36. data/lib/write_xlsx/format/fill_style.rb +52 -0
  37. data/lib/write_xlsx/format/font_state.rb +74 -0
  38. data/lib/write_xlsx/format/font_style.rb +172 -0
  39. data/lib/write_xlsx/format/format_state.rb +65 -0
  40. data/lib/write_xlsx/format/number_format_state.rb +20 -0
  41. data/lib/write_xlsx/format/number_format_style.rb +28 -0
  42. data/lib/write_xlsx/format/protection_state.rb +20 -0
  43. data/lib/write_xlsx/format/protection_style.rb +28 -0
  44. data/lib/write_xlsx/format.rb +1093 -426
  45. data/lib/write_xlsx/formats.rb +0 -2
  46. data/lib/write_xlsx/image_property.rb +4 -1
  47. data/lib/write_xlsx/inserted_chart.rb +1 -1
  48. data/lib/write_xlsx/object_positioning.rb +203 -0
  49. data/lib/write_xlsx/package/app.rb +3 -3
  50. data/lib/write_xlsx/package/button.rb +6 -2
  51. data/lib/write_xlsx/package/comments.rb +11 -3
  52. data/lib/write_xlsx/package/conditional_format.rb +7 -3
  53. data/lib/write_xlsx/package/content_types.rb +2 -2
  54. data/lib/write_xlsx/package/core.rb +2 -2
  55. data/lib/write_xlsx/package/custom.rb +3 -2
  56. data/lib/write_xlsx/package/metadata.rb +2 -2
  57. data/lib/write_xlsx/package/packager.rb +0 -3
  58. data/lib/write_xlsx/package/relationships.rb +2 -2
  59. data/lib/write_xlsx/package/rich_value.rb +4 -2
  60. data/lib/write_xlsx/package/rich_value_rel.rb +2 -2
  61. data/lib/write_xlsx/package/rich_value_structure.rb +2 -2
  62. data/lib/write_xlsx/package/rich_value_types.rb +3 -3
  63. data/lib/write_xlsx/package/shared_strings.rb +2 -2
  64. data/lib/write_xlsx/package/styles.rb +13 -9
  65. data/lib/write_xlsx/package/table.rb +8 -2
  66. data/lib/write_xlsx/package/theme.rb +0 -3
  67. data/lib/write_xlsx/package/vml.rb +2 -2
  68. data/lib/write_xlsx/page_setup.rb +192 -0
  69. data/lib/write_xlsx/shape.rb +97 -100
  70. data/lib/write_xlsx/sheets.rb +9 -4
  71. data/lib/write_xlsx/sparkline.rb +2 -2
  72. data/lib/write_xlsx/utility/cell_reference.rb +124 -0
  73. data/lib/write_xlsx/utility/chart_formatting.rb +262 -0
  74. data/lib/write_xlsx/utility/common.rb +44 -0
  75. data/lib/write_xlsx/utility/date_time.rb +113 -0
  76. data/lib/write_xlsx/utility/dimensions.rb +40 -0
  77. data/lib/write_xlsx/utility/drawing.rb +136 -0
  78. data/lib/write_xlsx/utility/rich_text.rb +184 -0
  79. data/lib/write_xlsx/utility/sheetname_quoting.rb +73 -0
  80. data/lib/write_xlsx/utility/string_width.rb +45 -0
  81. data/lib/write_xlsx/utility/url.rb +27 -0
  82. data/lib/write_xlsx/utility/xml_primitives.rb +32 -0
  83. data/lib/write_xlsx/version.rb +1 -1
  84. data/lib/write_xlsx/workbook/chart_data.rb +188 -0
  85. data/lib/write_xlsx/workbook/format_preparation.rb +199 -0
  86. data/lib/write_xlsx/workbook/initialization.rb +223 -0
  87. data/lib/write_xlsx/workbook/package_preparation.rb +231 -0
  88. data/lib/write_xlsx/workbook/workbook_writer.rb +164 -0
  89. data/lib/write_xlsx/workbook.rb +143 -981
  90. data/lib/write_xlsx/worksheet/asset_manager.rb +60 -0
  91. data/lib/write_xlsx/worksheet/autofilter.rb +390 -0
  92. data/lib/write_xlsx/worksheet/cell_data.rb +13 -6
  93. data/lib/write_xlsx/worksheet/cell_data_manager.rb +47 -0
  94. data/lib/write_xlsx/worksheet/cell_data_store.rb +61 -0
  95. data/lib/write_xlsx/worksheet/columns.rb +204 -0
  96. data/lib/write_xlsx/worksheet/comments_support.rb +61 -0
  97. data/lib/write_xlsx/worksheet/conditional_formats.rb +30 -0
  98. data/lib/write_xlsx/worksheet/data_validation.rb +9 -1
  99. data/lib/write_xlsx/worksheet/data_writing.rb +1017 -0
  100. data/lib/write_xlsx/worksheet/drawing_methods.rb +308 -0
  101. data/lib/write_xlsx/worksheet/drawing_preparation.rb +290 -0
  102. data/lib/write_xlsx/worksheet/drawing_relations.rb +76 -0
  103. data/lib/write_xlsx/worksheet/drawing_xml_writer.rb +50 -0
  104. data/lib/write_xlsx/worksheet/formatting.rb +418 -0
  105. data/lib/write_xlsx/worksheet/hyperlink.rb +9 -1
  106. data/lib/write_xlsx/worksheet/initialization.rb +146 -0
  107. data/lib/write_xlsx/worksheet/panes.rb +64 -0
  108. data/lib/write_xlsx/worksheet/print_options.rb +72 -0
  109. data/lib/write_xlsx/worksheet/protection.rb +65 -0
  110. data/lib/write_xlsx/worksheet/rich_text_helpers.rb +78 -0
  111. data/lib/write_xlsx/worksheet/row_col_sizing.rb +69 -0
  112. data/lib/write_xlsx/worksheet/rows.rb +84 -0
  113. data/lib/write_xlsx/worksheet/selection.rb +41 -0
  114. data/lib/write_xlsx/worksheet/xml_writer.rb +1246 -0
  115. data/lib/write_xlsx/worksheet.rb +376 -4530
  116. metadata +66 -4
  117. data/lib/write_xlsx/utility.rb +0 -986
  118. data/lib/write_xlsx/worksheet/page_setup.rb +0 -192
@@ -0,0 +1,204 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Writexlsx
4
+ class Worksheet
5
+ # Column-related operations extracted from Worksheet to slim the main class.
6
+ module Columns
7
+ # :call-seq:
8
+ # set_column(firstcol, lastcol, width, format, hidden, level, collapsed)
9
+ #
10
+ # This method can be used to change the default properties of a single
11
+ # column or a range of columns. All parameters apart from +first_col+
12
+ # and +last_col+ are optional.
13
+ def set_column(*args)
14
+ # Check for a cell reference in A1 notation and substitute row and column
15
+ # ruby 3.2 no longer handles =~ for various types
16
+ if args[0].respond_to?(:=~) && args[0].to_s =~ /^\D/
17
+ _row1, firstcol, _row2, lastcol, *data = substitute_cellref(*args)
18
+ else
19
+ firstcol, lastcol, *data = args
20
+ end
21
+
22
+ # Ensure at least firstcol, lastcol and width
23
+ return unless firstcol && lastcol && !data.empty?
24
+
25
+ # Assume second column is the same as first if 0. Avoids KB918419 bug.
26
+ lastcol = firstcol unless ptrue?(lastcol)
27
+
28
+ # Ensure 2nd col is larger than first. Also for KB918419 bug.
29
+ firstcol, lastcol = lastcol, firstcol if firstcol > lastcol
30
+
31
+ width, format, hidden, level, collapsed = data
32
+ autofit = 0
33
+
34
+ # Check that cols are valid and store max and min values with default row.
35
+ # NOTE: The check shouldn't modify the row dimensions and should only modify
36
+ # the column dimensions in certain cases.
37
+ ignore_row = 1
38
+ ignore_col = 1
39
+ ignore_col = 0 if format.respond_to?(:xf_index) # Column has a format.
40
+ ignore_col = 0 if width && ptrue?(hidden) # Column has a width but is hidden
41
+
42
+ check_dimensions_and_update_max_min_values(0, firstcol, ignore_row, ignore_col)
43
+ check_dimensions_and_update_max_min_values(0, lastcol, ignore_row, ignore_col)
44
+
45
+ # Set the limits for the outline levels (0 <= x <= 7).
46
+ level ||= 0
47
+ level = 0 if level < 0
48
+ level = 7 if level > 7
49
+
50
+ # Excel has a maximum column width of 255 characters.
51
+ width = 255.0 if width && width > 255.0
52
+
53
+ @outline_col_level = level if level > @outline_col_level
54
+
55
+ # Store the column data based on the first column. Padded for sorting.
56
+ (firstcol..lastcol).each do |col|
57
+ @col_info[col] =
58
+ COLINFO.new(width, format, hidden, level, collapsed, autofit)
59
+ end
60
+
61
+ # Store the column change to allow optimisations.
62
+ @col_size_changed = true
63
+ end
64
+
65
+ #
66
+ # Set the width (and properties) of a single column or a range of columns in
67
+ # pixels rather than character units.
68
+ #
69
+ def set_column_pixels(*data)
70
+ cell = data[0]
71
+
72
+ # Check for a cell reference in A1 notation and substitute row and column
73
+ if cell =~ /^\D/
74
+ data = substitute_cellref(*data)
75
+
76
+ # Returned values row1 and row2 aren't required here. Remove them.
77
+ data.shift # $row1
78
+ data.delete_at(1) # $row2
79
+ end
80
+
81
+ # Ensure at least $first_col, $last_col and $width
82
+ return if data.size < 3
83
+
84
+ first_col, last_col, pixels, format, hidden, level = data
85
+ hidden ||= 0
86
+
87
+ width = pixels_to_width(pixels) if ptrue?(pixels)
88
+
89
+ set_column(first_col, last_col, width, format, hidden, level)
90
+ end
91
+
92
+ #
93
+ # autofit()
94
+ #
95
+ # Simulate autofit based on the data, and datatypes in each column. We do this
96
+ # by estimating a pixel width for each cell data.
97
+ #
98
+ def autofit(max_width = 255.0)
99
+ col_width = {}
100
+
101
+ # Convert the autofit maximum pixel width to a column/character width, but
102
+ # limit it to the Excel max limit.
103
+ max_width = pixels_to_width(max_width)
104
+ max_width = 255.0 if max_width > 255.0
105
+
106
+ # Iterate through all the data in the worksheet.
107
+ (@dim_rowmin..@dim_rowmax).each do |row_num|
108
+ # Skip row if it doesn't contain cell data.
109
+ next unless @cell_data_store[row_num]
110
+
111
+ (@dim_colmin..@dim_colmax).each do |col_num|
112
+ length = 0
113
+ case (cell_data = @cell_data_store[row_num][col_num])
114
+ when StringCellData, RichStringCellData
115
+ # Handle strings and rich strings.
116
+ #
117
+ # For standard shared strings we do a reverse lookup
118
+ # from the shared string id to the actual string. For
119
+ # rich strings we use the unformatted string. We also
120
+ # split multiline strings and handle each part
121
+ # separately.
122
+ string = cell_data.raw_string
123
+
124
+ length = if string =~ /\n/
125
+ # Handle multiline strings.
126
+ max = string.split("\n").collect do |str|
127
+ xl_string_pixel_width(str)
128
+ end.max
129
+ else
130
+ xl_string_pixel_width(string)
131
+ end
132
+ when DateTimeCellData
133
+
134
+ # Handle dates.
135
+ #
136
+ # The following uses the default width for mm/dd/yyyy
137
+ # dates. It isn't feasible to parse the number format
138
+ # to get the actual string width for all format types.
139
+ length = @default_date_pixels
140
+ when NumberCellData
141
+
142
+ # Handle numbers.
143
+ #
144
+ # We use a workaround/optimization for numbers since
145
+ # digits all have a pixel width of 7. This gives a
146
+ # slightly greater width for the decimal place and
147
+ # minus sign but only by a few pixels and
148
+ # over-estimation is okay.
149
+ length = 7 * cell_data.token.to_s.length
150
+ when BooleanCellData
151
+
152
+ # Handle boolean values.
153
+ #
154
+ # Use the Excel standard widths for TRUE and FALSE.
155
+ length = if ptrue?(cell_data.token)
156
+ 31
157
+ else
158
+ 36
159
+ end
160
+ when FormulaCellData, FormulaArrayCellData, DynamicFormulaArrayCellData
161
+ # Handle formulas.
162
+ #
163
+ # We only try to autofit a formula if it has a
164
+ # non-zero value.
165
+ if ptrue?(cell_data.data)
166
+ length = xl_string_pixel_width(cell_data.data)
167
+ end
168
+ end
169
+
170
+ # If the cell is in an autofilter header we add an
171
+ # additional 16 pixels for the dropdown arrow.
172
+ if length > 0 &&
173
+ @filter_cells["#{row_num}:#{col_num}"]
174
+ length += 16
175
+ end
176
+
177
+ # Add the string lenght to the lookup hash.
178
+ max = col_width[col_num] || 0
179
+ col_width[col_num] = length if length > max
180
+ end
181
+ end
182
+
183
+ # Apply the width to the column.
184
+ col_width.each do |col_num, pixel_width|
185
+ # Convert the string pixel width to a character width using an
186
+ # additional padding of 7 pixels, like Excel.
187
+ width = pixels_to_width(pixel_width + 7)
188
+
189
+ # Limit the width to the maximum user or Excel value.
190
+ width = max_width if width > max_width
191
+
192
+ # Add the width to an existing col info structure or add a new one.
193
+ if @col_info[col_num]
194
+ @col_info[col_num].width = width
195
+ @col_info[col_num].autofit = 1
196
+ else
197
+ @col_info[col_num] =
198
+ COLINFO.new(width, nil, 0, 0, 0, 1)
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,61 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ module Writexlsx
5
+ class Worksheet
6
+ module CommentsSupport
7
+ #
8
+ # This method is used to make all cell comments visible when a worksheet
9
+ # is opened.
10
+ #
11
+ def show_comments(visible = true)
12
+ @comments_visible = visible
13
+ end
14
+
15
+ def comments_visible? # :nodoc:
16
+ !!@comments_visible
17
+ end
18
+
19
+ #
20
+ # This method is used to set the default author of all cell comments.
21
+ #
22
+ def comments_author=(author)
23
+ @comments_author = author || ''
24
+ end
25
+
26
+ # This method is deprecated. use comments_author=().
27
+ def set_comments_author(author)
28
+ put_deprecate_message("#{self}.set_comments_author")
29
+ self.comments_author = author
30
+ end
31
+
32
+ def sorted_comments # :nodoc:
33
+ @comments.sorted_comments
34
+ end
35
+
36
+ def num_comments_block
37
+ @comments.size / 1024
38
+ end
39
+
40
+ def has_comments? # :nodoc:
41
+ !@comments.empty?
42
+ end
43
+
44
+ def has_vml? # :nodoc:
45
+ @has_vml
46
+ end
47
+
48
+ def has_header_vml? # :nodoc:
49
+ !(header_images.empty? && footer_images.empty?)
50
+ end
51
+
52
+ def buttons_data # :nodoc:
53
+ @buttons_array
54
+ end
55
+
56
+ def header_images_data # :nodoc:
57
+ @header_images_array
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Writexlsx
4
+ class Worksheet
5
+ # Conditional formatting operations extracted from Worksheet to slim the main class.
6
+ module ConditionalFormats
7
+ #
8
+ # :call-seq:
9
+ # conditional_formatting(cell_or_cell_range, options)
10
+ #
11
+ # Conditional formatting is a feature of Excel which allows you to apply a
12
+ # format to a cell or a range of cells based on a certain criteria.
13
+ #
14
+ def conditional_formatting(*args)
15
+ cond_format = Package::ConditionalFormat.factory(self, *args)
16
+ @cond_formats[cond_format.range] ||= []
17
+ @cond_formats[cond_format.range] << cond_format
18
+ end
19
+
20
+ #
21
+ # Write the <conditionalFormatting> element.
22
+ #
23
+ def write_conditional_formatting(range, cond_formats) # :nodoc:
24
+ @writer.tag_elements('conditionalFormatting', [['sqref', range]]) do
25
+ cond_formats.each(&:write_cf_rule)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,10 +1,18 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'write_xlsx/utility/common'
5
+ require 'write_xlsx/utility/cell_reference'
6
+ require 'write_xlsx/utility/dimensions'
7
+ require 'write_xlsx/utility/date_time'
8
+
4
9
  module Writexlsx
5
10
  class Worksheet
6
11
  class DataValidation # :nodoc:
7
- include Writexlsx::Utility
12
+ include Writexlsx::Utility::Common
13
+ include Writexlsx::Utility::CellReference
14
+ include Writexlsx::Utility::Dimensions
15
+ include Writexlsx::Utility::DateTime
8
16
 
9
17
  attr_reader :value, :source, :minimum, :maximum, :validate, :criteria
10
18
  attr_reader :error_type, :cells, :other_cells