write_xlsx 1.10.1 → 1.10.2
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 +4 -4
- data/.rubocop.yml +6 -0
- data/Changes +6 -0
- data/README.md +1 -1
- data/lib/write_xlsx/package/conditional_format.rb +15 -4
- data/lib/write_xlsx/package/table.rb +25 -16
- data/lib/write_xlsx/utility.rb +9 -8
- data/lib/write_xlsx/version.rb +1 -1
- data/lib/write_xlsx/worksheet/data_validation.rb +13 -1
- data/lib/write_xlsx/worksheet.rb +458 -218
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74c1fe583292a7a5318db09651b114e58358646a8706b5b4d35fc01c1850ec6c
|
4
|
+
data.tar.gz: 424d3f3a1983e4de16de9a943c67718874e7ef7e4a78c440767ecf8c68f0ef88
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4603c1400dd60ec345b8cf4db50ae1c03e87716192a074d2a767cebc7cfc085439c733ea11167cf900efc3aae3fe555a32639731d36338100bf9fbb170f28fd5
|
7
|
+
data.tar.gz: 3ccbb69460382ae8074cc62fc896daa1aa608dbbb6ff894bb1fc425643c0ac3b9e91cc55b0c8e2de05a50113b179621db83fcea033b9b201bf56957f833624e3
|
data/.rubocop.yml
CHANGED
@@ -38,6 +38,9 @@ Lint/DuplicateBranch:
|
|
38
38
|
Exclude:
|
39
39
|
- 'lib/write_xlsx/worksheet.rb'
|
40
40
|
|
41
|
+
Lint/UnderscorePrefixedVariableName:
|
42
|
+
Enabled: false
|
43
|
+
|
41
44
|
Lint/UselessSetterCall:
|
42
45
|
Exclude:
|
43
46
|
- 'lib/write_xlsx/worksheet.rb'
|
@@ -93,6 +96,9 @@ Style/HashSyntax:
|
|
93
96
|
EnforceStyle: ruby19_no_mixed_keys
|
94
97
|
EnforcedShorthandSyntax: either
|
95
98
|
|
99
|
+
Style/IfUnlessModifier:
|
100
|
+
Enabled: false
|
101
|
+
|
96
102
|
Style/NumericLiterals:
|
97
103
|
MinDigits: 10
|
98
104
|
|
data/Changes
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
Change history of write_xlsx rubygem.
|
2
2
|
|
3
|
+
2023-02-16 v1.10.2
|
4
|
+
Fixed issue #104. Worksheet#write Ruby 3.2 removed Object#=~
|
5
|
+
making it impossible to write Date objects
|
6
|
+
|
7
|
+
Memory usage optimization.
|
8
|
+
|
3
9
|
2023-01-31 v1.10.1
|
4
10
|
Fixed PR #99. Remove range [1..] style to work on Ruby 2.5.
|
5
11
|
|
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-
|
88
|
+
Copyright (c) 2012-2023 Hideo NAKAMURA.
|
89
89
|
|
90
90
|
See LICENSE.txt for further details.
|
91
91
|
|
@@ -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
|
-
|
414
|
-
|
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
|
@@ -162,41 +162,50 @@ module Writexlsx
|
|
162
162
|
|
163
163
|
private
|
164
164
|
|
165
|
-
def handle_args(
|
165
|
+
def handle_args(row1, col1 = nil, row2 = nil, col2 = nil, param = nil)
|
166
166
|
# Check for a cell reference in A1 notation and substitute row and column
|
167
|
-
|
167
|
+
if (row_col_array = row_col_notation(row1))
|
168
|
+
_row1, _col1, _row2, _col2 = row_col_array
|
169
|
+
_param = col1
|
170
|
+
else
|
171
|
+
_row1 = row1
|
172
|
+
_col1 = col1
|
173
|
+
_row2 = row2
|
174
|
+
_col2 = col2
|
175
|
+
_param = param
|
176
|
+
end
|
168
177
|
|
169
178
|
# Check for a valid number of args.
|
170
|
-
raise "Not enough parameters to add_table()" if [
|
179
|
+
raise "Not enough parameters to add_table()" if [_row1, _col1, _row2, _col2].include?(nil)
|
171
180
|
|
172
181
|
# Check that row and col are valid without storing the values.
|
173
|
-
check_dimensions_and_update_max_min_values(
|
174
|
-
check_dimensions_and_update_max_min_values(
|
182
|
+
check_dimensions_and_update_max_min_values(_row1, _col1, 1, 1)
|
183
|
+
check_dimensions_and_update_max_min_values(_row2, _col2, 1, 1)
|
175
184
|
|
176
185
|
# Swap last row/col for first row/col as necessary.
|
177
|
-
|
178
|
-
|
186
|
+
_row1, _row2 = _row2, _row1 if _row1 > _row2
|
187
|
+
_col1, _col2 = _col2, _col1 if _col1 > _col2
|
179
188
|
|
180
189
|
# The final hash contains the validation parameters.
|
181
|
-
|
190
|
+
_param ||= {}
|
182
191
|
|
183
192
|
# Turn on Excel's defaults.
|
184
|
-
|
185
|
-
|
186
|
-
|
193
|
+
_param[:banded_rows] ||= 1
|
194
|
+
_param[:header_row] ||= 1
|
195
|
+
_param[:autofilter] ||= 1
|
187
196
|
|
188
197
|
# Check that there are enough rows.
|
189
|
-
num_rows =
|
190
|
-
num_rows -= 1 if ptrue?(
|
198
|
+
num_rows = _row2 - _row1
|
199
|
+
num_rows -= 1 if ptrue?(_param[:header_row])
|
191
200
|
|
192
201
|
raise "Must have at least one data row in in add_table()" if num_rows < 0
|
193
202
|
|
194
203
|
# If the header row if off the default is to turn autofilter off.
|
195
|
-
|
204
|
+
_param[:autofilter] = 0 if _param[:header_row] == 0
|
196
205
|
|
197
|
-
check_parameter(
|
206
|
+
check_parameter(_param, valid_table_parameter, 'add_table')
|
198
207
|
|
199
|
-
[
|
208
|
+
[_row1, _row2, _col1, _col2, _param]
|
200
209
|
end
|
201
210
|
|
202
211
|
# List of valid input parameters.
|
data/lib/write_xlsx/utility.rb
CHANGED
@@ -53,7 +53,12 @@ module Writexlsx
|
|
53
53
|
|
54
54
|
def xl_col_to_name(col, col_absolute)
|
55
55
|
col_str = ColName.instance.col_str(col)
|
56
|
-
|
56
|
+
if col_absolute
|
57
|
+
"#{absolute_char(col_absolute)}#{col_str}"
|
58
|
+
else
|
59
|
+
# Do not allocate new string
|
60
|
+
col_str
|
61
|
+
end
|
57
62
|
end
|
58
63
|
|
59
64
|
def xl_range(row_1, row_2, col_1, col_2,
|
@@ -252,12 +257,8 @@ module Writexlsx
|
|
252
257
|
end
|
253
258
|
|
254
259
|
# Check for a cell reference in A1 notation and substitute row and column
|
255
|
-
def row_col_notation(
|
256
|
-
if
|
257
|
-
substitute_cellref(*args)
|
258
|
-
else
|
259
|
-
args
|
260
|
-
end
|
260
|
+
def row_col_notation(row_or_a1) # :nodoc:
|
261
|
+
substitute_cellref(row_or_a1) if row_or_a1.to_s =~ /^\D/
|
261
262
|
end
|
262
263
|
|
263
264
|
#
|
@@ -267,7 +268,7 @@ module Writexlsx
|
|
267
268
|
# Ex: ("A4", "Hello") is converted to (3, 0, "Hello").
|
268
269
|
#
|
269
270
|
def substitute_cellref(cell, *args) # :nodoc:
|
270
|
-
return [*args] if cell.respond_to?(:coerce) # Numeric
|
271
|
+
# return [*args] if cell.respond_to?(:coerce) # Numeric
|
271
272
|
|
272
273
|
normalized_cell = cell.upcase
|
273
274
|
|
data/lib/write_xlsx/version.rb
CHANGED
@@ -13,7 +13,19 @@ module Writexlsx
|
|
13
13
|
|
14
14
|
def initialize(*args)
|
15
15
|
# Check for a cell reference in A1 notation and substitute row and column.
|
16
|
-
|
16
|
+
if (row_col_array = row_col_notation(args.first))
|
17
|
+
case row_col_array.size
|
18
|
+
when 2
|
19
|
+
row1, col1 = row_col_array
|
20
|
+
row2, col2, options = args[1..-1]
|
21
|
+
when 4
|
22
|
+
row1, col1, row2, col2 = row_col_array
|
23
|
+
options = args[1]
|
24
|
+
end
|
25
|
+
else
|
26
|
+
row1, col1, row2, col2, options = args
|
27
|
+
end
|
28
|
+
|
17
29
|
if row2.respond_to?(:keys)
|
18
30
|
options_to_instance_variable(row2.dup)
|
19
31
|
row2 = row1
|
data/lib/write_xlsx/worksheet.rb
CHANGED
@@ -15,6 +15,7 @@ require 'write_xlsx/worksheet/data_validation'
|
|
15
15
|
require 'write_xlsx/worksheet/hyperlink'
|
16
16
|
require 'write_xlsx/worksheet/page_setup'
|
17
17
|
require 'tempfile'
|
18
|
+
require 'date'
|
18
19
|
|
19
20
|
module Writexlsx
|
20
21
|
class Worksheet
|
@@ -395,7 +396,12 @@ module Writexlsx
|
|
395
396
|
def set_selection(*args)
|
396
397
|
return if args.empty?
|
397
398
|
|
398
|
-
|
399
|
+
if (row_col_array = row_col_notation(args.first))
|
400
|
+
row_first, col_first, row_last, col_last = row_col_array
|
401
|
+
else
|
402
|
+
row_first, col_first, row_last, col_last = args
|
403
|
+
end
|
404
|
+
|
399
405
|
active_cell = xl_rowcol_to_cell(row_first, col_first)
|
400
406
|
|
401
407
|
if row_last # Range selection.
|
@@ -420,10 +426,15 @@ module Writexlsx
|
|
420
426
|
#
|
421
427
|
# Set the first visible cell at the top left of the worksheet.
|
422
428
|
#
|
423
|
-
def set_top_left_cell(
|
424
|
-
|
429
|
+
def set_top_left_cell(row, col = nil)
|
430
|
+
if (row_col_array = row_col_notation(row))
|
431
|
+
_row, _col = row_col_array
|
432
|
+
else
|
433
|
+
_row = row
|
434
|
+
_col = col
|
435
|
+
end
|
425
436
|
|
426
|
-
@top_left_cell = xl_rowcol_to_cell(
|
437
|
+
@top_left_cell = xl_rowcol_to_cell(_row, _col)
|
427
438
|
end
|
428
439
|
|
429
440
|
#
|
@@ -439,7 +450,12 @@ module Writexlsx
|
|
439
450
|
return if args.empty?
|
440
451
|
|
441
452
|
# Check for a cell reference in A1 notation and substitute row and column.
|
442
|
-
|
453
|
+
if (row_col_array = row_col_notation(args.first))
|
454
|
+
row, col, top_row, left_col = row_col_array
|
455
|
+
type = args[1]
|
456
|
+
else
|
457
|
+
row, col, top_row, left_col, type = args
|
458
|
+
end
|
443
459
|
|
444
460
|
col ||= 0
|
445
461
|
top_row ||= row
|
@@ -772,7 +788,12 @@ module Writexlsx
|
|
772
788
|
def print_area(*args)
|
773
789
|
return @page_setup.print_area.dup if args.empty?
|
774
790
|
|
775
|
-
|
791
|
+
if (row_col_array = row_col_notation(args.first))
|
792
|
+
row1, col1, row2, col2 = row_col_array
|
793
|
+
else
|
794
|
+
row1, col1, row2, col2 = args
|
795
|
+
end
|
796
|
+
|
776
797
|
return if [row1, col1, row2, col2].include?(nil)
|
777
798
|
|
778
799
|
# Ignore max print area since this is the same as no print area for Excel.
|
@@ -889,50 +910,62 @@ module Writexlsx
|
|
889
910
|
# data the {#write()}[#method-i-write] method acts as a general alias for several more
|
890
911
|
# specific methods:
|
891
912
|
#
|
892
|
-
def write(
|
913
|
+
def write(row, col, token = nil, format = nil, value1 = nil, value2 = nil)
|
893
914
|
# Check for a cell reference in A1 notation and substitute row and column
|
894
|
-
|
895
|
-
|
896
|
-
|
915
|
+
if (row_col_array = row_col_notation(row))
|
916
|
+
_row, _col = row_col_array
|
917
|
+
_token = col
|
918
|
+
_format = token
|
919
|
+
_value1 = format
|
920
|
+
_value2 = value1
|
921
|
+
else
|
922
|
+
_row = row
|
923
|
+
_col = col
|
924
|
+
_token = token
|
925
|
+
_format = format
|
926
|
+
_value1 = value1
|
927
|
+
_value2 = value2
|
928
|
+
end
|
929
|
+
_token ||= ''
|
930
|
+
_token = _token.to_s if token.instance_of?(Time) || token.instance_of?(Date)
|
897
931
|
|
898
|
-
|
899
|
-
|
900
|
-
write_string(*args) # Force text format
|
932
|
+
if _format.respond_to?(:force_text_format?) && _format.force_text_format?
|
933
|
+
write_string(_row, _col, _token, _format) # Force text format
|
901
934
|
# Match an array ref.
|
902
|
-
elsif
|
903
|
-
write_row(
|
904
|
-
elsif
|
905
|
-
write_number(
|
935
|
+
elsif _token.respond_to?(:to_ary)
|
936
|
+
write_row(_row, _col, _token, _format, _value1, _value2)
|
937
|
+
elsif _token.respond_to?(:coerce) # Numeric
|
938
|
+
write_number(_row, _col, _token, _format)
|
906
939
|
# Match integer with leading zero(s)
|
907
|
-
elsif @leading_zeros &&
|
908
|
-
write_string(
|
909
|
-
elsif
|
910
|
-
write_number(
|
940
|
+
elsif @leading_zeros && _token =~ /^0\d*$/
|
941
|
+
write_string(_row, _col, _token, _format)
|
942
|
+
elsif _token =~ /\A([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?\Z/
|
943
|
+
write_number(_row, _col, _token, _format)
|
911
944
|
# Match formula
|
912
|
-
elsif
|
913
|
-
write_formula(
|
945
|
+
elsif _token =~ /^=/
|
946
|
+
write_formula(_row, _col, _token, _format, _value1)
|
914
947
|
# Match array formula
|
915
|
-
elsif
|
916
|
-
write_formula(
|
948
|
+
elsif _token =~ /^\{=.*\}$/
|
949
|
+
write_formula(_row, _col, _token, _format, _value1)
|
917
950
|
# Match blank
|
918
|
-
elsif
|
919
|
-
row_col_args.delete_at(2) # remove the empty string from the parameter list
|
920
|
-
write_blank(
|
951
|
+
elsif _token == ''
|
952
|
+
# row_col_args.delete_at(2) # remove the empty string from the parameter list
|
953
|
+
write_blank(_row, _col, _format)
|
921
954
|
elsif @workbook.strings_to_urls
|
922
955
|
# Match http, https or ftp URL
|
923
|
-
if
|
924
|
-
write_url(
|
956
|
+
if _token =~ %r{\A[fh]tt?ps?://}
|
957
|
+
write_url(_row, _col, _token, _format, _value1, _value2)
|
925
958
|
# Match mailto:
|
926
|
-
elsif
|
927
|
-
write_url(
|
959
|
+
elsif _token =~ /\Amailto:/
|
960
|
+
write_url(_row, _col, _token, _format, _value1, _value2)
|
928
961
|
# Match internal or external sheet link
|
929
|
-
elsif
|
930
|
-
write_url(
|
962
|
+
elsif _token =~ /\A(?:in|ex)ternal:/
|
963
|
+
write_url(_row, _col, _token, _format, _value1, _value2)
|
931
964
|
else
|
932
|
-
write_string(
|
965
|
+
write_string(_row, _col, _token, _format)
|
933
966
|
end
|
934
967
|
else
|
935
|
-
write_string(
|
968
|
+
write_string(_row, _col, _token, _format)
|
936
969
|
end
|
937
970
|
end
|
938
971
|
|
@@ -944,19 +977,28 @@ module Writexlsx
|
|
944
977
|
# the elements of the array are in turn array. This allows the writing
|
945
978
|
# of 1D or 2D arrays of data in one go.
|
946
979
|
#
|
947
|
-
def write_row(*
|
980
|
+
def write_row(row, col, tokens = nil, *options)
|
948
981
|
# Check for a cell reference in A1 notation and substitute row and column
|
949
|
-
|
950
|
-
|
982
|
+
if (row_col_array = row_col_notation(row))
|
983
|
+
_row, _col = row_col_array
|
984
|
+
_tokens = col
|
985
|
+
_options = [tokens] + options
|
986
|
+
else
|
987
|
+
_row = row
|
988
|
+
_col = col
|
989
|
+
_tokens = tokens
|
990
|
+
_options = options
|
991
|
+
end
|
992
|
+
raise "Not an array ref in call to write_row()$!" unless _tokens.respond_to?(:to_ary)
|
951
993
|
|
952
|
-
|
994
|
+
_tokens.each do |_token|
|
953
995
|
# Check for nested arrays
|
954
|
-
if
|
955
|
-
write_col(
|
996
|
+
if _token.respond_to?(:to_ary)
|
997
|
+
write_col(_row, _col, _token, *_options)
|
956
998
|
else
|
957
|
-
write(
|
999
|
+
write(_row, _col, _token, *_options)
|
958
1000
|
end
|
959
|
-
|
1001
|
+
_col += 1
|
960
1002
|
end
|
961
1003
|
end
|
962
1004
|
|
@@ -968,13 +1010,22 @@ module Writexlsx
|
|
968
1010
|
# the elements of the array are in turn array. This allows the writing
|
969
1011
|
# of 1D or 2D arrays of data in one go.
|
970
1012
|
#
|
971
|
-
def write_col(*
|
972
|
-
|
1013
|
+
def write_col(row, col, tokens = nil, *options)
|
1014
|
+
if (row_col_array = row_col_notation(row))
|
1015
|
+
_row, _col = row_col_array
|
1016
|
+
_tokens = col
|
1017
|
+
_options = [tokens] + options if options
|
1018
|
+
else
|
1019
|
+
_row = row
|
1020
|
+
_col = col
|
1021
|
+
_tokens = tokens
|
1022
|
+
_options = options
|
1023
|
+
end
|
973
1024
|
|
974
|
-
|
1025
|
+
_tokens.each do |_token|
|
975
1026
|
# write() will deal with any nested arrays
|
976
|
-
write(
|
977
|
-
|
1027
|
+
write(_row, _col, _token, *_options)
|
1028
|
+
_row += 1
|
978
1029
|
end
|
979
1030
|
end
|
980
1031
|
|
@@ -984,19 +1035,28 @@ module Writexlsx
|
|
984
1035
|
#
|
985
1036
|
# Write a comment to the specified row and column (zero indexed).
|
986
1037
|
#
|
987
|
-
def write_comment(
|
1038
|
+
def write_comment(row, col, string = nil, options = nil)
|
988
1039
|
# Check for a cell reference in A1 notation and substitute row and column
|
989
|
-
|
990
|
-
|
1040
|
+
if (row_col_array = row_col_notation(row))
|
1041
|
+
_row, _col = row_col_array
|
1042
|
+
_string = col
|
1043
|
+
_options = string
|
1044
|
+
else
|
1045
|
+
_row = row
|
1046
|
+
_col = col
|
1047
|
+
_string = string
|
1048
|
+
_options = options
|
1049
|
+
end
|
1050
|
+
raise WriteXLSXInsufficientArgumentError if [_row, _col, _string].include?(nil)
|
991
1051
|
|
992
1052
|
# Check that row and col are valid and store max and min values
|
993
|
-
check_dimensions(
|
994
|
-
store_row_col_max_min_values(
|
1053
|
+
check_dimensions(_row, _col)
|
1054
|
+
store_row_col_max_min_values(_row, _col)
|
995
1055
|
|
996
1056
|
@has_vml = true
|
997
1057
|
|
998
1058
|
# Process the properties of the cell comment.
|
999
|
-
@comments.add(@workbook, self,
|
1059
|
+
@comments.add(@workbook, self, _row, _col, _string, _options)
|
1000
1060
|
end
|
1001
1061
|
|
1002
1062
|
#
|
@@ -1005,16 +1065,25 @@ module Writexlsx
|
|
1005
1065
|
#
|
1006
1066
|
# Write an integer or a float to the cell specified by row and column:
|
1007
1067
|
#
|
1008
|
-
def write_number(
|
1068
|
+
def write_number(row, col, number, format = nil)
|
1009
1069
|
# Check for a cell reference in A1 notation and substitute row and column
|
1010
|
-
|
1011
|
-
|
1070
|
+
if (row_col_array = row_col_notation(row))
|
1071
|
+
_row, _col = row_col_array
|
1072
|
+
_number = col
|
1073
|
+
_format = number
|
1074
|
+
else
|
1075
|
+
_row = row
|
1076
|
+
_col = col
|
1077
|
+
_number = number
|
1078
|
+
_format = format
|
1079
|
+
end
|
1080
|
+
raise WriteXLSXInsufficientArgumentError if _row.nil? || _col.nil? || _number.nil?
|
1012
1081
|
|
1013
1082
|
# Check that row and col are valid and store max and min values
|
1014
|
-
check_dimensions(
|
1015
|
-
store_row_col_max_min_values(
|
1083
|
+
check_dimensions(_row, _col)
|
1084
|
+
store_row_col_max_min_values(_row, _col)
|
1016
1085
|
|
1017
|
-
store_data_to_table(NumberCellData.new(
|
1086
|
+
store_data_to_table(NumberCellData.new(_number, _format), _row, _col)
|
1018
1087
|
end
|
1019
1088
|
|
1020
1089
|
#
|
@@ -1024,19 +1093,28 @@ module Writexlsx
|
|
1024
1093
|
# Write a string to the specified row and column (zero indexed).
|
1025
1094
|
# +format+ is optional.
|
1026
1095
|
#
|
1027
|
-
def write_string(
|
1096
|
+
def write_string(row, col, string = nil, format = nil)
|
1028
1097
|
# Check for a cell reference in A1 notation and substitute row and column
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1098
|
+
if (row_col_array = row_col_notation(row))
|
1099
|
+
_row, _col = row_col_array
|
1100
|
+
_string = col
|
1101
|
+
_format = string
|
1102
|
+
else
|
1103
|
+
_row = row
|
1104
|
+
_col = col
|
1105
|
+
_string = string
|
1106
|
+
_format = format
|
1107
|
+
end
|
1108
|
+
_string &&= _string.to_s
|
1109
|
+
raise WriteXLSXInsufficientArgumentError if _row.nil? || _col.nil? || _string.nil?
|
1032
1110
|
|
1033
1111
|
# Check that row and col are valid and store max and min values
|
1034
|
-
check_dimensions(
|
1035
|
-
store_row_col_max_min_values(
|
1112
|
+
check_dimensions(_row, _col)
|
1113
|
+
store_row_col_max_min_values(_row, _col)
|
1036
1114
|
|
1037
|
-
index = shared_string_index(
|
1115
|
+
index = shared_string_index(_string.length > STR_MAX ? _string[0, STR_MAX] : _string)
|
1038
1116
|
|
1039
|
-
store_data_to_table(StringCellData.new(index,
|
1117
|
+
store_data_to_table(StringCellData.new(index, _format), _row, _col)
|
1040
1118
|
end
|
1041
1119
|
|
1042
1120
|
#
|
@@ -1047,24 +1125,31 @@ module Writexlsx
|
|
1047
1125
|
# The method receives string fragments prefixed by format objects. The final
|
1048
1126
|
# format object is used as the cell format.
|
1049
1127
|
#
|
1050
|
-
def write_rich_string(*
|
1128
|
+
def write_rich_string(row, col, *rich_strings)
|
1051
1129
|
# Check for a cell reference in A1 notation and substitute row and column
|
1052
|
-
|
1053
|
-
|
1130
|
+
if (row_col_array = row_col_notation(row))
|
1131
|
+
_row, _col = row_col_array
|
1132
|
+
_rich_strings = [col] + rich_strings
|
1133
|
+
else
|
1134
|
+
_row = row
|
1135
|
+
_col = col
|
1136
|
+
_rich_strings = rich_strings
|
1137
|
+
end
|
1138
|
+
raise WriteXLSXInsufficientArgumentError if [_row, _col, _rich_strings[0]].include?(nil)
|
1054
1139
|
|
1055
|
-
|
1140
|
+
_xf = cell_format_of_rich_string(_rich_strings)
|
1056
1141
|
|
1057
1142
|
# Check that row and col are valid and store max and min values
|
1058
|
-
check_dimensions(
|
1059
|
-
store_row_col_max_min_values(
|
1143
|
+
check_dimensions(_row, _col)
|
1144
|
+
store_row_col_max_min_values(_row, _col)
|
1060
1145
|
|
1061
|
-
|
1146
|
+
_fragments, _length = rich_strings_fragments(_rich_strings)
|
1062
1147
|
# can't allow 2 formats in a row
|
1063
|
-
return -4 unless
|
1148
|
+
return -4 unless _fragments
|
1064
1149
|
|
1065
|
-
index = shared_string_index(xml_str_of_rich_string(
|
1150
|
+
index = shared_string_index(xml_str_of_rich_string(_fragments))
|
1066
1151
|
|
1067
|
-
store_data_to_table(StringCellData.new(index,
|
1152
|
+
store_data_to_table(StringCellData.new(index, _xf), _row, _col)
|
1068
1153
|
end
|
1069
1154
|
|
1070
1155
|
#
|
@@ -1075,19 +1160,26 @@ module Writexlsx
|
|
1075
1160
|
# A blank cell is used to specify formatting without adding a string
|
1076
1161
|
# or a number.
|
1077
1162
|
#
|
1078
|
-
def write_blank(
|
1163
|
+
def write_blank(row, col, format = nil)
|
1079
1164
|
# Check for a cell reference in A1 notation and substitute row and column
|
1080
|
-
|
1081
|
-
|
1165
|
+
if (row_col_array = row_col_notation(row))
|
1166
|
+
_row, _col = row_col_array
|
1167
|
+
_format = col
|
1168
|
+
else
|
1169
|
+
_row = row
|
1170
|
+
_col = col
|
1171
|
+
_format = format
|
1172
|
+
end
|
1173
|
+
raise WriteXLSXInsufficientArgumentError if [_row, _col].include?(nil)
|
1082
1174
|
|
1083
1175
|
# Don't write a blank cell unless it has a format
|
1084
|
-
return unless
|
1176
|
+
return unless _format
|
1085
1177
|
|
1086
1178
|
# Check that row and col are valid and store max and min values
|
1087
|
-
check_dimensions(
|
1088
|
-
store_row_col_max_min_values(
|
1179
|
+
check_dimensions(_row, _col)
|
1180
|
+
store_row_col_max_min_values(_row, _col)
|
1089
1181
|
|
1090
|
-
store_data_to_table(BlankCellData.new(
|
1182
|
+
store_data_to_table(BlankCellData.new(_format), _row, _col)
|
1091
1183
|
end
|
1092
1184
|
|
1093
1185
|
def expand_formula(formula, function, addition = '')
|
@@ -1261,28 +1353,39 @@ module Writexlsx
|
|
1261
1353
|
#
|
1262
1354
|
# Write a formula or function to the cell specified by +row+ and +column+:
|
1263
1355
|
#
|
1264
|
-
def write_formula(
|
1356
|
+
def write_formula(row, col, formula = nil, format = nil, value = nil)
|
1265
1357
|
# Check for a cell reference in A1 notation and substitute row and column
|
1266
|
-
|
1267
|
-
|
1358
|
+
if (row_col_array = row_col_notation(row))
|
1359
|
+
_row, _col = row_col_array
|
1360
|
+
_formula = col
|
1361
|
+
_format = formula
|
1362
|
+
_value = format
|
1363
|
+
else
|
1364
|
+
_row = row
|
1365
|
+
_col = col
|
1366
|
+
_formula = formula
|
1367
|
+
_format = format
|
1368
|
+
_value = value
|
1369
|
+
end
|
1370
|
+
raise WriteXLSXInsufficientArgumentError if [_row, _col, _formula].include?(nil)
|
1268
1371
|
|
1269
1372
|
# Check for dynamic array functions.
|
1270
1373
|
regex = /\bLET\(|\bSORT\(|\bLAMBDA\(|\bSINGLE\(|\bSORTBY\(|\bUNIQUE\(|\bXMATCH\(|\bFILTER\(|\bXLOOKUP\(|\bSEQUENCE\(|\bRANDARRAY\(|\bANCHORARRAY\(/
|
1271
|
-
if
|
1374
|
+
if _formula =~ regex
|
1272
1375
|
return write_dynamic_array_formula(
|
1273
|
-
|
1376
|
+
_row, _col, _row, _col, _formula, _format, _value
|
1274
1377
|
)
|
1275
1378
|
end
|
1276
1379
|
|
1277
1380
|
# Hand off array formulas.
|
1278
|
-
if
|
1279
|
-
write_array_formula(
|
1381
|
+
if _formula =~ /^\{=.*\}$/
|
1382
|
+
write_array_formula(_row, _col, _row, _col, _formula, _format, _value)
|
1280
1383
|
else
|
1281
|
-
check_dimensions(
|
1282
|
-
store_row_col_max_min_values(
|
1283
|
-
|
1384
|
+
check_dimensions(_row, _col)
|
1385
|
+
store_row_col_max_min_values(_row, _col)
|
1386
|
+
_formula = _formula.sub(/^=/, '')
|
1284
1387
|
|
1285
|
-
store_data_to_table(FormulaCellData.new(
|
1388
|
+
store_data_to_table(FormulaCellData.new(_formula, _format, _value), _row, _col)
|
1286
1389
|
end
|
1287
1390
|
end
|
1288
1391
|
|
@@ -1300,7 +1403,12 @@ module Writexlsx
|
|
1300
1403
|
params = args
|
1301
1404
|
end
|
1302
1405
|
|
1303
|
-
|
1406
|
+
if (row_col_array = row_col_notation(params.first))
|
1407
|
+
row1, col1, row2, col2 = row_col_array
|
1408
|
+
formula, xf, value = params[1..-1]
|
1409
|
+
else
|
1410
|
+
row1, col1, row2, col2, formula, xf, value = params
|
1411
|
+
end
|
1304
1412
|
raise WriteXLSXInsufficientArgumentError if [row1, col1, row2, col2, formula].include?(nil)
|
1305
1413
|
|
1306
1414
|
# Swap last row/col with first row/col as necessary
|
@@ -1349,8 +1457,8 @@ module Writexlsx
|
|
1349
1457
|
#
|
1350
1458
|
# Write an array formula to the specified row and column (zero indexed).
|
1351
1459
|
#
|
1352
|
-
def write_array_formula(
|
1353
|
-
write_array_formula_base('a',
|
1460
|
+
def write_array_formula(row1, col1, row2 = nil, col2 = nil, formula = nil, format = nil, value = nil)
|
1461
|
+
write_array_formula_base('a', row1, col1, row2, col2, formula, format, value)
|
1354
1462
|
end
|
1355
1463
|
|
1356
1464
|
#
|
@@ -1358,8 +1466,8 @@ module Writexlsx
|
|
1358
1466
|
#
|
1359
1467
|
# Write a dynamic formula to the specified row and column (zero indexed).
|
1360
1468
|
#
|
1361
|
-
def write_dynamic_array_formula(
|
1362
|
-
write_array_formula_base('d',
|
1469
|
+
def write_dynamic_array_formula(row1, col1, row2 = nil, col2 = nil, formula = nil, format = nil, value = nil)
|
1470
|
+
write_array_formula_base('d', row1, col1, row2, col2, formula, format, value)
|
1363
1471
|
@has_dynamic_arrays = true
|
1364
1472
|
end
|
1365
1473
|
|
@@ -1368,18 +1476,27 @@ module Writexlsx
|
|
1368
1476
|
#
|
1369
1477
|
# Write a boolean value to the specified row and column (zero indexed).
|
1370
1478
|
#
|
1371
|
-
def write_boolean(
|
1372
|
-
|
1373
|
-
|
1479
|
+
def write_boolean(row, col, val = nil, format = nil)
|
1480
|
+
if (row_col_array = row_col_notation(row))
|
1481
|
+
_row, _col = row_col_array
|
1482
|
+
_val = col
|
1483
|
+
_format = val
|
1484
|
+
else
|
1485
|
+
_row = row
|
1486
|
+
_col = col
|
1487
|
+
_val = val
|
1488
|
+
_format = format
|
1489
|
+
end
|
1490
|
+
raise WriteXLSXInsufficientArgumentError if _row.nil? || _col.nil?
|
1374
1491
|
|
1375
|
-
|
1492
|
+
_val = _val ? 1 : 0 # Boolean value.
|
1376
1493
|
# xf : cell format.
|
1377
1494
|
|
1378
1495
|
# Check that row and col are valid and store max and min values
|
1379
|
-
check_dimensions(
|
1380
|
-
store_row_col_max_min_values(
|
1496
|
+
check_dimensions(_row, _col)
|
1497
|
+
store_row_col_max_min_values(_row, _col)
|
1381
1498
|
|
1382
|
-
store_data_to_table(BooleanCellData.new(
|
1499
|
+
store_data_to_table(BooleanCellData.new(_val, _format), _row, _col)
|
1383
1500
|
end
|
1384
1501
|
|
1385
1502
|
#
|
@@ -1388,28 +1505,35 @@ module Writexlsx
|
|
1388
1505
|
#
|
1389
1506
|
# Update formatting of the cell to the specified row and column (zero indexed).
|
1390
1507
|
#
|
1391
|
-
def update_format_with_params(
|
1392
|
-
|
1393
|
-
|
1508
|
+
def update_format_with_params(row, col, params = nil)
|
1509
|
+
if (row_col_array = row_col_notation(row))
|
1510
|
+
_row, _col = row_col_array
|
1511
|
+
_params = args[1]
|
1512
|
+
else
|
1513
|
+
_row = row
|
1514
|
+
_col = col
|
1515
|
+
_params = params
|
1516
|
+
end
|
1517
|
+
raise WriteXLSXInsufficientArgumentError if _row.nil? || _col.nil? || _params.nil?
|
1394
1518
|
|
1395
1519
|
# Check that row and col are valid and store max and min values
|
1396
|
-
check_dimensions(
|
1397
|
-
store_row_col_max_min_values(
|
1520
|
+
check_dimensions(_row, _col)
|
1521
|
+
store_row_col_max_min_values(_row, _col)
|
1398
1522
|
|
1399
1523
|
format = nil
|
1400
1524
|
cell_data = nil
|
1401
|
-
if @cell_data_table[
|
1402
|
-
format = @workbook.add_format(
|
1403
|
-
write_blank(
|
1525
|
+
if @cell_data_table[_row].nil? || @cell_data_table[_row][_col].nil?
|
1526
|
+
format = @workbook.add_format(_params)
|
1527
|
+
write_blank(_row, _col, format)
|
1404
1528
|
else
|
1405
|
-
if @cell_data_table[
|
1406
|
-
format = @workbook.add_format(
|
1407
|
-
cell_data = @cell_data_table[
|
1529
|
+
if @cell_data_table[_row][_col].xf.nil?
|
1530
|
+
format = @workbook.add_format(_params)
|
1531
|
+
cell_data = @cell_data_table[_row][_col]
|
1408
1532
|
else
|
1409
1533
|
format = @workbook.add_format
|
1410
|
-
cell_data = @cell_data_table[
|
1534
|
+
cell_data = @cell_data_table[_row][_col]
|
1411
1535
|
format.copy(cell_data.xf)
|
1412
|
-
format.set_format_properties(
|
1536
|
+
format.set_format_properties(_params)
|
1413
1537
|
end
|
1414
1538
|
# keep original value of cell
|
1415
1539
|
value = if cell_data.is_a? FormulaCellData
|
@@ -1421,7 +1545,7 @@ module Writexlsx
|
|
1421
1545
|
else
|
1422
1546
|
cell_data.data
|
1423
1547
|
end
|
1424
|
-
write(
|
1548
|
+
write(_row, _col, value, format)
|
1425
1549
|
end
|
1426
1550
|
end
|
1427
1551
|
|
@@ -1431,22 +1555,31 @@ module Writexlsx
|
|
1431
1555
|
#
|
1432
1556
|
# Update formatting of cells in range to the specified row and column (zero indexed).
|
1433
1557
|
#
|
1434
|
-
def update_range_format_with_params(
|
1435
|
-
|
1558
|
+
def update_range_format_with_params(row_first, col_first, row_last = nil, col_last = nil, params = nil)
|
1559
|
+
if (row_col_array = row_col_notation(row_first))
|
1560
|
+
_row_first, _col_first, _row_last, _col_last = row_col_array
|
1561
|
+
params = args[1..-1]
|
1562
|
+
else
|
1563
|
+
_row_first = row_first
|
1564
|
+
_col_first = col_first
|
1565
|
+
_row_last = row_last
|
1566
|
+
_col_last = col_last
|
1567
|
+
_params = params
|
1568
|
+
end
|
1436
1569
|
|
1437
|
-
raise WriteXLSXInsufficientArgumentError if [
|
1570
|
+
raise WriteXLSXInsufficientArgumentError if [_row_first, _col_first, _row_last, _col_last, _params].include?(nil)
|
1438
1571
|
|
1439
1572
|
# Swap last row/col with first row/col as necessary
|
1440
|
-
|
1441
|
-
|
1573
|
+
_row_first, _row_last = _row_last, _row_first if _row_first > _row_last
|
1574
|
+
_col_first, _col_last = _col_last, _col_first if _col_first > _col_last
|
1442
1575
|
|
1443
1576
|
# Check that column number is valid and store the max value
|
1444
|
-
check_dimensions(
|
1445
|
-
store_row_col_max_min_values(
|
1577
|
+
check_dimensions(_row_last, _col_last)
|
1578
|
+
store_row_col_max_min_values(_row_last, _col_last)
|
1446
1579
|
|
1447
|
-
(
|
1448
|
-
(
|
1449
|
-
update_format_with_params(row, col,
|
1580
|
+
(_row_first.._row_last).each do |row|
|
1581
|
+
(_col_first.._col_last).each do |col|
|
1582
|
+
update_format_with_params(row, col, _params)
|
1450
1583
|
end
|
1451
1584
|
end
|
1452
1585
|
end
|
@@ -1483,26 +1616,39 @@ module Writexlsx
|
|
1483
1616
|
# The label is written using the {#write()}[#method-i-write] method. Therefore it is
|
1484
1617
|
# possible to write strings, numbers or formulas as labels.
|
1485
1618
|
#
|
1486
|
-
def write_url(
|
1619
|
+
def write_url(row, col, url = nil, format = nil, str = nil, tip = nil)
|
1487
1620
|
# Check for a cell reference in A1 notation and substitute row and column
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1621
|
+
if (row_col_array = row_col_notation(row))
|
1622
|
+
_row, _col = row_col_array
|
1623
|
+
_url = col
|
1624
|
+
_format = url
|
1625
|
+
_str = format
|
1626
|
+
_tip = str
|
1627
|
+
else
|
1628
|
+
_row = row
|
1629
|
+
_col = col
|
1630
|
+
_url = url
|
1631
|
+
_format = format
|
1632
|
+
_str = str
|
1633
|
+
_tip = tip
|
1634
|
+
end
|
1635
|
+
_format, _str = _str, _format if _str.respond_to?(:xf_index) || !_format.respond_to?(:xf_index)
|
1636
|
+
raise WriteXLSXInsufficientArgumentError if [_row, _col, _url].include?(nil)
|
1491
1637
|
|
1492
1638
|
# Check that row and col are valid and store max and min values
|
1493
|
-
check_dimensions(
|
1494
|
-
store_row_col_max_min_values(
|
1639
|
+
check_dimensions(_row, _col)
|
1640
|
+
store_row_col_max_min_values(_row, _col)
|
1495
1641
|
|
1496
|
-
hyperlink = Hyperlink.factory(
|
1497
|
-
store_hyperlink(
|
1642
|
+
hyperlink = Hyperlink.factory(_url, _str, _tip)
|
1643
|
+
store_hyperlink(_row, _col, hyperlink)
|
1498
1644
|
|
1499
1645
|
raise "URL '#{url}' added but URL exceeds Excel's limit of 65,530 URLs per worksheet." if hyperlinks_count > 65_530
|
1500
1646
|
|
1501
1647
|
# Add the default URL format.
|
1502
|
-
|
1648
|
+
_format ||= @default_url_format
|
1503
1649
|
|
1504
1650
|
# Write the hyperlink string.
|
1505
|
-
write_string(
|
1651
|
+
write_string(_row, _col, hyperlink.str, _format)
|
1506
1652
|
end
|
1507
1653
|
|
1508
1654
|
#
|
@@ -1512,22 +1658,31 @@ module Writexlsx
|
|
1512
1658
|
# Write a datetime string in ISO8601 "yyyy-mm-ddThh:mm:ss.ss" format as a
|
1513
1659
|
# number representing an Excel date. format is optional.
|
1514
1660
|
#
|
1515
|
-
def write_date_time(
|
1661
|
+
def write_date_time(row, col, str, format = nil)
|
1516
1662
|
# Check for a cell reference in A1 notation and substitute row and column
|
1517
|
-
|
1518
|
-
|
1663
|
+
if (row_col_array = row_col_notation(row))
|
1664
|
+
_row, _col = row_col_array
|
1665
|
+
_str = col
|
1666
|
+
_format = str
|
1667
|
+
else
|
1668
|
+
_row = row
|
1669
|
+
_col = col
|
1670
|
+
_str = str
|
1671
|
+
_format = format
|
1672
|
+
end
|
1673
|
+
raise WriteXLSXInsufficientArgumentError if [_row, _col, _str].include?(nil)
|
1519
1674
|
|
1520
1675
|
# Check that row and col are valid and store max and min values
|
1521
|
-
check_dimensions(
|
1522
|
-
store_row_col_max_min_values(
|
1676
|
+
check_dimensions(_row, _col)
|
1677
|
+
store_row_col_max_min_values(_row, _col)
|
1523
1678
|
|
1524
|
-
date_time = convert_date_time(
|
1679
|
+
date_time = convert_date_time(_str)
|
1525
1680
|
|
1526
1681
|
if date_time
|
1527
|
-
store_data_to_table(NumberCellData.new(date_time,
|
1682
|
+
store_data_to_table(NumberCellData.new(date_time, _format), _row, _col)
|
1528
1683
|
else
|
1529
1684
|
# If the date isn't valid then write it as a string.
|
1530
|
-
write_string(
|
1685
|
+
write_string(_row, _col, _str, _format)
|
1531
1686
|
end
|
1532
1687
|
end
|
1533
1688
|
|
@@ -1539,13 +1694,22 @@ module Writexlsx
|
|
1539
1694
|
# The Chart must be created by the add_chart() Workbook method and
|
1540
1695
|
# it must have the embedded option set.
|
1541
1696
|
#
|
1542
|
-
def insert_chart(*
|
1697
|
+
def insert_chart(row, col, chart = nil, *options)
|
1543
1698
|
# Check for a cell reference in A1 notation and substitute row and column.
|
1544
|
-
|
1545
|
-
|
1699
|
+
if (row_col_array = row_col_notation(row))
|
1700
|
+
_row, _col = row_col_array
|
1701
|
+
_chart = col
|
1702
|
+
_options = [chart] + options
|
1703
|
+
else
|
1704
|
+
_row = row
|
1705
|
+
_col = col
|
1706
|
+
_chart = chart
|
1707
|
+
_options = options
|
1708
|
+
end
|
1709
|
+
raise WriteXLSXInsufficientArgumentError if [_row, _col, _chart].include?(nil)
|
1546
1710
|
|
1547
|
-
if
|
1548
|
-
params =
|
1711
|
+
if _options.first.instance_of?(Hash)
|
1712
|
+
params = _options.first
|
1549
1713
|
x_offset = params[:x_offset]
|
1550
1714
|
y_offset = params[:y_offset]
|
1551
1715
|
x_scale = params[:x_scale]
|
@@ -1554,7 +1718,7 @@ module Writexlsx
|
|
1554
1718
|
description = params[:description]
|
1555
1719
|
decorative = params[:decorative]
|
1556
1720
|
else
|
1557
|
-
x_offset, y_offset, x_scale, y_scale, anchor =
|
1721
|
+
x_offset, y_offset, x_scale, y_scale, anchor = _options
|
1558
1722
|
end
|
1559
1723
|
x_offset ||= 0
|
1560
1724
|
y_offset ||= 0
|
@@ -1562,24 +1726,24 @@ module Writexlsx
|
|
1562
1726
|
y_scale ||= 1
|
1563
1727
|
anchor ||= 1
|
1564
1728
|
|
1565
|
-
raise "Not a Chart object in insert_chart()" unless
|
1566
|
-
raise "Not a embedded style Chart object in insert_chart()" if
|
1729
|
+
raise "Not a Chart object in insert_chart()" unless _chart.is_a?(Chart) || _chart.is_a?(Chartsheet)
|
1730
|
+
raise "Not a embedded style Chart object in insert_chart()" if _chart.respond_to?(:embedded) && _chart.embedded == 0
|
1567
1731
|
|
1568
|
-
if
|
1732
|
+
if _chart.already_inserted? || (_chart.combined && _chart.combined.already_inserted?)
|
1569
1733
|
raise "Chart cannot be inserted in a worksheet more than once"
|
1570
1734
|
else
|
1571
|
-
|
1572
|
-
|
1735
|
+
_chart.already_inserted = true
|
1736
|
+
_chart.combined.already_inserted = true if _chart.combined
|
1573
1737
|
end
|
1574
1738
|
|
1575
1739
|
# Use the values set with chart.set_size, if any.
|
1576
|
-
x_scale =
|
1577
|
-
y_scale =
|
1578
|
-
x_offset =
|
1579
|
-
y_offset =
|
1740
|
+
x_scale = _chart.x_scale if _chart.x_scale != 1
|
1741
|
+
y_scale = _chart.y_scale if _chart.y_scale != 1
|
1742
|
+
x_offset = _chart.x_offset if ptrue?(_chart.x_offset)
|
1743
|
+
y_offset = _chart.y_offset if ptrue?(_chart.y_offset)
|
1580
1744
|
|
1581
1745
|
@charts << [
|
1582
|
-
|
1746
|
+
_row, _col, _chart, x_offset, y_offset,
|
1583
1747
|
x_scale, y_scale, anchor, description, decorative
|
1584
1748
|
]
|
1585
1749
|
end
|
@@ -1588,14 +1752,23 @@ module Writexlsx
|
|
1588
1752
|
# :call-seq:
|
1589
1753
|
# insert_image(row, column, filename, options)
|
1590
1754
|
#
|
1591
|
-
def insert_image(*
|
1755
|
+
def insert_image(row, col, image = nil, *options)
|
1592
1756
|
# Check for a cell reference in A1 notation and substitute row and column.
|
1593
|
-
|
1594
|
-
|
1757
|
+
if (row_col_array = row_col_notation(row))
|
1758
|
+
_row, _col = row_col_array
|
1759
|
+
_image = col
|
1760
|
+
_options = [image] + options
|
1761
|
+
else
|
1762
|
+
_row = row
|
1763
|
+
_col = col
|
1764
|
+
_image = image
|
1765
|
+
_options = options
|
1766
|
+
end
|
1767
|
+
raise WriteXLSXInsufficientArgumentError if [_row, _col, _image].include?(nil)
|
1595
1768
|
|
1596
|
-
if
|
1769
|
+
if _options.first.instance_of?(Hash)
|
1597
1770
|
# Newer hash bashed options
|
1598
|
-
params =
|
1771
|
+
params = _options.first
|
1599
1772
|
x_offset = params[:x_offset]
|
1600
1773
|
y_offset = params[:y_offset]
|
1601
1774
|
x_scale = params[:x_scale]
|
@@ -1606,7 +1779,7 @@ module Writexlsx
|
|
1606
1779
|
description = params[:description]
|
1607
1780
|
decorative = params[:decorative]
|
1608
1781
|
else
|
1609
|
-
x_offset, y_offset, x_scale, y_scale, anchor =
|
1782
|
+
x_offset, y_offset, x_scale, y_scale, anchor = _options
|
1610
1783
|
end
|
1611
1784
|
x_offset ||= 0
|
1612
1785
|
y_offset ||= 0
|
@@ -1615,7 +1788,7 @@ module Writexlsx
|
|
1615
1788
|
anchor ||= 2
|
1616
1789
|
|
1617
1790
|
@images << [
|
1618
|
-
|
1791
|
+
_row, _col, _image, x_offset, y_offset,
|
1619
1792
|
x_scale, y_scale, url, tip, anchor, description, decorative
|
1620
1793
|
]
|
1621
1794
|
end
|
@@ -1627,32 +1800,43 @@ module Writexlsx
|
|
1627
1800
|
# Deprecated. This is a writeexcel gem's method that is no longer
|
1628
1801
|
# required by WriteXLSX.
|
1629
1802
|
#
|
1630
|
-
def repeat_formula(*
|
1803
|
+
def repeat_formula(row, col, formula, format, *pairs)
|
1631
1804
|
# Check for a cell reference in A1 notation and substitute row and column.
|
1632
|
-
|
1633
|
-
|
1805
|
+
if (row_col_array = row_col_notation(row))
|
1806
|
+
_row, _col = row_col_array
|
1807
|
+
_formula = col
|
1808
|
+
_format = formula
|
1809
|
+
_pairs = [format] + pairs
|
1810
|
+
else
|
1811
|
+
_row = row
|
1812
|
+
_col = col
|
1813
|
+
_formula = formula
|
1814
|
+
_format = format
|
1815
|
+
_pairs = pairs
|
1816
|
+
end
|
1817
|
+
raise WriteXLSXInsufficientArgumentError if [_row, _col].include?(nil)
|
1634
1818
|
|
1635
|
-
raise "Odd number of elements in pattern/replacement list" unless
|
1636
|
-
raise "Not a valid formula" unless
|
1819
|
+
raise "Odd number of elements in pattern/replacement list" unless _pairs.size.even?
|
1820
|
+
raise "Not a valid formula" unless _formula.respond_to?(:to_ary)
|
1637
1821
|
|
1638
|
-
tokens =
|
1822
|
+
tokens = _formula.join("\t").split("\t")
|
1639
1823
|
raise "No tokens in formula" if tokens.empty?
|
1640
1824
|
|
1641
|
-
|
1642
|
-
if
|
1643
|
-
|
1644
|
-
|
1825
|
+
_value = nil
|
1826
|
+
if _pairs[-2] == 'result'
|
1827
|
+
_value = _pairs.pop
|
1828
|
+
_pairs.pop
|
1645
1829
|
end
|
1646
|
-
until
|
1647
|
-
pattern =
|
1648
|
-
replace =
|
1830
|
+
until _pairs.empty?
|
1831
|
+
pattern = _pairs.shift
|
1832
|
+
replace = _pairs.shift
|
1649
1833
|
|
1650
1834
|
tokens.each do |token|
|
1651
1835
|
break if token.sub!(pattern, replace)
|
1652
1836
|
end
|
1653
1837
|
end
|
1654
|
-
|
1655
|
-
write_formula(
|
1838
|
+
_formula = tokens.join('')
|
1839
|
+
write_formula(_row, _col, _formula, _format, _value)
|
1656
1840
|
end
|
1657
1841
|
|
1658
1842
|
#
|
@@ -1741,7 +1925,13 @@ module Writexlsx
|
|
1741
1925
|
# others should be blank. All cells should contain the same format.
|
1742
1926
|
#
|
1743
1927
|
def merge_range(*args)
|
1744
|
-
|
1928
|
+
if (row_col_array = row_col_notation(args.first))
|
1929
|
+
row_first, col_first, row_last, col_last = row_col_array
|
1930
|
+
string, format, *extra_args = args[1..-1]
|
1931
|
+
else
|
1932
|
+
row_first, col_first, row_last, col_last,
|
1933
|
+
string, format, *extra_args = args
|
1934
|
+
end
|
1745
1935
|
|
1746
1936
|
raise "Incorrect number of arguments" if [row_first, col_first, row_last, col_last, format].include?(nil)
|
1747
1937
|
raise "Fifth parameter must be a format object" unless format.respond_to?(:xf_index)
|
@@ -1774,10 +1964,21 @@ module Writexlsx
|
|
1774
1964
|
def merge_range_type(type, *args)
|
1775
1965
|
case type
|
1776
1966
|
when 'array_formula', 'blank', 'rich_string'
|
1777
|
-
|
1967
|
+
if (row_col_array = row_col_notation(args.first))
|
1968
|
+
row_first, col_first, row_last, col_last = row_col_array
|
1969
|
+
*others = args[1..-1]
|
1970
|
+
else
|
1971
|
+
row_first, col_first, row_last, col_last, *others = args
|
1972
|
+
end
|
1778
1973
|
format = others.pop
|
1779
1974
|
else
|
1780
|
-
|
1975
|
+
if (row_col_array = row_col_notation(args.first))
|
1976
|
+
row_first, col_first, row_last, col_last = row_col_array
|
1977
|
+
token, format, *others = args[1..-1]
|
1978
|
+
else
|
1979
|
+
row_first, col_first, row_last, col_last,
|
1980
|
+
token, format, *others = args
|
1981
|
+
end
|
1781
1982
|
end
|
1782
1983
|
|
1783
1984
|
raise "Format object missing or in an incorrect position" unless format.respond_to?(:xf_index)
|
@@ -1870,8 +2071,16 @@ module Writexlsx
|
|
1870
2071
|
# The insert_button() method can be used to insert an Excel form button
|
1871
2072
|
# into a worksheet.
|
1872
2073
|
#
|
1873
|
-
def insert_button(
|
1874
|
-
|
2074
|
+
def insert_button(row, col, properties = nil)
|
2075
|
+
if (row_col_array = row_col_notation(row))
|
2076
|
+
_row, _col = row_col_array
|
2077
|
+
_properties = col
|
2078
|
+
else
|
2079
|
+
_row = row
|
2080
|
+
_col = col
|
2081
|
+
_properties = properties
|
2082
|
+
end
|
2083
|
+
@buttons_array << button_params(_row, _col, _properties)
|
1875
2084
|
@has_vml = 1
|
1876
2085
|
end
|
1877
2086
|
|
@@ -1937,17 +2146,24 @@ module Writexlsx
|
|
1937
2146
|
#
|
1938
2147
|
# Set the autofilter area in the worksheet.
|
1939
2148
|
#
|
1940
|
-
def autofilter(
|
1941
|
-
|
1942
|
-
|
2149
|
+
def autofilter(row1, col1 = nil, row2 = nil, col2 = nil)
|
2150
|
+
if (row_col_array = row_col_notation(row1))
|
2151
|
+
_row1, _col1, _row2, _col2 = row_col_array
|
2152
|
+
else
|
2153
|
+
_row1 = row1
|
2154
|
+
_col1 = col1
|
2155
|
+
_row2 = row2
|
2156
|
+
_col2 = col2
|
2157
|
+
end
|
2158
|
+
return if [_row1, _col1, _row2, _col2].include?(nil)
|
1943
2159
|
|
1944
2160
|
# Reverse max and min values if necessary.
|
1945
|
-
|
1946
|
-
|
2161
|
+
_row1, _row2 = _row2, _row1 if _row2 < _row1
|
2162
|
+
_col1, _col2 = _col2, _col1 if _col2 < _col1
|
1947
2163
|
|
1948
|
-
@autofilter_area = convert_name_area(
|
1949
|
-
@autofilter_ref = xl_range(
|
1950
|
-
@filter_range = [
|
2164
|
+
@autofilter_area = convert_name_area(_row1, _col1, _row2, _col2)
|
2165
|
+
@autofilter_ref = xl_range(_row1, _row2, _col1, _col2)
|
2166
|
+
@filter_range = [_col1, _col2]
|
1951
2167
|
end
|
1952
2168
|
|
1953
2169
|
#
|
@@ -2228,10 +2444,12 @@ module Writexlsx
|
|
2228
2444
|
# Write the cell value <v> element.
|
2229
2445
|
#
|
2230
2446
|
def write_cell_value(value = '') # :nodoc:
|
2231
|
-
return write_cell_formula('=NA()') if
|
2447
|
+
return write_cell_formula('=NA()') if value.is_a?(Float) && value.nan?
|
2232
2448
|
|
2233
2449
|
value ||= ''
|
2234
|
-
|
2450
|
+
|
2451
|
+
int_value = value.to_i
|
2452
|
+
value = int_value if value == int_value
|
2235
2453
|
@writer.data_element('v', value)
|
2236
2454
|
end
|
2237
2455
|
|
@@ -2902,19 +3120,38 @@ EOS
|
|
2902
3120
|
#
|
2903
3121
|
# Insert a shape into the worksheet.
|
2904
3122
|
#
|
2905
|
-
def insert_shape(
|
3123
|
+
def insert_shape(
|
3124
|
+
row_start, column_start, shape = nil, x_offset = nil, y_offset = nil,
|
3125
|
+
x_scale = nil, y_scale = nil, anchor = nil
|
3126
|
+
)
|
2906
3127
|
# Check for a cell reference in A1 notation and substitute row and column.
|
2907
|
-
|
2908
|
-
|
2909
|
-
|
3128
|
+
if (row_col_array = row_col_notation(row_start))
|
3129
|
+
_row_start, _column_start = row_col_array
|
3130
|
+
_shape = column_start
|
3131
|
+
_x_offset = shape
|
3132
|
+
_y_offset = x_offset
|
3133
|
+
_x_scale = y_offset
|
3134
|
+
_y_scale = x_scale
|
3135
|
+
_anchor = y_scale
|
3136
|
+
else
|
3137
|
+
_row_start = row_start
|
3138
|
+
_column_start = column_start
|
3139
|
+
_shape = shape
|
3140
|
+
_x_offset = x_offset
|
3141
|
+
_y_offset = y_offset
|
3142
|
+
_x_scale = x_scale
|
3143
|
+
_y_scale = y_scale
|
3144
|
+
_anchor = anchor
|
3145
|
+
end
|
3146
|
+
raise "Insufficient arguments in insert_shape()" if [_row_start, _column_start, _shape].include?(nil)
|
2910
3147
|
|
2911
|
-
|
2912
|
-
|
2913
|
-
|
3148
|
+
_shape.set_position(
|
3149
|
+
_row_start, _column_start, _x_offset, _y_offset,
|
3150
|
+
_x_scale, _y_scale, _anchor
|
2914
3151
|
)
|
2915
3152
|
# Assign a shape ID.
|
2916
3153
|
while true
|
2917
|
-
id =
|
3154
|
+
id = _shape.id || 0
|
2918
3155
|
used = @shape_hash[id]
|
2919
3156
|
|
2920
3157
|
# Test if shape ID is already used. Otherwise assign a new one.
|
@@ -2922,20 +3159,20 @@ EOS
|
|
2922
3159
|
break
|
2923
3160
|
else
|
2924
3161
|
@last_shape_id += 1
|
2925
|
-
|
3162
|
+
_shape.id = @last_shape_id
|
2926
3163
|
end
|
2927
3164
|
end
|
2928
3165
|
|
2929
3166
|
# Allow lookup of entry into shape array by shape ID.
|
2930
|
-
@shape_hash[
|
3167
|
+
@shape_hash[_shape.id] = _shape.element = @shapes.size
|
2931
3168
|
|
2932
|
-
insert = if ptrue?(
|
3169
|
+
insert = if ptrue?(_shape.stencil)
|
2933
3170
|
# Insert a copy of the shape, not a reference so that the shape is
|
2934
3171
|
# used as a stencil. Previously stamped copies don't get modified
|
2935
3172
|
# if the stencil is modified.
|
2936
|
-
|
3173
|
+
_shape.dup
|
2937
3174
|
else
|
2938
|
-
|
3175
|
+
_shape
|
2939
3176
|
end
|
2940
3177
|
|
2941
3178
|
# For connectors change x/y coords based on location of connected shapes.
|
@@ -3333,8 +3570,11 @@ EOS
|
|
3333
3570
|
end
|
3334
3571
|
|
3335
3572
|
def write_cell_column_dimension(row_num) # :nodoc:
|
3573
|
+
row = @cell_data_table[row_num]
|
3336
3574
|
(@dim_colmin..@dim_colmax).each do |col_num|
|
3337
|
-
|
3575
|
+
if (cell = row[col_num])
|
3576
|
+
cell.write_cell(self, row_num, col_num)
|
3577
|
+
end
|
3338
3578
|
end
|
3339
3579
|
end
|
3340
3580
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: write_xlsx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.10.
|
4
|
+
version: 1.10.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hideo NAKAMURA
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyzip
|
@@ -275,7 +275,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
275
275
|
- !ruby/object:Gem::Version
|
276
276
|
version: '0'
|
277
277
|
requirements: []
|
278
|
-
rubygems_version: 3.4.
|
278
|
+
rubygems_version: 3.4.5
|
279
279
|
signing_key:
|
280
280
|
specification_version: 4
|
281
281
|
summary: write_xlsx is a gem to create a new file in the Excel 2007+ XLSX format.
|