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,262 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ module Writexlsx
5
+ module Utility
6
+ module ChartFormatting
7
+ PATTERN_TYPES = {
8
+ 'percent_5' => 'pct5',
9
+ 'percent_10' => 'pct10',
10
+ 'percent_20' => 'pct20',
11
+ 'percent_25' => 'pct25',
12
+ 'percent_30' => 'pct30',
13
+ 'percent_40' => 'pct40',
14
+
15
+ 'percent_50' => 'pct50',
16
+ 'percent_60' => 'pct60',
17
+ 'percent_70' => 'pct70',
18
+ 'percent_75' => 'pct75',
19
+ 'percent_80' => 'pct80',
20
+ 'percent_90' => 'pct90',
21
+
22
+ 'light_downward_diagonal' => 'ltDnDiag',
23
+ 'light_upward_diagonal' => 'ltUpDiag',
24
+ 'dark_downward_diagonal' => 'dkDnDiag',
25
+ 'dark_upward_diagonal' => 'dkUpDiag',
26
+ 'wide_downward_diagonal' => 'wdDnDiag',
27
+ 'wide_upward_diagonal' => 'wdUpDiag',
28
+
29
+ 'light_vertical' => 'ltVert',
30
+ 'light_horizontal' => 'ltHorz',
31
+ 'narrow_vertical' => 'narVert',
32
+ 'narrow_horizontal' => 'narHorz',
33
+ 'dark_vertical' => 'dkVert',
34
+ 'dark_horizontal' => 'dkHorz',
35
+
36
+ 'dashed_downward_diagonal' => 'dashDnDiag',
37
+ 'dashed_upward_diagonal' => 'dashUpDiag',
38
+ 'dashed_horizontal' => 'dashHorz',
39
+ 'dashed_vertical' => 'dashVert',
40
+ 'small_confetti' => 'smConfetti',
41
+ 'large_confetti' => 'lgConfetti',
42
+
43
+ 'zigzag' => 'zigZag',
44
+ 'wave' => 'wave',
45
+ 'diagonal_brick' => 'diagBrick',
46
+ 'horizontal_brick' => 'horzBrick',
47
+ 'weave' => 'weave',
48
+ 'plaid' => 'plaid',
49
+
50
+ 'divot' => 'divot',
51
+ 'dotted_grid' => 'dotGrid',
52
+ 'dotted_diamond' => 'dotDmnd',
53
+ 'shingle' => 'shingle',
54
+ 'trellis' => 'trellis',
55
+ 'sphere' => 'sphere',
56
+
57
+ 'small_grid' => 'smGrid',
58
+ 'large_grid' => 'lgGrid',
59
+ 'small_check' => 'smCheck',
60
+ 'large_check' => 'lgCheck',
61
+ 'outlined_diamond' => 'openDmnd',
62
+ 'solid_diamond' => 'solidDmnd'
63
+ }.freeze
64
+
65
+ #
66
+ # Convert user defined legend properties to the structure required internally.
67
+ #
68
+ def legend_properties(params)
69
+ legend = Writexlsx::Chart::Legend.new
70
+
71
+ legend.position = params[:position] || 'right'
72
+ legend.delete_series = params[:delete_series]
73
+ legend.font = convert_font_args(params[:font])
74
+
75
+ # Set the legend layout.
76
+ legend.layout = layout_properties(params[:layout])
77
+
78
+ # Turn off the legend.
79
+ legend.position = 'none' if params[:none]
80
+
81
+ # Set the line properties for the legend.
82
+ line = line_properties(params[:line])
83
+
84
+ # Allow 'border' as a synonym for 'line'.
85
+ line = line_properties(params[:border]) if params[:border]
86
+
87
+ # Set the fill properties for the legend.
88
+ fill = fill_properties(params[:fill])
89
+
90
+ # Set the pattern properties for the legend.
91
+ pattern = pattern_properties(params[:pattern])
92
+
93
+ # Set the gradient fill properties for the legend.
94
+ gradient = gradient_properties(params[:gradient])
95
+
96
+ # Pattern fill overrides solid fill.
97
+ fill = nil if pattern
98
+
99
+ # Gradient fill overrides solid and pattern fills.
100
+ if gradient
101
+ pattern = nil
102
+ fill = nil
103
+ end
104
+
105
+ # Set the legend layout.
106
+ layout = layout_properties(params[:layout])
107
+
108
+ legend.line = line
109
+ legend.fill = fill
110
+ legend.pattern = pattern
111
+ legend.gradient = gradient
112
+ legend.layout = layout
113
+
114
+ @legend = legend
115
+ end
116
+
117
+ #
118
+ # Convert user defined layout properties to the format required internally.
119
+ #
120
+ def layout_properties(args, is_text = false)
121
+ return unless ptrue?(args)
122
+
123
+ properties = is_text ? %i[x y] : %i[x y width height]
124
+
125
+ # Check for valid properties.
126
+ args.each_key do |key|
127
+ raise "Property '#{key}' not allowed in layout options\n" unless properties.include?(key.to_sym)
128
+ end
129
+
130
+ # Set the layout properties
131
+ layout = {}
132
+ properties.each do |property|
133
+ value = args[property]
134
+ # Convert to the format used by Excel for easier testing.
135
+ layout[property] = sprintf("%.17g", value)
136
+ end
137
+
138
+ layout
139
+ end
140
+
141
+ #
142
+ # Convert user defined line properties to the structure required internally.
143
+ #
144
+ def line_properties(line) # :nodoc:
145
+ line_fill_properties(line) do
146
+ value_or_raise(dash_types, line[:dash_type], 'dash type')
147
+ end
148
+ end
149
+
150
+ #
151
+ # Convert user defined fill properties to the structure required internally.
152
+ #
153
+ def fill_properties(fill) # :nodoc:
154
+ line_fill_properties(fill)
155
+ end
156
+
157
+ #
158
+ # Convert user defined pattern properties to the structure required internally.
159
+ #
160
+ def pattern_properties(args) # :nodoc:
161
+ return nil unless args
162
+ # Check the pattern type is present.
163
+ return nil unless args.has_key?(:pattern)
164
+ # Check the foreground color is present.
165
+ return nil unless args.has_key?(:fg_color)
166
+
167
+ pattern = {}
168
+
169
+ type = PATTERN_TYPES[args[:pattern]]
170
+ raise "Unknown pattern type '#{args[:pattern]}'" unless type
171
+
172
+ pattern[:pattern] = type
173
+ pattern[:bg_color] = args[:bg_color] || '#FFFFFF'
174
+ pattern[:fg_color] = args[:fg_color]
175
+
176
+ pattern
177
+ end
178
+
179
+ def line_fill_properties(params)
180
+ return { _defined: 0 } unless params
181
+
182
+ ret = params.dup
183
+ ret[:dash_type] = yield if block_given? && ret[:dash_type]
184
+ ret[:_defined] = 1
185
+ ret
186
+ end
187
+
188
+ def dash_types
189
+ {
190
+ solid: 'solid',
191
+ round_dot: 'sysDot',
192
+ square_dot: 'sysDash',
193
+ dash: 'dash',
194
+ dash_dot: 'dashDot',
195
+ long_dash: 'lgDash',
196
+ long_dash_dot: 'lgDashDot',
197
+ long_dash_dot_dot: 'lgDashDotDot',
198
+ dot: 'dot',
199
+ system_dash_dot: 'sysDashDot',
200
+ system_dash_dot_dot: 'sysDashDotDot'
201
+ }
202
+ end
203
+
204
+ def value_or_raise(hash, key, msg)
205
+ raise "Unknown #{msg} '#{key}'" if hash[key.to_sym].nil?
206
+
207
+ hash[key.to_sym]
208
+ end
209
+
210
+ def palette_color_from_index(index)
211
+ # Adjust the colour index.
212
+ idx = index - 8
213
+
214
+ r, g, b = @palette[idx]
215
+ sprintf("%02X%02X%02X", r, g, b)
216
+ end
217
+
218
+ #
219
+ # Convert the user specified colour index or string to a rgb colour.
220
+ #
221
+ def color(color_code) # :nodoc:
222
+ if color_code && color_code =~ /^#[0-9a-fA-F]{6}$/
223
+ # Convert a HTML style #RRGGBB color.
224
+ color_code.sub(/^#/, '').upcase
225
+ else
226
+ index = Format.color(color_code)
227
+ raise "Unknown color '#{color_code}' used in chart formatting." unless index
228
+
229
+ palette_color_from_index(index)
230
+ end
231
+ end
232
+
233
+ #
234
+ # Write the <a:solidFill> element.
235
+ #
236
+ def write_a_solid_fill(fill) # :nodoc:
237
+ @writer.tag_elements('a:solidFill') do
238
+ if fill[:color]
239
+ # Write the a:srgbClr element.
240
+ write_a_srgb_clr(color(fill[:color]), fill[:transparency])
241
+ end
242
+ end
243
+ end
244
+
245
+ #
246
+ # Write the <a:srgbClr> element.
247
+ #
248
+ def write_a_srgb_clr(color, transparency = nil) # :nodoc:
249
+ tag = 'a:srgbClr'
250
+ attributes = [['val', color]]
251
+
252
+ if ptrue?(transparency)
253
+ @writer.tag_elements(tag, attributes) do
254
+ write_a_alpha(transparency)
255
+ end
256
+ else
257
+ @writer.empty_tag(tag, attributes)
258
+ end
259
+ end
260
+ end
261
+ end
262
+ end
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ module Writexlsx
5
+ module Utility
6
+ module Common
7
+ PERL_TRUE_VALUES = [false, nil, 0, "0", "", [], {}].freeze
8
+
9
+ #
10
+ # return perl's boolean result
11
+ #
12
+ def ptrue?(value)
13
+ !PERL_TRUE_VALUES.include?(value)
14
+ end
15
+
16
+ def check_parameter(params, valid_keys, method)
17
+ invalids = params.keys - valid_keys
18
+ unless invalids.empty?
19
+ raise WriteXLSXOptionParameterError,
20
+ "Unknown parameter '#{invalids.join(", ")}' in #{method}."
21
+ end
22
+ true
23
+ end
24
+
25
+ def absolute_char(absolute)
26
+ absolute ? '$' : ''
27
+ end
28
+
29
+ def float_to_str(float)
30
+ return '' unless float
31
+
32
+ if float == float.to_i
33
+ float.to_i.to_s
34
+ else
35
+ float.to_s
36
+ end
37
+ end
38
+
39
+ def put_deprecate_message(method)
40
+ warn("Warning: calling deprecated method #{method}. This method will be removed in a future release.")
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,113 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ module Writexlsx
5
+ module Utility
6
+ module DateTime
7
+ #
8
+ # convert_date_time(date_time_string)
9
+ #
10
+ # The function takes a date and time in ISO8601 "yyyy-mm-ddThh:mm:ss.ss" format
11
+ # and converts it to a decimal number representing a valid Excel date.
12
+ #
13
+ def convert_date_time(date_time_string) # :nodoc:
14
+ date_time = date_time_string.to_s.sub(/^\s+/, '').sub(/\s+$/, '').sub(/Z$/, '')
15
+
16
+ # Check for invalid date char.
17
+ return nil if date_time =~ /[^0-9T:\-.Z]/
18
+
19
+ # Check for "T" after date or before time.
20
+ return nil unless date_time =~ /\dT|T\d/
21
+
22
+ days = 0 # Number of days since epoch
23
+ seconds = 0 # Time expressed as fraction of 24h hours in seconds
24
+
25
+ # Split into date and time.
26
+ date, time = date_time.split("T")
27
+
28
+ # We allow the time portion of the input DateTime to be optional.
29
+ if time
30
+ # Match hh:mm:ss.sss+ where the seconds are optional
31
+ if time =~ /^(\d\d):(\d\d)(:(\d\d(\.\d+)?))?/
32
+ hour = ::Regexp.last_match(1).to_i
33
+ min = ::Regexp.last_match(2).to_i
34
+ sec = ::Regexp.last_match(4).to_f
35
+ else
36
+ return nil # Not a valid time format.
37
+ end
38
+
39
+ # Some boundary checks
40
+ return nil if hour >= 24
41
+ return nil if min >= 60
42
+ return nil if sec >= 60
43
+
44
+ # Excel expresses seconds as a fraction of the number in 24 hours.
45
+ seconds = ((hour * 60 * 60) + (min * 60) + sec) / (24.0 * 60 * 60)
46
+ end
47
+
48
+ # We allow the date portion of the input DateTime to be optional.
49
+ return seconds if date == ''
50
+
51
+ # Match date as yyyy-mm-dd.
52
+ if date =~ /^(\d\d\d\d)-(\d\d)-(\d\d)$/
53
+ year = ::Regexp.last_match(1).to_i
54
+ month = ::Regexp.last_match(2).to_i
55
+ day = ::Regexp.last_match(3).to_i
56
+ else
57
+ return nil # Not a valid date format.
58
+ end
59
+
60
+ # Set the epoch as 1900 or 1904. Defaults to 1900.
61
+ # Special cases for Excel.
62
+ unless date_1904?
63
+ return seconds if date == '1899-12-31' # Excel 1900 epoch
64
+ return seconds if date == '1900-01-00' # Excel 1900 epoch
65
+ return 60 + seconds if date == '1900-02-29' # Excel false leapday
66
+ end
67
+
68
+ # We calculate the date by calculating the number of days since the epoch
69
+ # and adjust for the number of leap days. We calculate the number of leap
70
+ # days by normalising the year in relation to the epoch. Thus the year 2000
71
+ # becomes 100 for 4 and 100 year leapdays and 400 for 400 year leapdays.
72
+ #
73
+ epoch = date_1904? ? 1904 : 1900
74
+ offset = date_1904? ? 4 : 0
75
+ norm = 300
76
+ range = year - epoch
77
+
78
+ # Set month days and check for leap year.
79
+ mdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
80
+ leap = 0
81
+ leap = 1 if (year % 4 == 0 && year % 100 != 0) || year % 400 == 0
82
+ mdays[1] = 29 if leap != 0
83
+
84
+ # Some boundary checks
85
+ return nil if year < epoch || year > 9999
86
+ return nil if month < 1 || month > 12
87
+ return nil if day < 1 || day > mdays[month - 1]
88
+
89
+ # Accumulate the number of days since the epoch.
90
+ days = day # Add days for current month
91
+ (0..(month - 2)).each do |m|
92
+ days += mdays[m] # Add days for past months
93
+ end
94
+ days += range * 365 # Add days for past years
95
+ days += (range / 4) # Add leapdays
96
+ days -= ((range + offset) / 100) # Subtract 100 year leapdays
97
+ days += ((range + offset + norm) / 400) # Add 400 year leapdays
98
+ days -= leap # Already counted above
99
+
100
+ # Adjust for Excel erroneously treating 1900 as a leap year.
101
+ days += 1 if !date_1904? && days > 59
102
+
103
+ date_time = sprintf("%0.10f", days + seconds)
104
+ date_time = date_time.sub(/\.?0+$/, '') if date_time =~ /\./
105
+ if date_time =~ /\./
106
+ date_time.to_f
107
+ else
108
+ date_time.to_i
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,40 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'write_xlsx/constants'
5
+
6
+ module Writexlsx
7
+ module Utility
8
+ module Dimensions
9
+ include Constants
10
+
11
+ def check_dimensions(row, col)
12
+ raise WriteXLSXDimensionError if !row || row >= ROW_MAX || !col || col >= COL_MAX
13
+
14
+ 0
15
+ end
16
+
17
+ #
18
+ # Check that row and col are valid and store max and min values for use in
19
+ # other methods/elements.
20
+ #
21
+ def check_dimensions_and_update_max_min_values(row, col, ignore_row = 0, ignore_col = 0) # :nodoc:
22
+ check_dimensions(row, col)
23
+ store_row_max_min_values(row) if ignore_row == 0
24
+ store_col_max_min_values(col) if ignore_col == 0
25
+
26
+ 0
27
+ end
28
+
29
+ def store_row_max_min_values(row)
30
+ @dim_rowmin = row if !@dim_rowmin || (row < @dim_rowmin)
31
+ @dim_rowmax = row if !@dim_rowmax || (row > @dim_rowmax)
32
+ end
33
+
34
+ def store_col_max_min_values(col)
35
+ @dim_colmin = col if !@dim_colmin || (col < @dim_colmin)
36
+ @dim_colmax = col if !@dim_colmax || (col > @dim_colmax)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,136 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ module Writexlsx
5
+ module Utility
6
+ module Drawing
7
+ #
8
+ # Convert vertices from pixels to points.
9
+ #
10
+ def pixels_to_points(vertices)
11
+ _col_start, _row_start, _x1, _y1,
12
+ _col_end, _row_end, _x2, _y2,
13
+ left, top, width, height = vertices.flatten
14
+
15
+ left *= 0.75
16
+ top *= 0.75
17
+ width *= 0.75
18
+ height *= 0.75
19
+
20
+ [left, top, width, height]
21
+ end
22
+
23
+ def v_shape_attributes_base(id)
24
+ [
25
+ ['id', "_x0000_s#{id}"],
26
+ ['type', type]
27
+ ]
28
+ end
29
+
30
+ def v_shape_style_base(z_index, vertices)
31
+ left, top, width, height = pixels_to_points(vertices)
32
+
33
+ left_str = float_to_str(left)
34
+ top_str = float_to_str(top)
35
+ width_str = float_to_str(width)
36
+ height_str = float_to_str(height)
37
+ z_index_str = float_to_str(z_index)
38
+
39
+ shape_style_base(left_str, top_str, width_str, height_str, z_index_str)
40
+ end
41
+
42
+ def shape_style_base(left_str, top_str, width_str, height_str, z_index_str)
43
+ [
44
+ 'position:absolute;',
45
+ 'margin-left:',
46
+ left_str, 'pt;',
47
+ 'margin-top:',
48
+ top_str, 'pt;',
49
+ 'width:',
50
+ width_str, 'pt;',
51
+ 'height:',
52
+ height_str, 'pt;',
53
+ 'z-index:',
54
+ z_index_str, ';'
55
+ ]
56
+ end
57
+
58
+ #
59
+ # Write the <v:fill> element.
60
+ #
61
+ def write_fill
62
+ @writer.empty_tag('v:fill', fill_attributes)
63
+ end
64
+
65
+ #
66
+ # Write the <v:path> element.
67
+ #
68
+ def write_comment_path(gradientshapeok, connecttype)
69
+ attributes = []
70
+
71
+ attributes << %w[gradientshapeok t] if gradientshapeok
72
+ attributes << ['o:connecttype', connecttype]
73
+
74
+ @writer.empty_tag('v:path', attributes)
75
+ end
76
+
77
+ #
78
+ # Write the <x:Anchor> element.
79
+ #
80
+ def write_anchor
81
+ col_start, row_start, x1, y1, col_end, row_end, x2, y2 = @vertices
82
+ data = [col_start, x1, row_start, y1, col_end, x2, row_end, y2].join(', ')
83
+
84
+ @writer.data_element('x:Anchor', data)
85
+ end
86
+
87
+ #
88
+ # Write the <x:AutoFill> element.
89
+ #
90
+ def write_auto_fill
91
+ @writer.data_element('x:AutoFill', 'False')
92
+ end
93
+
94
+ #
95
+ # Write the <div> element.
96
+ #
97
+ def write_div(align, font = nil)
98
+ style = "text-align:#{align}"
99
+ attributes = [['style', style]]
100
+
101
+ @writer.tag_elements('div', attributes) do
102
+ if font
103
+ # Write the font element.
104
+ write_font(font)
105
+ end
106
+ end
107
+ end
108
+
109
+ #
110
+ # Write the <font> element.
111
+ #
112
+ def write_font(font)
113
+ caption = font[:_caption]
114
+ face = 'Calibri'
115
+ size = 220
116
+ color = '#000000'
117
+
118
+ attributes = [
119
+ ['face', face],
120
+ ['size', size],
121
+ ['color', color]
122
+ ]
123
+ @writer.data_element('font', caption, attributes)
124
+ end
125
+
126
+ #
127
+ # Write the <v:stroke> element.
128
+ #
129
+ def write_stroke
130
+ attributes = [%w[joinstyle miter]]
131
+
132
+ @writer.empty_tag('v:stroke', attributes)
133
+ end
134
+ end
135
+ end
136
+ end