write_xlsx 1.10.1 → 1.11.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 66e9354b51872770af7121d5581615b53c0cb3b7e86c221b0ecee60fe54dae4b
4
- data.tar.gz: 97d6ae9ed6dee9e57e98981e105da155ef405fd5ea40ea17e8057871f02d90d9
3
+ metadata.gz: 14a7593970ecc4db14f2accbdc1634033ac9042cdd7680a20d4400ea1eda741f
4
+ data.tar.gz: 2ec671ba25dc571f612dc5b9d4a9c4ede2e147203d2e085313ea8b4a5f774377
5
5
  SHA512:
6
- metadata.gz: a86f539563acd7da100be9fb11e1e3da99c1985200e21eaa91ca9db3f69ea130038f0ecead40ea0ba6efcc5b4f433dcd4acf039006faa65adb60ed88d0d5f005
7
- data.tar.gz: f98a3ac1110600e8e2c578127f85a804c1237d44069481f6c0baacc27ff6f21eddbb96f063c544239730ba059a16f7637f39ebfd902f3cc87be4995401bf303b
6
+ metadata.gz: 255b8f5d60623d6c9966ba1209773129d3312238df315a16564d8c950fa39ac738296a9c788d4cb707abad7e659e9eaef528749fa7f1de7f93a2152e0534fbb4
7
+ data.tar.gz: c161bd9e8cfe47754f763a874ab83b183f76d7d290ecc53db1fa7a1ea1ec4433ee1d80efda0c139417321f02069db690fc113ab54104b5922b9c942210949e60
data/.rubocop.yml CHANGED
@@ -8,6 +8,9 @@ AllCops:
8
8
  TargetRubyVersion: 2.6
9
9
  NewCops: enable
10
10
 
11
+ Gemspec/DevelopmentDependencies:
12
+ Enabled: false
13
+
11
14
  Gemspec/RequiredRubyVersion:
12
15
  Enabled: false
13
16
 
@@ -33,11 +36,17 @@ Layout/HeredocIndentation:
33
36
  Layout/LineLength:
34
37
  Max: 7000
35
38
 
39
+ Layout/MultilineMethodCallIndentation:
40
+ Enabled: false
41
+
36
42
  Lint/DuplicateBranch:
37
43
  IgnoreLiteralBranches: true
38
44
  Exclude:
39
45
  - 'lib/write_xlsx/worksheet.rb'
40
46
 
47
+ Lint/UnderscorePrefixedVariableName:
48
+ Enabled: false
49
+
41
50
  Lint/UselessSetterCall:
42
51
  Exclude:
43
52
  - 'lib/write_xlsx/worksheet.rb'
@@ -57,6 +66,9 @@ Metrics/CyclomaticComplexity:
57
66
  Metrics/MethodLength:
58
67
  Max: 400
59
68
 
69
+ Metrics/ModuleLength:
70
+ Max: 1000
71
+
60
72
  Metrics/ParameterLists:
61
73
  Max: 12
62
74
  MaxOptionalParameters: 6
@@ -93,6 +105,9 @@ Style/HashSyntax:
93
105
  EnforceStyle: ruby19_no_mixed_keys
94
106
  EnforcedShorthandSyntax: either
95
107
 
108
+ Style/IfUnlessModifier:
109
+ Enabled: false
110
+
96
111
  Style/NumericLiterals:
97
112
  MinDigits: 10
98
113
 
data/Changes CHANGED
@@ -1,5 +1,26 @@
1
1
  Change history of write_xlsx rubygem.
2
2
 
3
+ 2023-05-06 v1.11.0
4
+ Added support for simulated worksheet `autofit()`.
5
+
6
+ Refactored internal column property handling to allow column ranges
7
+ to be overridden (a common UX expectation).
8
+
9
+ Add `quote_prefix` format property.
10
+
11
+ Fix for duplicate number formats. Issue #283(excel-write-xlsx)
12
+
13
+ Add fix for worksheets with tables and background images.
14
+
15
+ Replace/fix the worksheet protection password algorithm
16
+ so that is works correctly for strings over 24 chars.
17
+
18
+ 2023-02-16 v1.10.2
19
+ Fixed issue #104. Worksheet#write Ruby 3.2 removed Object#=~
20
+ making it impossible to write Date objects
21
+
22
+ Memory usage optimization.
23
+
3
24
  2023-01-31 v1.10.1
4
25
  Fixed PR #99. Remove range [1..] style to work on Ruby 2.5.
5
26
 
data/README.md CHANGED
@@ -85,7 +85,7 @@ the first worksheet in an Excel XML spreadsheet called ruby.xlsx:
85
85
  Original Perl module was written by John McNamara(jmcnamara@cpan.org).
86
86
 
87
87
  Converted to ruby by Hideo NAKAMURA(nakamrua.hideo@gmail.com)
88
- Copyright (c) 2012-2022 Hideo NAKAMURA.
88
+ Copyright (c) 2012-2023 Hideo NAKAMURA.
89
89
 
90
90
  See LICENSE.txt for further details.
91
91
 
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #
5
+ # An example of using simulated autofit to automatically adjust the width of
6
+ # worksheet columns based on the data in the cells.
7
+ #
8
+ # Copyright 2000-2023, John McNamara, jmcnamara@cpan.org
9
+ #
10
+ # SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later
11
+ #
12
+ # convert to Ruby by Hideo NAKAMURA, nakamura.hideo@gmail.com
13
+ #
14
+ require 'write_xlsx'
15
+
16
+ workbook = WriteXLSX.new('autofit.xlsx')
17
+ worksheet = workbook.add_worksheet
18
+
19
+ # Write some worksheet data to demonstrate autofitting.
20
+ worksheet.write(0, 0, "Foo")
21
+ worksheet.write(1, 0, "Food")
22
+ worksheet.write(2, 0, "Foody")
23
+ worksheet.write(3, 0, "Froody")
24
+
25
+ worksheet.write(0, 1, 12345)
26
+ worksheet.write(1, 1, 12345678)
27
+ worksheet.write(2, 1, 12345)
28
+
29
+ worksheet.write(0, 2, "Some longer text")
30
+
31
+ worksheet.write(0, 3, 'http://www.google.com')
32
+ worksheet.write(1, 3, 'https://github.com')
33
+
34
+ # Autofit the worksheet
35
+ worksheet.autofit
36
+
37
+ workbook.close
@@ -44,10 +44,8 @@ chart1.add_series(
44
44
  values: ['Sheet1', 1, 6, 2, 2]
45
45
  )
46
46
 
47
- # Add a chart title and some axis labels.
47
+ # Add a chart title.
48
48
  chart1.set_title(name: 'Results of sample analysis')
49
- chart1.set_x_axis(name: 'Test number')
50
- chart1.set_y_axis(name: 'Sample length (mm)')
51
49
 
52
50
  # Set an Excel chart style. Blue colors with white outline and shadow.
53
51
  chart1.set_style(11)
@@ -81,10 +79,8 @@ chart2.add_series(
81
79
  values: ['Sheet1', 1, 6, 2, 2]
82
80
  )
83
81
 
84
- # Add a chart title and some axis labels.
82
+ # Add a chart title.
85
83
  chart2.set_title(name: 'Stacked Chart')
86
- chart2.set_x_axis(name: 'Test number')
87
- chart2.set_y_axis(name: 'Sample length (mm)')
88
84
 
89
85
  # Set an Excel chart style. Blue colors with white outline and shadow.
90
86
  chart2.set_style(12)
@@ -118,10 +114,8 @@ chart3.add_series(
118
114
  values: ['Sheet1', 1, 6, 2, 2]
119
115
  )
120
116
 
121
- # Add a chart title and some axis labels.
117
+ # Add a chart title.
122
118
  chart3.set_title(name: 'Percent Stacked Chart')
123
- chart3.set_x_axis(name: 'Test number')
124
- chart3.set_y_axis(name: 'Sample length (mm)')
125
119
 
126
120
  # Set an Excel chart style. Blue colors with white outline and shadow.
127
121
  chart3.set_style(13)
@@ -371,7 +371,7 @@ module Writexlsx
371
371
  # Set on of the 42 built-in Excel chart styles. The default style is 2.
372
372
  #
373
373
  def set_style(style_id = 2)
374
- style_id = 2 if style_id < 0 || style_id > 48
374
+ style_id = 2 if style_id < 1 || style_id > 48
375
375
  @style_id = style_id
376
376
  end
377
377
 
@@ -12,7 +12,7 @@ module Writexlsx
12
12
  attr_reader :diag_type, :diag_color, :font_only, :color_indexed # :nodoc:
13
13
  attr_reader :left, :left_color, :right, :right_color, :top, :top_color, :bottom, :bottom_color # :nodoc:
14
14
  attr_reader :font_scheme # :nodoc:
15
- attr_accessor :num_format_index, :border_index, :font_index # :nodoc:
15
+ attr_accessor :quote_prefix, :num_format_index, :border_index, :font_index # :nodoc:
16
16
  attr_accessor :fill_index, :font_condense, :font_extend, :diag_border # :nodoc:
17
17
  attr_accessor :bg_color, :fg_color, :pattern # :nodoc:
18
18
 
@@ -84,6 +84,7 @@ module Writexlsx
84
84
  @just_distrib = 0
85
85
  @color_indexed = 0
86
86
  @font_only = 0
87
+ @quote_prefix = 0
87
88
 
88
89
  set_format_properties(params) unless params.empty?
89
90
  end
@@ -213,7 +214,7 @@ module Writexlsx
213
214
  # Returns a unique hash key for the Format object.
214
215
  #
215
216
  def get_format_key
216
- [get_font_key, get_border_key, get_fill_key, get_alignment_key, @num_format, @locked, @hidden].join(':')
217
+ [get_font_key, get_border_key, get_fill_key, get_alignment_key, @num_format, @locked, @hidden, @quote_prefix].join(':')
217
218
  end
218
219
 
219
220
  #
@@ -642,6 +643,7 @@ module Writexlsx
642
643
  ['borderId', border_index],
643
644
  ['xfId', xf_id]
644
645
  ]
646
+ attributes << ['quotePrefix', 1] if ptrue?(quote_prefix)
645
647
  attributes << ['applyNumberFormat', 1] if num_format_index > 0
646
648
  # Add applyFont attribute if XF format uses a font element.
647
649
  attributes << ['applyFont', 1] if font_index > 0 && !ptrue?(@hyperlink)
@@ -409,12 +409,23 @@ module Writexlsx
409
409
 
410
410
  def row_col_param_for_conditional_formatting(*args)
411
411
  # Check for a cell reference in A1 notation and substitute row and column
412
- if args[0].to_s =~ (/^\D/) && (args[0] =~ /,/)
413
- # Check for a user defined multiple range like B3:K6,B8:K11.
414
- user_range = args[0].sub(/^=/, '').gsub(/\s*,\s*/, ' ').gsub(/\$/, '')
412
+ user_range = if args[0].to_s =~ (/^\D/) && (args[0] =~ /,/)
413
+ # Check for a user defined multiple range like B3:K6,B8:K11.
414
+ args[0].sub(/^=/, '').gsub(/\s*,\s*/, ' ').gsub(/\$/, '')
415
+ end
416
+
417
+ if (row_col_array = row_col_notation(args.first))
418
+ if row_col_array.size == 2
419
+ row1, col1 = row_col_array
420
+ row2 = args[1]
421
+ elsif row_col_array.size == 4
422
+ row1, col1, row2, col2 = row_col_array
423
+ param = args[1]
424
+ end
425
+ else
426
+ row1, col1, row2, col2, param = args
415
427
  end
416
428
 
417
- row1, col1, row2, col2, param = row_col_notation(args)
418
429
  if row2.respond_to?(:keys)
419
430
  param = row2
420
431
  row2 = row1
@@ -11,11 +11,14 @@ module Writexlsx
11
11
 
12
12
  PRESERVE_SPACE_ATTRIBUTES = ['xml:space', 'preserve'].freeze
13
13
 
14
+ attr_reader :strings
15
+
14
16
  def initialize
15
17
  @writer = Package::XMLWriterSimple.new
16
18
  @strings = [] # string table
17
19
  @strings_index = {} # string table index
18
20
  @count = 0 # count
21
+ @str_unique = 0
19
22
  end
20
23
 
21
24
  def index(string, params = {})
@@ -25,10 +28,9 @@ module Writexlsx
25
28
 
26
29
  def add(string)
27
30
  unless @strings_index[string]
28
- # Only first time the string will be append to list
29
- # next time we only check and not #dup it
30
31
  str = string.frozen? ? string : string.freeze
31
32
  @strings << str
33
+ @str_unique += 1
32
34
  @strings_index[str] = @strings.size - 1
33
35
  end
34
36
  @count += 1
@@ -128,7 +130,7 @@ module Writexlsx
128
130
  end
129
131
 
130
132
  def unique_count
131
- @strings.size
133
+ @str_unique
132
134
  end
133
135
  end
134
136
  end
@@ -14,7 +14,7 @@ module Writexlsx
14
14
  @xf_formats = nil
15
15
  @palette = []
16
16
  @font_count = 0
17
- @num_format_count = 0
17
+ @num_formats = []
18
18
  @border_count = 0
19
19
  @fill_count = 0
20
20
  @custom_colors = []
@@ -38,18 +38,18 @@ module Writexlsx
38
38
  # Pass in the Format objects and other properties used to set the styles.
39
39
  #
40
40
  def set_style_properties(
41
- xf_formats, palette, font_count, num_format_count, border_count,
41
+ xf_formats, palette, font_count, num_formats, border_count,
42
42
  fill_count, custom_colors, dxf_formats, has_comments
43
43
  )
44
- @xf_formats = xf_formats
45
- @palette = palette
46
- @font_count = font_count
47
- @num_format_count = num_format_count
48
- @border_count = border_count
49
- @fill_count = fill_count
50
- @custom_colors = custom_colors
51
- @dxf_formats = dxf_formats
52
- @has_comments = has_comments
44
+ @xf_formats = xf_formats
45
+ @palette = palette
46
+ @font_count = font_count
47
+ @num_formats = num_formats
48
+ @border_count = border_count
49
+ @fill_count = fill_count
50
+ @custom_colors = custom_colors
51
+ @dxf_formats = dxf_formats
52
+ @has_comments = has_comments
53
53
  end
54
54
 
55
55
  #
@@ -77,7 +77,7 @@ module Writexlsx
77
77
  # Write the <numFmts> element.
78
78
  #
79
79
  def write_num_fmts
80
- count = @num_format_count
80
+ count = @num_formats.size
81
81
 
82
82
  return if count == 0
83
83
 
@@ -85,11 +85,10 @@ module Writexlsx
85
85
 
86
86
  @writer.tag_elements('numFmts', attributes) do
87
87
  # Write the numFmts elements.
88
- @xf_formats.each do |format|
89
- # Ignore built-in number formats, i.e., < 164.
90
- next unless format.num_format_index >= 164
91
-
92
- write_num_fmt(format.num_format_index, format.num_format)
88
+ index = 164
89
+ @num_formats.each do |num_format|
90
+ write_num_fmt(index, num_format)
91
+ index += 1
93
92
  end
94
93
  end
95
94
  end
@@ -51,6 +51,7 @@ module Writexlsx
51
51
 
52
52
  add_the_table_columns
53
53
  write_the_cell_data_if_supplied
54
+ store_filter_cell_positions
54
55
  end
55
56
 
56
57
  def set_xml_writer(filename)
@@ -155,6 +156,14 @@ module Writexlsx
155
156
  end
156
157
  end
157
158
 
159
+ def store_filter_cell_positions
160
+ if ptrue?(@param[:autofilter])
161
+ (@col1..@col2).each do |col|
162
+ @worksheet.filter_cells["#{@row1}:#{col}"] = 1
163
+ end
164
+ end
165
+ end
166
+
158
167
  def prepare(id)
159
168
  @id = id
160
169
  @name ||= "Table#{id}"
@@ -162,41 +171,50 @@ module Writexlsx
162
171
 
163
172
  private
164
173
 
165
- def handle_args(*args)
174
+ def handle_args(row1, col1 = nil, row2 = nil, col2 = nil, param = nil)
166
175
  # Check for a cell reference in A1 notation and substitute row and column
167
- row1, col1, row2, col2, param = row_col_notation(args)
176
+ if (row_col_array = row_col_notation(row1))
177
+ _row1, _col1, _row2, _col2 = row_col_array
178
+ _param = col1
179
+ else
180
+ _row1 = row1
181
+ _col1 = col1
182
+ _row2 = row2
183
+ _col2 = col2
184
+ _param = param
185
+ end
168
186
 
169
187
  # Check for a valid number of args.
170
- raise "Not enough parameters to add_table()" if [row1, col1, row2, col2].include?(nil)
188
+ raise "Not enough parameters to add_table()" if [_row1, _col1, _row2, _col2].include?(nil)
171
189
 
172
190
  # Check that row and col are valid without storing the values.
173
- check_dimensions_and_update_max_min_values(row1, col1, 1, 1)
174
- check_dimensions_and_update_max_min_values(row2, col2, 1, 1)
191
+ check_dimensions_and_update_max_min_values(_row1, _col1, 1, 1)
192
+ check_dimensions_and_update_max_min_values(_row2, _col2, 1, 1)
175
193
 
176
194
  # Swap last row/col for first row/col as necessary.
177
- row1, row2 = row2, row1 if row1 > row2
178
- col1, col2 = col2, col1 if col1 > col2
195
+ _row1, _row2 = _row2, _row1 if _row1 > _row2
196
+ _col1, _col2 = _col2, _col1 if _col1 > _col2
179
197
 
180
198
  # The final hash contains the validation parameters.
181
- param ||= {}
199
+ _param ||= {}
182
200
 
183
201
  # Turn on Excel's defaults.
184
- param[:banded_rows] ||= 1
185
- param[:header_row] ||= 1
186
- param[:autofilter] ||= 1
202
+ _param[:banded_rows] ||= 1
203
+ _param[:header_row] ||= 1
204
+ _param[:autofilter] ||= 1
187
205
 
188
206
  # Check that there are enough rows.
189
- num_rows = row2 - row1
190
- num_rows -= 1 if ptrue?(param[:header_row])
207
+ num_rows = _row2 - _row1
208
+ num_rows -= 1 if ptrue?(_param[:header_row])
191
209
 
192
210
  raise "Must have at least one data row in in add_table()" if num_rows < 0
193
211
 
194
212
  # If the header row if off the default is to turn autofilter off.
195
- param[:autofilter] = 0 if param[:header_row] == 0
213
+ _param[:autofilter] = 0 if _param[:header_row] == 0
196
214
 
197
- check_parameter(param, valid_table_parameter, 'add_table')
215
+ check_parameter(_param, valid_table_parameter, 'add_table')
198
216
 
199
- [row1, row2, col1, col2, param]
217
+ [_row1, _row2, _col1, _col2, _param]
200
218
  end
201
219
 
202
220
  # List of valid input parameters.
@@ -5,10 +5,28 @@ require 'write_xlsx/col_name'
5
5
 
6
6
  module Writexlsx
7
7
  module Utility
8
- ROW_MAX = 1048576 # :nodoc:
9
- COL_MAX = 16384 # :nodoc:
10
- STR_MAX = 32767 # :nodoc:
8
+ ROW_MAX = 1048576 # :nodoc:
9
+ COL_MAX = 16384 # :nodoc:
10
+ STR_MAX = 32767 # :nodoc:
11
11
  SHEETNAME_MAX = 31 # :nodoc:
12
+ CHAR_WIDTHS = {
13
+ ' ' => 3, '!' => 5, '"' => 6, '#' => 7, '$' => 7, '%' => 11,
14
+ '&' => 10, "'" => 3, '(' => 5, ')' => 5, '*' => 7, '+' => 7,
15
+ ',' => 4, '-' => 5, '.' => 4, '/' => 6, '0' => 7, '1' => 7,
16
+ '2' => 7, '3' => 7, '4' => 7, '5' => 7, '6' => 7, '7' => 7,
17
+ '8' => 7, '9' => 7, ':' => 4, ';' => 4, '<' => 7, '=' => 7,
18
+ '>' => 7, '?' => 7, '@' => 13, 'A' => 9, 'B' => 8, 'C' => 8,
19
+ 'D' => 9, 'E' => 7, 'F' => 7, 'G' => 9, 'H' => 9, 'I' => 4,
20
+ 'J' => 5, 'K' => 8, 'L' => 6, 'M' => 12, 'N' => 10, 'O' => 10,
21
+ 'P' => 8, 'Q' => 10, 'R' => 8, 'S' => 7, 'T' => 7, 'U' => 9,
22
+ 'V' => 9, 'W' => 13, 'X' => 8, 'Y' => 7, 'Z' => 7, '[' => 5,
23
+ '\\' => 6, ']' => 5, '^' => 7, '_' => 7, '`' => 4, 'a' => 7,
24
+ 'b' => 8, 'c' => 6, 'd' => 8, 'e' => 8, 'f' => 5, 'g' => 7,
25
+ 'h' => 8, 'i' => 4, 'j' => 4, 'k' => 7, 'l' => 4, 'm' => 12,
26
+ 'n' => 8, 'o' => 8, 'p' => 8, 'q' => 8, 'r' => 5, 's' => 6,
27
+ 't' => 5, 'u' => 8, 'v' => 7, 'w' => 11, 'x' => 7, 'y' => 7,
28
+ 'z' => 6, '{' => 5, '|' => 7, '}' => 5, '~' => 7
29
+ }.freeze
12
30
 
13
31
  #
14
32
  # xl_rowcol_to_cell($row, col, row_absolute, col_absolute)
@@ -53,7 +71,12 @@ module Writexlsx
53
71
 
54
72
  def xl_col_to_name(col, col_absolute)
55
73
  col_str = ColName.instance.col_str(col)
56
- "#{absolute_char(col_absolute)}#{col_str}"
74
+ if col_absolute
75
+ "#{absolute_char(col_absolute)}#{col_str}"
76
+ else
77
+ # Do not allocate new string
78
+ col_str
79
+ end
57
80
  end
58
81
 
59
82
  def xl_range(row_1, row_2, col_1, col_2,
@@ -79,6 +102,21 @@ module Writexlsx
79
102
  "=#{sheetname}!#{range1}:#{range2}"
80
103
  end
81
104
 
105
+ #
106
+ # xl_string_pixel_width($string)
107
+ #
108
+ # Get the pixel width of a string based on individual character widths taken
109
+ # from Excel. UTF8 characters are given a default width of 8.
110
+ #
111
+ # Note, Excel adds an additional 7 pixels padding to a cell.
112
+ #
113
+ def xl_string_pixel_width(string)
114
+ length = 0
115
+ string.to_s.split(//).each { |char| length += CHAR_WIDTHS[char] || 8 }
116
+
117
+ length
118
+ end
119
+
82
120
  #
83
121
  # Sheetnames used in references should be quoted if they contain any spaces,
84
122
  # special characters or if the look like something that isn't a sheet name.
@@ -252,12 +290,8 @@ module Writexlsx
252
290
  end
253
291
 
254
292
  # Check for a cell reference in A1 notation and substitute row and column
255
- def row_col_notation(args) # :nodoc:
256
- if args[0].to_s =~ /^\D/
257
- substitute_cellref(*args)
258
- else
259
- args
260
- end
293
+ def row_col_notation(row_or_a1) # :nodoc:
294
+ substitute_cellref(row_or_a1) if row_or_a1.respond_to?(:match) && row_or_a1.to_s =~ /^\D/
261
295
  end
262
296
 
263
297
  #
@@ -267,7 +301,7 @@ module Writexlsx
267
301
  # Ex: ("A4", "Hello") is converted to (3, 0, "Hello").
268
302
  #
269
303
  def substitute_cellref(cell, *args) # :nodoc:
270
- return [*args] if cell.respond_to?(:coerce) # Numeric
304
+ # return [*args] if cell.respond_to?(:coerce) # Numeric
271
305
 
272
306
  normalized_cell = cell.upcase
273
307
 
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- WriteXLSX_VERSION = "1.10.1"
3
+ WriteXLSX_VERSION = "1.11.0"
@@ -58,7 +58,7 @@ module Writexlsx
58
58
  @xf_formats = []
59
59
  @dxf_formats = []
60
60
  @font_count = 0
61
- @num_format_count = 0
61
+ @num_formats = []
62
62
  @defined_names = []
63
63
  @named_ranges = []
64
64
  @custom_colors = []
@@ -560,7 +560,7 @@ module Writexlsx
560
560
  @xf_formats,
561
561
  @palette,
562
562
  @font_count,
563
- @num_format_count,
563
+ @num_formats,
564
564
  @border_count,
565
565
  @fill_count,
566
566
  @custom_colors,
@@ -869,6 +869,9 @@ module Writexlsx
869
869
  @activesheet = @worksheets.visible_first.index if @activesheet == 0
870
870
  @worksheets[@activesheet].activate
871
871
 
872
+ # Convert the SST strings data structure.
873
+ prepare_sst_string_data
874
+
872
875
  # Prepare the worksheet VML elements such as comments and buttons.
873
876
  prepare_vml_objects
874
877
  # Set the defined names for the worksheets such as Print Titles.
@@ -917,6 +920,11 @@ module Writexlsx
917
920
  Dir.glob(File.join(tempdir, "**", "*"), File::FNM_DOTMATCH).select { |f| File.file?(f) }
918
921
  end
919
922
 
923
+ #
924
+ # prepare_sst_string_data
925
+ #
926
+ def prepare_sst_string_data; end
927
+
920
928
  #
921
929
  # Prepare all of the format properties prior to passing them to Styles.rb.
922
930
  #
@@ -977,9 +985,10 @@ module Writexlsx
977
985
  # User defined records start from index 0xA4.
978
986
  #
979
987
  def prepare_num_formats # :nodoc:
980
- num_formats = {}
981
- index = 164
982
- num_format_count = 0
988
+ num_formats = []
989
+ unique_num_formats = {}
990
+ index = 164
991
+ num_format_count = 0
983
992
 
984
993
  (@xf_formats + @dxf_formats).each do |format|
985
994
  num_format = format.num_format
@@ -1000,21 +1009,22 @@ module Writexlsx
1000
1009
  next
1001
1010
  end
1002
1011
 
1003
- if num_formats[num_format]
1012
+ if unique_num_formats[num_format]
1004
1013
  # Number format has already been used.
1005
- format.num_format_index = num_formats[num_format]
1014
+ format.num_format_index = unique_num_formats[num_format]
1006
1015
  else
1007
1016
  # Add a new number format.
1008
- num_formats[num_format] = index
1017
+ unique_num_formats[num_format] = index
1009
1018
  format.num_format_index = index
1010
1019
  index += 1
1011
1020
 
1012
- # Only increase font count for XF formats (not for DXF formats).
1013
- num_format_count += 1 if ptrue?(format.xf_index)
1021
+ # Only store/increase number format count for XF formats
1022
+ # (not for DXF formats).
1023
+ num_formats << num_format if ptrue?(format.xf_index)
1014
1024
  end
1015
1025
  end
1016
1026
 
1017
- @num_format_count = num_format_count
1027
+ @num_formats = num_formats
1018
1028
  end
1019
1029
 
1020
1030
  #
@@ -1,5 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # frozen_string_literal: true
2
+
3
+ # frozen__literal: true
3
4
 
4
5
  module Writexlsx
5
6
  class Worksheet
@@ -24,8 +25,8 @@ module Writexlsx
24
25
  elsif worksheet.set_rows[row] && worksheet.set_rows[row][1]
25
26
  row_xf = worksheet.set_rows[row][1]
26
27
  attributes << ['s', row_xf.get_xf_index]
27
- elsif worksheet.col_formats[col]
28
- col_xf = worksheet.col_formats[col]
28
+ elsif worksheet.col_info[col] && worksheet.col_info[col].format
29
+ col_xf = worksheet.col_info[col].format
29
30
  attributes << ['s', col_xf.get_xf_index]
30
31
  end
31
32
  attributes
@@ -56,11 +57,12 @@ module Writexlsx
56
57
  end
57
58
 
58
59
  class StringCellData < CellData # :nodoc:
59
- attr_reader :token
60
+ attr_reader :token, :raw_string
60
61
 
61
- def initialize(index, xf)
62
+ def initialize(index, xf, raw_string)
62
63
  @token = index
63
64
  @xf = xf
65
+ @raw_string = raw_string
64
66
  end
65
67
 
66
68
  def data
@@ -81,6 +83,12 @@ module Writexlsx
81
83
  end
82
84
  end
83
85
 
86
+ class RichStringCellData < StringCellData # :nodoc:
87
+ end
88
+
89
+ class DateTimeCellData < NumberCellData # :nodoc:
90
+ end
91
+
84
92
  class FormulaCellData < CellData # :nodoc:
85
93
  attr_reader :token, :result, :range, :link_type, :url
86
94