xlsxrb 0.1.12 → 0.1.13
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/CHANGELOG.md +59 -42
- data/README.md +26 -22
- data/lib/xlsxrb/dsl_helpers.rb +59 -0
- data/lib/xlsxrb/elements/workbook.rb +11 -0
- data/lib/xlsxrb/ooxml/shared_strings_parser.rb +3 -5
- data/lib/xlsxrb/ooxml/workbook_writer.rb +5 -7
- data/lib/xlsxrb/ooxml/worksheet_parser.rb +172 -9
- data/lib/xlsxrb/ooxml/writer.rb +2 -1
- data/lib/xlsxrb/ooxml/xml_builder.rb +20 -0
- data/lib/xlsxrb/ooxml/zip_reader.rb +364 -78
- data/lib/xlsxrb/ooxml/zip_writer.rb +32 -5
- data/lib/xlsxrb/stream_sheet.rb +94 -6
- data/lib/xlsxrb/stream_writer.rb +33 -66
- data/lib/xlsxrb/version.rb +1 -1
- data/lib/xlsxrb/workbook_builder.rb +1 -1
- data/lib/xlsxrb/worksheet_builder.rb +3 -31
- data/lib/xlsxrb.rb +448 -171
- data/sig/generated/xlsxrb/dsl_helpers.rbs +32 -0
- data/sig/generated/xlsxrb/elements/workbook.rbs +7 -0
- data/sig/generated/xlsxrb/ooxml/shared_strings_parser.rbs +0 -2
- data/sig/generated/xlsxrb/ooxml/worksheet_parser.rbs +5 -4
- data/sig/generated/xlsxrb/ooxml/xml_builder.rbs +11 -0
- data/sig/generated/xlsxrb/ooxml/zip_reader.rbs +96 -8
- data/sig/generated/xlsxrb/ooxml/zip_writer.rbs +5 -1
- data/sig/generated/xlsxrb/stream_sheet.rbs +43 -3
- data/sig/generated/xlsxrb.rbs +18 -11
- metadata +6 -146
- data/.devcontainer/Dockerfile +0 -65
- data/.devcontainer/devcontainer.json +0 -17
- data/.gem_rbs_collection/ast/2.4/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/ast/2.4/ast.rbs +0 -73
- data/.gem_rbs_collection/concurrent-ruby/1.1/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/concurrent-ruby/1.1/array.rbs +0 -4
- data/.gem_rbs_collection/concurrent-ruby/1.1/atomic_reference.rbs +0 -16
- data/.gem_rbs_collection/concurrent-ruby/1.1/executor.rbs +0 -96
- data/.gem_rbs_collection/concurrent-ruby/1.1/hash.rbs +0 -4
- data/.gem_rbs_collection/concurrent-ruby/1.1/map.rbs +0 -68
- data/.gem_rbs_collection/concurrent-ruby/1.1/promises.rbs +0 -249
- data/.gem_rbs_collection/concurrent-ruby/1.1/set.rbs +0 -4
- data/.gem_rbs_collection/concurrent-ruby/1.1/timer_task.rbs +0 -47
- data/.gem_rbs_collection/concurrent-ruby/1.1/utility/processor_counter.rbs +0 -5
- data/.gem_rbs_collection/csv/3.3/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/csv/3.3/csv.rbs +0 -3871
- data/.gem_rbs_collection/csv/3.3/manifest.yaml +0 -3
- data/.gem_rbs_collection/lint_roller/1.1/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/lint_roller/1.1/lint_roller.rbs +0 -48
- data/.gem_rbs_collection/listen/3.9/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/listen/3.9/listen.rbs +0 -25
- data/.gem_rbs_collection/listen/3.9/listener.rbs +0 -24
- data/.gem_rbs_collection/logger/1.7/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/logger/1.7/formatter.rbs +0 -45
- data/.gem_rbs_collection/logger/1.7/log_device.rbs +0 -100
- data/.gem_rbs_collection/logger/1.7/logger.rbs +0 -796
- data/.gem_rbs_collection/logger/1.7/manifest.yaml +0 -2
- data/.gem_rbs_collection/logger/1.7/period.rbs +0 -17
- data/.gem_rbs_collection/logger/1.7/severity.rbs +0 -34
- data/.gem_rbs_collection/nokogiri/1.11/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/nokogiri/1.11/nokogiri.rbs +0 -2332
- data/.gem_rbs_collection/nokogiri/1.11/patch.rbs +0 -4
- data/.gem_rbs_collection/parallel/1.20/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/parallel/1.20/parallel.rbs +0 -86
- data/.gem_rbs_collection/parser/3.2/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/parser/3.2/manifest.yaml +0 -7
- data/.gem_rbs_collection/parser/3.2/parser.rbs +0 -194
- data/.gem_rbs_collection/parser/3.2/polyfill.rbs +0 -4
- data/.gem_rbs_collection/rainbow/3.0/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/rainbow/3.0/global.rbs +0 -7
- data/.gem_rbs_collection/rainbow/3.0/presenter.rbs +0 -209
- data/.gem_rbs_collection/rainbow/3.0/rainbow.rbs +0 -5
- data/.gem_rbs_collection/rake/13.0/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/rake/13.0/manifest.yaml +0 -2
- data/.gem_rbs_collection/rake/13.0/rake.rbs +0 -39
- data/.gem_rbs_collection/regexp_parser/2.8/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/regexp_parser/2.8/regexp_parser.rbs +0 -17
- data/.gem_rbs_collection/rubocop/1.57/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/rubocop/1.57/rubocop.rbs +0 -208
- data/.gem_rbs_collection/rubocop-ast/1.46/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/rubocop-ast/1.46/rubocop-ast.rbs +0 -903
- data/.gem_rbs_collection/rubyzip/3.2/.rbs_meta.yaml +0 -9
- data/.gem_rbs_collection/rubyzip/3.2/manifest.yaml +0 -8
- data/.gem_rbs_collection/rubyzip/3.2/zip/central_directory.rbs +0 -42
- data/.gem_rbs_collection/rubyzip/3.2/zip/compressor.rbs +0 -5
- data/.gem_rbs_collection/rubyzip/3.2/zip/constants.rbs +0 -47
- data/.gem_rbs_collection/rubyzip/3.2/zip/crypto/aes_encryption.rbs +0 -30
- data/.gem_rbs_collection/rubyzip/3.2/zip/crypto/decrypted_io.rbs +0 -9
- data/.gem_rbs_collection/rubyzip/3.2/zip/crypto/encryption.rbs +0 -7
- data/.gem_rbs_collection/rubyzip/3.2/zip/crypto/null_encryption.rbs +0 -19
- data/.gem_rbs_collection/rubyzip/3.2/zip/crypto/traditional_encryption.rbs +0 -31
- data/.gem_rbs_collection/rubyzip/3.2/zip/decompressor.rbs +0 -18
- data/.gem_rbs_collection/rubyzip/3.2/zip/deflater.rbs +0 -12
- data/.gem_rbs_collection/rubyzip/3.2/zip/dirtyable.rbs +0 -11
- data/.gem_rbs_collection/rubyzip/3.2/zip/dos_time.rbs +0 -13
- data/.gem_rbs_collection/rubyzip/3.2/zip/entry.rbs +0 -95
- data/.gem_rbs_collection/rubyzip/3.2/zip/entry_set.rbs +0 -31
- data/.gem_rbs_collection/rubyzip/3.2/zip/errors.rbs +0 -58
- data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/aes.rbs +0 -24
- data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/generic.rbs +0 -17
- data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/ntfs.rbs +0 -23
- data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/old_unix.rbs +0 -22
- data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/universal_time.rbs +0 -30
- data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/unix.rbs +0 -20
- data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/unknown.rbs +0 -15
- data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field/zip64.rbs +0 -26
- data/.gem_rbs_collection/rubyzip/3.2/zip/extra_field.rbs +0 -21
- data/.gem_rbs_collection/rubyzip/3.2/zip/file.rbs +0 -131
- data/.gem_rbs_collection/rubyzip/3.2/zip/file_split.rbs +0 -14
- data/.gem_rbs_collection/rubyzip/3.2/zip/filesystem/dir.rbs +0 -33
- data/.gem_rbs_collection/rubyzip/3.2/zip/filesystem/directory_iterator.rbs +0 -21
- data/.gem_rbs_collection/rubyzip/3.2/zip/filesystem/file.rbs +0 -63
- data/.gem_rbs_collection/rubyzip/3.2/zip/filesystem/file_stat.rbs +0 -55
- data/.gem_rbs_collection/rubyzip/3.2/zip/filesystem/zip_file_name_mapper.rbs +0 -35
- data/.gem_rbs_collection/rubyzip/3.2/zip/filesystem.rbs +0 -7
- data/.gem_rbs_collection/rubyzip/3.2/zip/inflater.rbs +0 -10
- data/.gem_rbs_collection/rubyzip/3.2/zip/input_stream.rbs +0 -22
- data/.gem_rbs_collection/rubyzip/3.2/zip/ioextras/abstract_input_stream.rbs +0 -29
- data/.gem_rbs_collection/rubyzip/3.2/zip/ioextras/abstract_output_stream.rbs +0 -17
- data/.gem_rbs_collection/rubyzip/3.2/zip/ioextras.rbs +0 -13
- data/.gem_rbs_collection/rubyzip/3.2/zip/null_compressor.rbs +0 -10
- data/.gem_rbs_collection/rubyzip/3.2/zip/null_decompressor.rbs +0 -8
- data/.gem_rbs_collection/rubyzip/3.2/zip/null_input_stream.rbs +0 -6
- data/.gem_rbs_collection/rubyzip/3.2/zip/output_stream.rbs +0 -30
- data/.gem_rbs_collection/rubyzip/3.2/zip/pass_thru_compressor.rbs +0 -10
- data/.gem_rbs_collection/rubyzip/3.2/zip/pass_thru_decompressor.rbs +0 -10
- data/.gem_rbs_collection/rubyzip/3.2/zip/streamable_directory.rbs +0 -5
- data/.gem_rbs_collection/rubyzip/3.2/zip/streamable_stream.rbs +0 -15
- data/.gem_rbs_collection/rubyzip/3.2/zip/version.rbs +0 -3
- data/.gem_rbs_collection/rubyzip/3.2/zip.rbs +0 -40
- data/.mutant.yml +0 -8
- data/Rakefile +0 -633
- data/Steepfile +0 -18
- data/benchmark.rb +0 -406
- data/docs/ARCHITECTURE.md +0 -514
- data/docs/DEVELOPMENT.md +0 -137
- data/docs/MUTATION_TESTING.md +0 -52
- data/docs/PEER_LIBRARIES.md +0 -121
- data/docs/QUALITY_ASSURANCE.md +0 -26
- data/docs/SPEC_SOURCES.md +0 -48
- data/docs/assets/benchmark_results.svg +0 -144
- data/docs/assets/lsp_autocompletion.png +0 -0
- data/docs/assets/playground_preview.png +0 -0
- data/docs/coi-serviceworker.js +0 -82
- data/docs/office_thread.js +0 -77
- data/docs/preview.html +0 -719
- data/docs/visual/VisualGallery.md +0 -4683
- data/docs/wasm/ruby.wasm +0 -0
- data/docs/wasm/wasm_doc_helper.css +0 -351
- data/docs/wasm/wasm_doc_helper.js +0 -439
- data/docs/zeta.js +0 -1107
- data/rbs_collection.lock.yaml +0 -252
- data/rbs_collection.yaml +0 -19
- data/vendor/sdk_runner/Program.cs +0 -93
- data/vendor/sdk_runner/sdk_runner.csproj +0 -13
data/lib/xlsxrb/stream_sheet.rb
CHANGED
|
@@ -36,15 +36,20 @@ module Xlsxrb
|
|
|
36
36
|
# Initializes a streaming worksheet context.
|
|
37
37
|
#
|
|
38
38
|
# @param name [String] The sheet name.
|
|
39
|
-
# @param
|
|
39
|
+
# @param sheet_source [String, Proc, IO, nil] Raw XML content or chunk supplier/stream.
|
|
40
40
|
# @param shared_strings [Array<String>] Shared strings table.
|
|
41
41
|
# @param styles [Hash, nil] Optional parsed styles hash.
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
# @param zip_reader [Ooxml::ZipReader, nil] Optional ZipReader context.
|
|
43
|
+
# @param entry_name [String, nil] Archive entry name for this sheet.
|
|
44
|
+
#: (String name, untyped sheet_source, Array[String] shared_strings, ?Hash[untyped, untyped]? styles, ?zip_reader: Ooxml::ZipReader?, ?entry_name: String?) -> void
|
|
45
|
+
def initialize(name, sheet_source, shared_strings, styles = nil, zip_reader: nil, entry_name: nil)
|
|
44
46
|
@name = name
|
|
45
|
-
@
|
|
47
|
+
@sheet_source = sheet_source
|
|
46
48
|
@shared_strings = shared_strings
|
|
47
49
|
@styles = styles
|
|
50
|
+
@zip_reader = zip_reader
|
|
51
|
+
@entry_name = entry_name
|
|
52
|
+
@sheet_xml = sheet_source if sheet_source.is_a?(String)
|
|
48
53
|
end
|
|
49
54
|
|
|
50
55
|
# Iterates over rows in this streaming worksheet with O(1) memory.
|
|
@@ -63,7 +68,13 @@ module Xlsxrb
|
|
|
63
68
|
def each_row(&)
|
|
64
69
|
return enum_for(:each_row) unless block_given?
|
|
65
70
|
|
|
66
|
-
|
|
71
|
+
source = if @sheet_source
|
|
72
|
+
@sheet_source
|
|
73
|
+
elsif @zip_reader && @entry_name
|
|
74
|
+
->(&blk) { @zip_reader.each_entry_chunk(@entry_name, &blk) }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
Ooxml::WorksheetParser.each_row(source, shared_strings: @shared_strings, &)
|
|
67
78
|
end
|
|
68
79
|
|
|
69
80
|
# Iterates over all cells across all rows continuously with O(1) memory.
|
|
@@ -112,8 +123,85 @@ module Xlsxrb
|
|
|
112
123
|
# @api public
|
|
113
124
|
#: () -> Elements::Worksheet
|
|
114
125
|
def load
|
|
115
|
-
Xlsxrb.send(:build_worksheet, @name,
|
|
126
|
+
Xlsxrb.send(:build_worksheet, @name, raw_sheet_xml, @shared_strings, @styles)
|
|
116
127
|
end
|
|
117
128
|
alias to_worksheet load
|
|
129
|
+
|
|
130
|
+
# Returns merged cell ranges (e.g. ["A1:B2"]) for this worksheet.
|
|
131
|
+
#
|
|
132
|
+
# @return [Array<String>]
|
|
133
|
+
# @api public
|
|
134
|
+
#: () -> Array[String]
|
|
135
|
+
def merged_cells
|
|
136
|
+
@merged_cells ||= begin
|
|
137
|
+
listener = Ooxml::Reader::MergeCellsListener.new
|
|
138
|
+
Ooxml::XmlParser.parse(raw_sheet_xml, listener)
|
|
139
|
+
listener.ranges
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Returns the auto-filter range (e.g. "A1:E100") for this worksheet, or nil if none.
|
|
144
|
+
#
|
|
145
|
+
# @return [String, nil]
|
|
146
|
+
# @api public
|
|
147
|
+
#: () -> String?
|
|
148
|
+
def auto_filter
|
|
149
|
+
@auto_filter ||= begin
|
|
150
|
+
listener = Ooxml::Reader::AutoFilterListener.new
|
|
151
|
+
Ooxml::XmlParser.parse(raw_sheet_xml, listener)
|
|
152
|
+
listener.ref
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Returns data validation rules configured for this worksheet.
|
|
157
|
+
#
|
|
158
|
+
# @return [Array<Hash[Symbol, untyped]>]
|
|
159
|
+
# @api public
|
|
160
|
+
#: () -> Array[Hash[Symbol, untyped]]
|
|
161
|
+
def data_validations
|
|
162
|
+
@data_validations ||= begin
|
|
163
|
+
listener = Ooxml::Reader::DataValidationsListener.new
|
|
164
|
+
Ooxml::XmlParser.parse(raw_sheet_xml, listener)
|
|
165
|
+
listener.validations
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Returns conditional formatting rules configured for this worksheet.
|
|
170
|
+
#
|
|
171
|
+
# @return [Array<Hash[Symbol, untyped]>]
|
|
172
|
+
# @api public
|
|
173
|
+
#: () -> Array[Hash[Symbol, untyped]]
|
|
174
|
+
def conditional_formats
|
|
175
|
+
@conditional_formats ||= begin
|
|
176
|
+
listener = Ooxml::Reader::ConditionalFormattingListener.new
|
|
177
|
+
Ooxml::XmlParser.parse(raw_sheet_xml, listener)
|
|
178
|
+
listener.rules
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Closes any underlying reader resources.
|
|
183
|
+
#: () -> void
|
|
184
|
+
def close
|
|
185
|
+
@zip_reader&.close
|
|
186
|
+
nil
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
private
|
|
190
|
+
|
|
191
|
+
# Returns the full raw XML string for this worksheet, loaded on demand.
|
|
192
|
+
#: () -> String
|
|
193
|
+
def raw_sheet_xml
|
|
194
|
+
@raw_sheet_xml ||= if @sheet_source.is_a?(String)
|
|
195
|
+
@sheet_source
|
|
196
|
+
elsif @zip_reader && @entry_name
|
|
197
|
+
@zip_reader.read_entry(@entry_name) || ""
|
|
198
|
+
elsif @sheet_source.respond_to?(:call)
|
|
199
|
+
buf = +""
|
|
200
|
+
@sheet_source.call { |c| buf << c }
|
|
201
|
+
buf
|
|
202
|
+
else
|
|
203
|
+
""
|
|
204
|
+
end
|
|
205
|
+
end
|
|
118
206
|
end
|
|
119
207
|
end
|
data/lib/xlsxrb/stream_writer.rb
CHANGED
|
@@ -911,39 +911,11 @@ module Xlsxrb
|
|
|
911
911
|
sheet if @current_sheet.nil?
|
|
912
912
|
|
|
913
913
|
row_index = @current_row_index
|
|
914
|
-
|
|
915
|
-
if @strict_excel_mode
|
|
916
|
-
raise ArgumentError, "Row index #{row_index} exceeds Excel limit of 1,048,576 rows" if row_index >= 1_048_576
|
|
917
|
-
raise ArgumentError, "Row height #{height} must be between 0 and 409 points (Excel limitation)" if height && (height.negative? || height > 409)
|
|
918
|
-
end
|
|
914
|
+
DslHelpers.validate_row_bounds!(row_index, height, strict_excel_mode: @strict_excel_mode)
|
|
919
915
|
@current_row_index += 1
|
|
920
916
|
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
cells_array = Array.new(max_col + 1)
|
|
924
|
-
values.each do |k, v|
|
|
925
|
-
idx = Elements::Cell.column_index(k)
|
|
926
|
-
cells_array[idx] = v
|
|
927
|
-
end
|
|
928
|
-
values = cells_array
|
|
929
|
-
end
|
|
930
|
-
|
|
931
|
-
if styles.is_a?(Hash)
|
|
932
|
-
expanded_styles = {}
|
|
933
|
-
styles.each do |k, v|
|
|
934
|
-
if k.is_a?(Range) || k.is_a?(Array)
|
|
935
|
-
k.each { |idx| expanded_styles[Elements::Cell.column_index(idx)] = v }
|
|
936
|
-
else
|
|
937
|
-
expanded_styles[Elements::Cell.column_index(k)] = v
|
|
938
|
-
end
|
|
939
|
-
end
|
|
940
|
-
max_col_style = expanded_styles.keys.max || -1
|
|
941
|
-
styles_array = Array.new(max_col_style + 1)
|
|
942
|
-
expanded_styles.each do |idx, v|
|
|
943
|
-
styles_array[idx] = v
|
|
944
|
-
end
|
|
945
|
-
styles = styles_array
|
|
946
|
-
end
|
|
917
|
+
values = DslHelpers.normalize_row_values(values)
|
|
918
|
+
styles = DslHelpers.normalize_row_styles(styles)
|
|
947
919
|
|
|
948
920
|
if @current_charts && !@current_charts.empty?
|
|
949
921
|
@current_cells ||= {}
|
|
@@ -1509,37 +1481,35 @@ module Xlsxrb
|
|
|
1509
1481
|
def close
|
|
1510
1482
|
raise ArgumentError, "Workbook must contain at least one sheet (Excel limitation)" if @strict_excel_mode && @sheets.empty? && @current_sheet.nil?
|
|
1511
1483
|
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
@io.close if @owns_io && !@io.closed?
|
|
1542
|
-
end
|
|
1484
|
+
flush_current_sheet
|
|
1485
|
+
|
|
1486
|
+
styles_definition = {
|
|
1487
|
+
fonts: @style_writer.fonts.dup,
|
|
1488
|
+
fills: @style_writer.fills.dup,
|
|
1489
|
+
borders: @style_writer.borders.dup,
|
|
1490
|
+
xf_entries: @style_writer.xf_entries.dup,
|
|
1491
|
+
num_fmts: @style_writer.num_fmts.dup,
|
|
1492
|
+
dxfs: @dxfs || []
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
resolved_names = resolve_defined_names(@defined_names, @sheets)
|
|
1496
|
+
|
|
1497
|
+
wb_writer = Ooxml::WorkbookWriter.new(
|
|
1498
|
+
sheets: @sheets,
|
|
1499
|
+
shared_strings: @sst,
|
|
1500
|
+
shared_strings_index: @sst_index,
|
|
1501
|
+
styles: styles_definition,
|
|
1502
|
+
defined_names: resolved_names.empty? ? nil : resolved_names,
|
|
1503
|
+
core_properties: @core_properties.empty? ? nil : @core_properties,
|
|
1504
|
+
app_properties: @app_properties.empty? ? nil : @app_properties,
|
|
1505
|
+
custom_properties: @custom_properties.empty? ? nil : @custom_properties,
|
|
1506
|
+
workbook_protection: @workbook_protection,
|
|
1507
|
+
workbook_properties: @workbook_properties
|
|
1508
|
+
)
|
|
1509
|
+
wb_writer.write_package_parts(@zip)
|
|
1510
|
+
|
|
1511
|
+
@zip.close
|
|
1512
|
+
@io.close if @owns_io && !@io.closed?
|
|
1543
1513
|
ensure
|
|
1544
1514
|
cleanup!
|
|
1545
1515
|
end
|
|
@@ -1570,10 +1540,7 @@ module Xlsxrb
|
|
|
1570
1540
|
|
|
1571
1541
|
#: (untyped range) -> untyped
|
|
1572
1542
|
def absolute_range(range)
|
|
1573
|
-
|
|
1574
|
-
# Edge case / untested delegation block
|
|
1575
|
-
range.gsub(/([A-Z]+)(\d+)/, '$\1$\2')
|
|
1576
|
-
# simplecov:enable
|
|
1543
|
+
DslHelpers.absolute_range(range)
|
|
1577
1544
|
end
|
|
1578
1545
|
|
|
1579
1546
|
#: (untyped names, untyped sheets) -> untyped
|
data/lib/xlsxrb/version.rb
CHANGED
|
@@ -87,38 +87,10 @@ module Xlsxrb
|
|
|
87
87
|
#: (Array[untyped] | Hash[untyped, untyped] values, ?styles: untyped, ?height: Float | Integer | nil, ?hidden: bool, ?custom_height: bool, ?outline_level: Integer | nil) -> void
|
|
88
88
|
def row(values, styles: nil, height: nil, hidden: false, custom_height: false, outline_level: nil)
|
|
89
89
|
row_index = @rows.size
|
|
90
|
-
|
|
91
|
-
if @strict_excel_mode
|
|
92
|
-
raise ArgumentError, "Row index #{row_index} exceeds Excel limit of 1,048,576 rows" if row_index >= 1_048_576
|
|
93
|
-
raise ArgumentError, "Row height #{height} must be between 0 and 409 points (Excel limitation)" if height && (height.negative? || height > 409)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
if values.is_a?(Hash)
|
|
97
|
-
max_col = values.keys.map { |k| Elements::Cell.column_index(k) }.max || -1
|
|
98
|
-
cells_array = Array.new(max_col + 1)
|
|
99
|
-
values.each do |k, v|
|
|
100
|
-
idx = Elements::Cell.column_index(k)
|
|
101
|
-
cells_array[idx] = v
|
|
102
|
-
end
|
|
103
|
-
values = cells_array
|
|
104
|
-
end
|
|
90
|
+
DslHelpers.validate_row_bounds!(row_index, height, strict_excel_mode: @strict_excel_mode)
|
|
105
91
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
styles.each do |k, v|
|
|
109
|
-
if k.is_a?(Range) || k.is_a?(Array)
|
|
110
|
-
k.each { |idx| expanded_styles[Elements::Cell.column_index(idx)] = v }
|
|
111
|
-
else
|
|
112
|
-
expanded_styles[Elements::Cell.column_index(k)] = v
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
max_col_style = expanded_styles.keys.max || -1
|
|
116
|
-
styles_array = Array.new(max_col_style + 1)
|
|
117
|
-
expanded_styles.each do |idx, v|
|
|
118
|
-
styles_array[idx] = v
|
|
119
|
-
end
|
|
120
|
-
styles = styles_array
|
|
121
|
-
end
|
|
92
|
+
values = DslHelpers.normalize_row_values(values)
|
|
93
|
+
styles = DslHelpers.normalize_row_styles(styles)
|
|
122
94
|
|
|
123
95
|
# Auto-detect Date / Time for built-in styles
|
|
124
96
|
values.each_with_index do |val, idx|
|