write_xlsx 1.10.1 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
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