xlsxrb 0.1.7 → 0.1.8
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 +11 -0
- data/README.md +87 -35
- data/Rakefile +16 -5
- data/benchmark.rb +32 -4
- data/docs/ARCHITECTURE.md +32 -30
- data/docs/visual/VisualGallery.md +157 -157
- data/docs/wasm/ruby.wasm +0 -0
- data/lib/ruby_lsp/xlsxrb/addon.rb +1 -1
- data/lib/ruby_lsp/xlsxrb/completion_listener.rb +11 -13
- data/lib/xlsxrb/elements/coordinate_access.rb +101 -0
- data/lib/xlsxrb/elements/workbook.rb +19 -1
- data/lib/xlsxrb/elements/worksheet.rb +92 -122
- data/lib/xlsxrb/elements.rb +1 -0
- data/lib/xlsxrb/ooxml/worksheet_parser.rb +21 -15
- data/lib/xlsxrb/stream_row.rb +181 -0
- data/lib/xlsxrb/version.rb +1 -1
- data/lib/xlsxrb.rb +164 -106
- data/sig/generated/xlsxrb/elements/coordinate_access.rbs +70 -0
- data/sig/generated/xlsxrb/elements/worksheet.rbs +116 -14
- data/sig/generated/xlsxrb/ooxml/worksheet_parser.rbs +2 -0
- data/sig/generated/xlsxrb/stream_row.rbs +125 -0
- data/sig/generated/xlsxrb.rbs +110 -68
- metadata +5 -1
|
@@ -2,33 +2,135 @@
|
|
|
2
2
|
|
|
3
3
|
module Xlsxrb
|
|
4
4
|
module Elements
|
|
5
|
-
# Represents a single worksheet in a workbook.
|
|
5
|
+
# Represents a single fully parsed, in-memory worksheet in a workbook.
|
|
6
|
+
# Provides coordinate random access (sheet["A1"]), row lookups (row_at),
|
|
7
|
+
# and immutable cell updates (update_cell).
|
|
6
8
|
#
|
|
7
9
|
# @example Access cells and rows
|
|
8
|
-
# sheet = workbook.sheet(0)
|
|
10
|
+
# sheet = workbook.sheet(0).load
|
|
9
11
|
# cell = sheet["A1"]
|
|
10
|
-
#
|
|
12
|
+
# row = sheet.row_at(0)
|
|
11
13
|
#
|
|
12
14
|
# @api public
|
|
13
|
-
class Worksheet
|
|
14
|
-
attr_reader name
|
|
15
|
+
class Worksheet
|
|
16
|
+
attr_reader name: untyped
|
|
15
17
|
|
|
16
|
-
attr_reader rows
|
|
18
|
+
attr_reader rows: untyped
|
|
17
19
|
|
|
18
|
-
attr_reader columns
|
|
20
|
+
attr_reader columns: untyped
|
|
19
21
|
|
|
20
|
-
attr_reader charts
|
|
22
|
+
attr_reader charts: untyped
|
|
21
23
|
|
|
22
|
-
attr_reader unmapped_data
|
|
24
|
+
attr_reader unmapped_data: untyped
|
|
23
25
|
|
|
24
|
-
attr_reader errors
|
|
26
|
+
attr_reader errors: untyped
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
# @param name [String] The worksheet name (max 31 characters).
|
|
29
|
+
# @param rows [Array<Elements::Row>] Rows in the sheet.
|
|
30
|
+
# @param columns [Array<Elements::Column>] Column definitions.
|
|
31
|
+
# @param charts [Array<Hash>] Charts in the sheet.
|
|
32
|
+
# @param unmapped_data [Hash] Additional metadata for round-tripping.
|
|
33
|
+
# @param errors [Array<String>, nil] Validation errors.
|
|
34
|
+
# : (name: String, ?rows: Array[Elements::Row], ?columns: Array[Elements::Column], ?charts: Array[Hash[Symbol, untyped]], ?unmapped_data: Hash[untyped, untyped], ?errors: Array[String]?) -> void
|
|
35
|
+
def initialize: (name: String, ?rows: Array[Elements::Row], ?columns: Array[Elements::Column], ?charts: Array[Hash[Symbol, untyped]], ?unmapped_data: Hash[untyped, untyped], ?errors: Array[String]?) -> void
|
|
28
36
|
|
|
29
|
-
|
|
37
|
+
# Iterate over rows in the worksheet.
|
|
38
|
+
#
|
|
39
|
+
# @example
|
|
40
|
+
# sheet.each do |row|
|
|
41
|
+
# puts row.to_a.inspect
|
|
42
|
+
# end
|
|
43
|
+
#
|
|
44
|
+
# @yield [row]
|
|
45
|
+
# @yieldparam row [Elements::Row]
|
|
46
|
+
# @return [Enumerator, void]
|
|
47
|
+
# @api public
|
|
48
|
+
# : () { (Elements::Row) -> void } -> void
|
|
49
|
+
# : | () -> Enumerator[Elements::Row, void]
|
|
50
|
+
def each: () { (Elements::Row) -> void } -> void
|
|
30
51
|
|
|
31
|
-
|
|
52
|
+
# Iterate over rows in the worksheet.
|
|
53
|
+
#
|
|
54
|
+
# @example
|
|
55
|
+
# sheet.each_row do |row|
|
|
56
|
+
# puts "Row #{row.index}: #{row.to_a.inspect}"
|
|
57
|
+
# end
|
|
58
|
+
#
|
|
59
|
+
# @yield [row]
|
|
60
|
+
# @yieldparam row [Elements::Row]
|
|
61
|
+
# @return [Enumerator, void]
|
|
62
|
+
# @api public
|
|
63
|
+
# : () { (Elements::Row) -> void } -> void
|
|
64
|
+
# : | () -> Enumerator[Elements::Row, void]
|
|
65
|
+
def each_row: () { (Elements::Row) -> void } -> void
|
|
66
|
+
|
|
67
|
+
# Iterate over all cells across rows.
|
|
68
|
+
#
|
|
69
|
+
# @yield [cell]
|
|
70
|
+
# @yieldparam cell [Elements::Cell]
|
|
71
|
+
# @return [Enumerator, void]
|
|
72
|
+
# @api public
|
|
73
|
+
# : () { (Elements::Cell) -> void } -> void
|
|
74
|
+
# : | () -> Enumerator[Elements::Cell, void]
|
|
75
|
+
def each_cell: () { (Elements::Cell) -> void } -> void
|
|
76
|
+
|
|
77
|
+
# Returns whether the worksheet is valid according to OOXML specifications.
|
|
78
|
+
#
|
|
79
|
+
# @return [Boolean]
|
|
80
|
+
# : () -> bool
|
|
81
|
+
def valid?: () -> bool
|
|
82
|
+
|
|
83
|
+
# Returns a new Worksheet with the specified cell updated.
|
|
84
|
+
#
|
|
85
|
+
# @example
|
|
86
|
+
# new_sheet = sheet.update_cell("B1", value: "Updated")
|
|
87
|
+
#
|
|
88
|
+
# @param ref [String] The cell reference (e.g. "B1").
|
|
89
|
+
# @param value [Object] The new cell value.
|
|
90
|
+
# @param style_index [Integer, String, nil] Optional new style index.
|
|
91
|
+
# @param formula [Elements::Formula, nil] Optional new formula.
|
|
92
|
+
# @return [Worksheet] A new Worksheet instance.
|
|
93
|
+
# @api public
|
|
94
|
+
# : (String ref, ?value: untyped, ?style_index: Integer | String | nil, ?formula: Elements::Formula?) -> Elements::Worksheet
|
|
95
|
+
def update_cell: (String ref, ?value: untyped, ?style_index: Integer | String | nil, ?formula: Elements::Formula?) -> Elements::Worksheet
|
|
96
|
+
|
|
97
|
+
# Returns a new Worksheet with attributes replaced (Data-like behavior).
|
|
98
|
+
#
|
|
99
|
+
# @param changes [Hash]
|
|
100
|
+
# @return [Worksheet]
|
|
101
|
+
# @api public
|
|
102
|
+
# : (**untyped) -> Elements::Worksheet
|
|
103
|
+
def with: (**untyped) -> Elements::Worksheet
|
|
104
|
+
|
|
105
|
+
# Support pattern matching.
|
|
106
|
+
# : (Array[Symbol]?) -> Hash[Symbol, untyped]
|
|
107
|
+
def deconstruct_keys: (Array[Symbol]?) -> Hash[Symbol, untyped]
|
|
108
|
+
|
|
109
|
+
# Compare worksheets for equality.
|
|
110
|
+
# : (untyped other) -> bool
|
|
111
|
+
def ==: (untyped other) -> bool
|
|
112
|
+
|
|
113
|
+
alias eql? ==
|
|
114
|
+
|
|
115
|
+
# : () -> Integer
|
|
116
|
+
def hash: () -> Integer
|
|
117
|
+
|
|
118
|
+
# Returns self when load is called on an already in-memory Worksheet.
|
|
119
|
+
#
|
|
120
|
+
# @return [Elements::Worksheet]
|
|
121
|
+
# @api public
|
|
122
|
+
# : () -> Elements::Worksheet
|
|
123
|
+
def load: () -> Elements::Worksheet
|
|
124
|
+
|
|
125
|
+
alias to_worksheet load
|
|
126
|
+
|
|
127
|
+
# Validates worksheet name and rows against OOXML limits.
|
|
128
|
+
#
|
|
129
|
+
# @param name [String]
|
|
130
|
+
# @param rows [Array<Elements::Row>]
|
|
131
|
+
# @return [Array<String>] List of errors.
|
|
132
|
+
# : (untyped name, untyped rows) -> Array[String]
|
|
133
|
+
def self.validate: (untyped name, untyped rows) -> Array[String]
|
|
32
134
|
end
|
|
33
135
|
end
|
|
34
136
|
end
|
|
@@ -62,6 +62,8 @@ module Xlsxrb
|
|
|
62
62
|
def self.fast_scan_rows_direct: (untyped xml_src, untyped shared_strings, untyped part_name) ?{ (?) -> untyped } -> untyped
|
|
63
63
|
|
|
64
64
|
def self.fast_parse_cells_direct: (untyped xml, untyped from, untyped to, untyped shared_strings, untyped row_source) -> untyped
|
|
65
|
+
|
|
66
|
+
def self.fast_scan_cells_direct: (untyped xml, untyped from, untyped to, untyped shared_strings, untyped row_source) ?{ (?) -> untyped } -> untyped
|
|
65
67
|
end
|
|
66
68
|
end
|
|
67
69
|
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Generated from lib/xlsxrb/stream_row.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Xlsxrb
|
|
4
|
+
# Streaming row implementation that parses cells on-demand / lazily.
|
|
5
|
+
# Provides O(1) memory consumption even for rows with tens of thousands of columns.
|
|
6
|
+
#
|
|
7
|
+
# @example Streaming cells one-by-one (O(1) memory)
|
|
8
|
+
# row.each_cell do |cell|
|
|
9
|
+
# puts "#{cell.ref}: #{cell.value}"
|
|
10
|
+
# end
|
|
11
|
+
#
|
|
12
|
+
# @example Random access or array conversion (cached on-demand)
|
|
13
|
+
# cell = row[0]
|
|
14
|
+
# values = row.to_a
|
|
15
|
+
#
|
|
16
|
+
# @api public
|
|
17
|
+
class StreamRow
|
|
18
|
+
attr_reader index: untyped
|
|
19
|
+
|
|
20
|
+
attr_reader height: untyped
|
|
21
|
+
|
|
22
|
+
attr_reader hidden: untyped
|
|
23
|
+
|
|
24
|
+
attr_reader custom_height: untyped
|
|
25
|
+
|
|
26
|
+
attr_reader outline_level: untyped
|
|
27
|
+
|
|
28
|
+
# @param index [Integer] 0-based row index.
|
|
29
|
+
# @param xml_bytes [String] Raw ASCII-8BIT XML bytes.
|
|
30
|
+
# @param from [Integer] Byte offset where cells start.
|
|
31
|
+
# @param to [Integer] Byte offset where cells end.
|
|
32
|
+
# @param shared_strings [Array<String>] Shared strings table.
|
|
33
|
+
# @param height [Float, Integer, nil] Row height in points.
|
|
34
|
+
# @param hidden [Boolean] Whether the row is hidden.
|
|
35
|
+
# @param custom_height [Boolean] Whether custom height is set.
|
|
36
|
+
# @param outline_level [Integer, nil] Grouping/outline level.
|
|
37
|
+
# : (index: Integer, xml_bytes: String, from: Integer, to: Integer, shared_strings: Array[String], ?height: Float | Integer | nil, ?hidden: bool, ?custom_height: bool, ?outline_level: Integer | nil) -> void
|
|
38
|
+
def initialize: (index: Integer, xml_bytes: String, from: Integer, to: Integer, shared_strings: Array[String], ?height: Float | Integer | nil, ?hidden: bool, ?custom_height: bool, ?outline_level: Integer | nil) -> void
|
|
39
|
+
|
|
40
|
+
# Iterate over cells in this streaming row one by one.
|
|
41
|
+
#
|
|
42
|
+
# @yield [cell]
|
|
43
|
+
# @yieldparam cell [Elements::Cell]
|
|
44
|
+
# @return [Enumerator, void]
|
|
45
|
+
# @api public
|
|
46
|
+
# : () { (Elements::Cell) -> void } -> void
|
|
47
|
+
# : | () -> Enumerator[Elements::Cell, void]
|
|
48
|
+
def each_cell: () { (Elements::Cell) -> void } -> void
|
|
49
|
+
|
|
50
|
+
# Iterate over cells in this streaming row.
|
|
51
|
+
#
|
|
52
|
+
# @yield [cell]
|
|
53
|
+
# @yieldparam cell [Elements::Cell]
|
|
54
|
+
# @return [Enumerator, void]
|
|
55
|
+
# @api public
|
|
56
|
+
# : () { (Elements::Cell) -> void } -> void
|
|
57
|
+
# : | () -> Enumerator[Elements::Cell, void]
|
|
58
|
+
def each: () { (Elements::Cell) -> void } -> void
|
|
59
|
+
|
|
60
|
+
# Returns all cells as an Array. Cached on first access.
|
|
61
|
+
#
|
|
62
|
+
# @return [Array<Elements::Cell>]
|
|
63
|
+
# @api public
|
|
64
|
+
# : () -> Array[Elements::Cell]
|
|
65
|
+
def cells: () -> Array[Elements::Cell]
|
|
66
|
+
|
|
67
|
+
# Access a cell by 0-based column index, or access row attributes via Symbol.
|
|
68
|
+
#
|
|
69
|
+
# @param col_index [Integer, Symbol] Column index or attribute symbol.
|
|
70
|
+
# @return [Elements::Cell, Object, nil]
|
|
71
|
+
# @api public
|
|
72
|
+
# : (Integer | Symbol col_index) -> untyped
|
|
73
|
+
def []: (Integer | Symbol col_index) -> untyped
|
|
74
|
+
|
|
75
|
+
# Access a cell by 0-based column index.
|
|
76
|
+
#
|
|
77
|
+
# @param col_index [Integer] 0-based column index.
|
|
78
|
+
# @return [Elements::Cell, nil]
|
|
79
|
+
# @api public
|
|
80
|
+
# : (Integer col_index) -> Elements::Cell?
|
|
81
|
+
def cell_at: (Integer col_index) -> Elements::Cell?
|
|
82
|
+
|
|
83
|
+
# Convert row cells to an Array of raw values (sparse columns get nil).
|
|
84
|
+
#
|
|
85
|
+
# @return [Array<Object>]
|
|
86
|
+
# @api public
|
|
87
|
+
# : () -> Array[untyped]
|
|
88
|
+
def to_a: () -> Array[untyped]
|
|
89
|
+
|
|
90
|
+
# Returns cell values as an Array.
|
|
91
|
+
#
|
|
92
|
+
# @return [Array<Object>]
|
|
93
|
+
# @api public
|
|
94
|
+
# : () -> Array[untyped]
|
|
95
|
+
def values: () -> Array[untyped]
|
|
96
|
+
|
|
97
|
+
# Returns whether the row is valid according to OOXML specifications.
|
|
98
|
+
#
|
|
99
|
+
# @return [Boolean]
|
|
100
|
+
# @api public
|
|
101
|
+
# : () -> bool
|
|
102
|
+
def valid?: () -> bool
|
|
103
|
+
|
|
104
|
+
# Unmapped metadata for compatibility with Elements::Row.
|
|
105
|
+
#
|
|
106
|
+
# @return [Hash]
|
|
107
|
+
# @api public
|
|
108
|
+
# : () -> Hash[untyped, untyped]
|
|
109
|
+
def unmapped_data: () -> Hash[untyped, untyped]
|
|
110
|
+
|
|
111
|
+
# Validation errors for compatibility with Elements::Row.
|
|
112
|
+
#
|
|
113
|
+
# @return [Array<String>]
|
|
114
|
+
# @api public
|
|
115
|
+
# : () -> Array[String]
|
|
116
|
+
def errors: () -> Array[String]
|
|
117
|
+
|
|
118
|
+
# Human-readable representation.
|
|
119
|
+
#
|
|
120
|
+
# @return [String]
|
|
121
|
+
# @api public
|
|
122
|
+
# : () -> String
|
|
123
|
+
def inspect: () -> String
|
|
124
|
+
end
|
|
125
|
+
end
|
data/sig/generated/xlsxrb.rbs
CHANGED
|
@@ -266,33 +266,78 @@ module Xlsxrb
|
|
|
266
266
|
# : (String expression, ?cached_value: String | Numeric | bool | nil) -> Elements::Formula
|
|
267
267
|
def self.formula: (String expression, ?cached_value: String | Numeric | bool | nil) -> Elements::Formula
|
|
268
268
|
|
|
269
|
-
# Reads an XLSX file
|
|
269
|
+
# Reads an XLSX file (streaming / lazy-loaded by default) from a file path, IO stream, or binary String.
|
|
270
270
|
#
|
|
271
|
-
#
|
|
272
|
-
#
|
|
273
|
-
# sheet = workbook["Sheet1"]
|
|
274
|
-
# puts sheet["A1"].value
|
|
271
|
+
# Sheets and rows are streamed lazily with O(1) constant memory. If a block is given,
|
|
272
|
+
# yields each StreamSheet sequentially.
|
|
275
273
|
#
|
|
276
|
-
#
|
|
277
|
-
#
|
|
274
|
+
# Call #load on the returned Workbook or Sheet to convert to an in-memory representation
|
|
275
|
+
# for coordinate random access (e.g. sheet["A1"]).
|
|
278
276
|
#
|
|
279
|
-
# @
|
|
280
|
-
#
|
|
277
|
+
# @example Streaming read across sheets and rows (O(1) memory)
|
|
278
|
+
# Xlsxrb.read("large.xlsx") do |sheet|
|
|
279
|
+
# puts "Sheet: #{sheet.name}"
|
|
280
|
+
# sheet.each_row do |row|
|
|
281
|
+
# row.each_cell { |cell| puts "#{cell.ref}: #{cell.value}" }
|
|
282
|
+
# end
|
|
283
|
+
# end
|
|
284
|
+
#
|
|
285
|
+
# @example Lazy workbook access and explicit in-memory loading
|
|
286
|
+
# wb = Xlsxrb.read("data.xlsx")
|
|
287
|
+
# sheet = wb.sheets.first
|
|
288
|
+
# sheet.each_row { |row| ... } # streams with O(1) memory
|
|
289
|
+
# doc_sheet = sheet.load # explicitly load into memory
|
|
290
|
+
# puts doc_sheet["A1"].value # coordinate random access
|
|
291
|
+
#
|
|
292
|
+
# @param source [String, IO] File path, binary content string (starting with PK..), or IO object.
|
|
293
|
+
# @yield [sheet] Yields each streaming sheet.
|
|
294
|
+
# @yieldparam sheet [StreamSheet] The streaming worksheet object.
|
|
295
|
+
# @return [Elements::Workbook, void] Returns Elements::Workbook when no block is given.
|
|
281
296
|
# @api public
|
|
282
|
-
# : (
|
|
283
|
-
|
|
297
|
+
# : (String | IO source) { (StreamSheet) -> void } -> void
|
|
298
|
+
# : (String | IO source) -> Elements::Workbook
|
|
299
|
+
def self.read: (String | IO source) { (StreamSheet) -> void } -> void
|
|
300
|
+
| (String | IO source) -> Elements::Workbook
|
|
284
301
|
|
|
285
|
-
# Writes an
|
|
302
|
+
# Writes an XLSX file or IO stream (streaming or in-memory), or returns a binary string.
|
|
303
|
+
#
|
|
304
|
+
# @overload write(target, strict_excel_mode: true, &block)
|
|
305
|
+
# Streaming write: yields a StreamWriter context for high-speed, zero-allocation XLSX generation.
|
|
306
|
+
# @param target [String, IO] Destination file path or writable IO object.
|
|
307
|
+
# @param strict_excel_mode [Boolean] Whether to enforce Excel specifications.
|
|
308
|
+
# @yield [stream_writer]
|
|
309
|
+
# @yieldparam stream_writer [Xlsxrb::StreamWriter]
|
|
310
|
+
# @return [void]
|
|
311
|
+
#
|
|
312
|
+
# @overload write(workbook)
|
|
313
|
+
# In-memory write: exports the workbook to an in-memory binary String.
|
|
314
|
+
# @param workbook [Elements::Workbook] The workbook to write.
|
|
315
|
+
# @return [String] Binary data representing the XLSX file.
|
|
316
|
+
#
|
|
317
|
+
# @overload write(target, workbook)
|
|
318
|
+
# In-memory write: writes the workbook to a file path or IO stream.
|
|
319
|
+
# @param target [String, IO] Destination file path or writable IO object.
|
|
320
|
+
# @param workbook [Elements::Workbook] The workbook to write.
|
|
321
|
+
# @return [void]
|
|
286
322
|
#
|
|
287
|
-
# @example
|
|
323
|
+
# @example Streaming write to file
|
|
324
|
+
# Xlsxrb.write("output.xlsx") do |writer|
|
|
325
|
+
# writer.sheet("Sheet1") { |s| s.row(["Hello", "World"]) }
|
|
326
|
+
# end
|
|
327
|
+
#
|
|
328
|
+
# @example In-memory export to binary string
|
|
329
|
+
# binary_data = Xlsxrb.write(workbook)
|
|
330
|
+
#
|
|
331
|
+
# @example In-memory write to file
|
|
288
332
|
# Xlsxrb.write("output.xlsx", workbook)
|
|
289
333
|
#
|
|
290
|
-
# @param target [String, IO] File path or IO object.
|
|
291
|
-
# @param workbook [Elements::Workbook] The workbook to write.
|
|
292
|
-
# @return [void]
|
|
293
334
|
# @api public
|
|
294
|
-
# : (
|
|
295
|
-
|
|
335
|
+
# : (Elements::Workbook workbook) -> String
|
|
336
|
+
# : (String | IO target, Elements::Workbook workbook) -> void
|
|
337
|
+
# : (String | IO target, ?strict_excel_mode: bool) ?{ (StreamWriter) -> void } -> void
|
|
338
|
+
def self.write: (Elements::Workbook workbook) -> String
|
|
339
|
+
| (String | IO target, Elements::Workbook workbook) -> void
|
|
340
|
+
| (String | IO target, ?strict_excel_mode: bool) ?{ (StreamWriter) -> void } -> void
|
|
296
341
|
|
|
297
342
|
# Modifies an existing XLSX file.
|
|
298
343
|
# Reads the workbook, passes it to the block, and writes the result.
|
|
@@ -318,15 +363,26 @@ module Xlsxrb
|
|
|
318
363
|
def self.modify: (untyped source, ?untyped target) ?{ (Elements::Workbook) -> untyped } -> void
|
|
319
364
|
|
|
320
365
|
# Represents a sheet being streamed sequentially from an XLSX file.
|
|
366
|
+
# Provides O(1) constant-memory streaming over rows and cells.
|
|
367
|
+
#
|
|
368
|
+
# Call #load (or #to_worksheet) to convert this streaming sheet into an
|
|
369
|
+
# in-memory Elements::Worksheet supporting coordinate random access (sheet["A1"]).
|
|
321
370
|
#
|
|
322
|
-
# @example Iterate rows in streaming mode
|
|
323
|
-
# Xlsxrb.
|
|
371
|
+
# @example Iterate rows and cells in streaming mode (O(1) memory)
|
|
372
|
+
# Xlsxrb.read("large_data.xlsx") do |sheet|
|
|
324
373
|
# puts "Processing sheet: #{sheet.name}"
|
|
325
374
|
# sheet.each_row do |row|
|
|
326
|
-
#
|
|
375
|
+
# row.each_cell do |cell|
|
|
376
|
+
# puts "#{cell.ref}: #{cell.value}"
|
|
377
|
+
# end
|
|
327
378
|
# end
|
|
328
379
|
# end
|
|
329
380
|
#
|
|
381
|
+
# @example Load into an in-memory Worksheet for coordinate random access
|
|
382
|
+
# wb = Xlsxrb.read("data.xlsx")
|
|
383
|
+
# doc_sheet = wb.sheet(0).load
|
|
384
|
+
# puts doc_sheet["A1"].value
|
|
385
|
+
#
|
|
330
386
|
# @api public
|
|
331
387
|
class StreamSheet
|
|
332
388
|
attr_reader name: untyped
|
|
@@ -334,65 +390,51 @@ module Xlsxrb
|
|
|
334
390
|
# @param name [String] The sheet name.
|
|
335
391
|
# @param sheet_xml [String] Raw XML content of the sheet.
|
|
336
392
|
# @param shared_strings [Array<String>] Shared strings table.
|
|
337
|
-
#
|
|
338
|
-
|
|
393
|
+
# @param styles [Hash, nil] Styles table.
|
|
394
|
+
# : (String name, String sheet_xml, Array[String] shared_strings, ?Hash[untyped, untyped]? styles) -> void
|
|
395
|
+
def initialize: (String name, String sheet_xml, Array[String] shared_strings, ?Hash[untyped, untyped]? styles) -> void
|
|
339
396
|
|
|
340
|
-
# Iterate over rows in this streaming sheet.
|
|
397
|
+
# Iterate over rows in this streaming sheet (O(1) memory).
|
|
341
398
|
#
|
|
342
399
|
# @yield [row]
|
|
343
|
-
# @yieldparam row [Elements::Row]
|
|
400
|
+
# @yieldparam row [StreamRow, Elements::Row]
|
|
344
401
|
# @return [Enumerator, void]
|
|
345
402
|
# @api public
|
|
346
|
-
# : () { (Elements::Row) -> void } -> void
|
|
347
|
-
# : | () -> Enumerator[Elements::Row, void]
|
|
348
|
-
def each_row: () { (Elements::Row) -> void } -> void
|
|
403
|
+
# : () { (StreamRow | Elements::Row) -> void } -> void
|
|
404
|
+
# : | () -> Enumerator[StreamRow | Elements::Row, void]
|
|
405
|
+
def each_row: () { (StreamRow | Elements::Row) -> void } -> void
|
|
349
406
|
|
|
350
|
-
# Iterate over rows
|
|
407
|
+
# Iterate over all cells across rows continuously (O(1) memory).
|
|
408
|
+
#
|
|
409
|
+
# @yield [cell]
|
|
410
|
+
# @yieldparam cell [Elements::Cell]
|
|
411
|
+
# @return [Enumerator, void]
|
|
412
|
+
# @api public
|
|
413
|
+
# : () { (Elements::Cell) -> void } -> void
|
|
414
|
+
# : | () -> Enumerator[Elements::Cell, void]
|
|
415
|
+
def each_cell: () { (Elements::Cell) -> void } -> void
|
|
416
|
+
|
|
417
|
+
# Default Enumerable iteration iterates rows in the streaming sheet.
|
|
351
418
|
#
|
|
352
419
|
# @yield [row]
|
|
353
|
-
# @yieldparam row [Elements::Row]
|
|
420
|
+
# @yieldparam row [StreamRow, Elements::Row]
|
|
354
421
|
# @return [Enumerator, void]
|
|
355
422
|
# @api public
|
|
356
|
-
# : () { (Elements::Row) -> void } -> void
|
|
357
|
-
# : | () -> Enumerator[Elements::Row, void]
|
|
358
|
-
def each: () { (Elements::Row) -> void } -> void
|
|
359
|
-
end
|
|
423
|
+
# : () { (StreamRow | Elements::Row) -> void } -> void
|
|
424
|
+
# : | () -> Enumerator[StreamRow | Elements::Row, void]
|
|
425
|
+
def each: () { (StreamRow | Elements::Row) -> void } -> void
|
|
360
426
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
#
|
|
370
|
-
# @param source [String, IO] File path or IO object.
|
|
371
|
-
# @yield [sheet] Yields each sheet.
|
|
372
|
-
# @yieldparam sheet [StreamSheet] The streaming sheet object.
|
|
373
|
-
# @return [Enumerator, void]
|
|
374
|
-
# @api public
|
|
375
|
-
# : (untyped source) ?{ (StreamSheet) -> void } -> untyped
|
|
376
|
-
def self.foreach: (untyped source) ?{ (StreamSheet) -> void } -> untyped
|
|
427
|
+
# Loads this sheet completely into an in-memory Elements::Worksheet,
|
|
428
|
+
# enabling coordinate random access (sheet["A1"]), row lookups (row_at),
|
|
429
|
+
# and immutable cell updates (update_cell).
|
|
430
|
+
#
|
|
431
|
+
# @return [Elements::Worksheet] The fully parsed in-memory worksheet.
|
|
432
|
+
# @api public
|
|
433
|
+
# : () -> Elements::Worksheet
|
|
434
|
+
def load: () -> Elements::Worksheet
|
|
377
435
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
# @example Generate an Excel file with styles and multiple sheets
|
|
381
|
-
# Xlsxrb.generate("sales.xlsx") do |stream_writer|
|
|
382
|
-
# stream_writer.sheet("Q1") do |sheet|
|
|
383
|
-
# sheet.row(["Product", "Revenue"], styles: :bold)
|
|
384
|
-
# sheet.row(["Widget", 15000])
|
|
385
|
-
# end
|
|
386
|
-
# end
|
|
387
|
-
#
|
|
388
|
-
# @param target [String, IO] File path or IO stream (e.g. pipe, socket, Rails response buffer).
|
|
389
|
-
# @param strict_excel_mode [Boolean] Whether to enforce Excel specifications (max rows/cols/length).
|
|
390
|
-
# @yield [stream_writer]
|
|
391
|
-
# @yieldparam stream_writer [Xlsxrb::StreamWriter]
|
|
392
|
-
# @return [void]
|
|
393
|
-
# @api public
|
|
394
|
-
# : (untyped target, ?strict_excel_mode: bool) ?{ (StreamWriter) -> void } -> void
|
|
395
|
-
def self.generate: (untyped target, ?strict_excel_mode: bool) ?{ (StreamWriter) -> void } -> void
|
|
436
|
+
alias to_worksheet load
|
|
437
|
+
end
|
|
396
438
|
|
|
397
439
|
# Builds an in-memory Elements::Workbook using a declarative DSL.
|
|
398
440
|
#
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: xlsxrb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- niku
|
|
@@ -184,6 +184,7 @@ files:
|
|
|
184
184
|
- lib/xlsxrb/elements.rb
|
|
185
185
|
- lib/xlsxrb/elements/cell.rb
|
|
186
186
|
- lib/xlsxrb/elements/column.rb
|
|
187
|
+
- lib/xlsxrb/elements/coordinate_access.rb
|
|
187
188
|
- lib/xlsxrb/elements/row.rb
|
|
188
189
|
- lib/xlsxrb/elements/types.rb
|
|
189
190
|
- lib/xlsxrb/elements/workbook.rb
|
|
@@ -203,6 +204,7 @@ files:
|
|
|
203
204
|
- lib/xlsxrb/ooxml/zip_generator.rb
|
|
204
205
|
- lib/xlsxrb/ooxml/zip_reader.rb
|
|
205
206
|
- lib/xlsxrb/ooxml/zip_writer.rb
|
|
207
|
+
- lib/xlsxrb/stream_row.rb
|
|
206
208
|
- lib/xlsxrb/style_builder.rb
|
|
207
209
|
- lib/xlsxrb/version.rb
|
|
208
210
|
- rbs_collection.lock.yaml
|
|
@@ -211,6 +213,7 @@ files:
|
|
|
211
213
|
- sig/generated/xlsxrb/elements.rbs
|
|
212
214
|
- sig/generated/xlsxrb/elements/cell.rbs
|
|
213
215
|
- sig/generated/xlsxrb/elements/column.rbs
|
|
216
|
+
- sig/generated/xlsxrb/elements/coordinate_access.rbs
|
|
214
217
|
- sig/generated/xlsxrb/elements/row.rbs
|
|
215
218
|
- sig/generated/xlsxrb/elements/types.rbs
|
|
216
219
|
- sig/generated/xlsxrb/elements/workbook.rbs
|
|
@@ -230,6 +233,7 @@ files:
|
|
|
230
233
|
- sig/generated/xlsxrb/ooxml/zip_generator.rbs
|
|
231
234
|
- sig/generated/xlsxrb/ooxml/zip_reader.rbs
|
|
232
235
|
- sig/generated/xlsxrb/ooxml/zip_writer.rbs
|
|
236
|
+
- sig/generated/xlsxrb/stream_row.rbs
|
|
233
237
|
- sig/generated/xlsxrb/style_builder.rbs
|
|
234
238
|
- sig/generated/xlsxrb/version.rbs
|
|
235
239
|
- sig/rexml.rbs
|