roo-oxide 0.0.2-x86_64-linux
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 +7 -0
- data/CHANGELOG.md +63 -0
- data/LICENSE +21 -0
- data/README.md +220 -0
- data/lib/roo/calamine/version.rb +5 -0
- data/lib/roo/calamine.rb +3 -0
- data/lib/roo/oxide/3.3/roo_oxide.so +0 -0
- data/lib/roo/oxide/3.4/roo_oxide.so +0 -0
- data/lib/roo/oxide/4.0/roo_oxide.so +0 -0
- data/lib/roo/oxide/context.rb +74 -0
- data/lib/roo/oxide/csv.rb +157 -0
- data/lib/roo/oxide/deferred_sheets.rb +284 -0
- data/lib/roo/oxide/excelx.rb +156 -0
- data/lib/roo/oxide/formatters.rb +114 -0
- data/lib/roo/oxide/row_index.rb +93 -0
- data/lib/roo/oxide/row_iteration.rb +33 -0
- data/lib/roo/oxide/shared_strings.rb +46 -0
- data/lib/roo/oxide/sheet.rb +99 -0
- data/lib/roo/oxide/sheet_doc.rb +138 -0
- data/lib/roo/oxide/sheet_parts.rb +78 -0
- data/lib/roo/oxide/version.rb +7 -0
- data/lib/roo/oxide.rb +100 -0
- metadata +88 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Roo
|
|
4
|
+
module Oxide
|
|
5
|
+
# Prepended to Roo::Excelx::SharedStrings: the native extension builds the
|
|
6
|
+
# arrays #to_a and #to_html memoize, deferring HTML objects until used.
|
|
7
|
+
# Roo's own code and the native reader share them. A file the extension
|
|
8
|
+
# does not read exactly the way roo does is left to roo.
|
|
9
|
+
module SharedStrings
|
|
10
|
+
# roo versions whose shared-string extraction the extension reproduces.
|
|
11
|
+
ROO_VERSIONS = %w[4.0.0].freeze
|
|
12
|
+
|
|
13
|
+
def to_a
|
|
14
|
+
oxide_read(html: !@options[:disable_html_wrapper] && !(@html || @oxide_html), plain: true) unless @array
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_html
|
|
19
|
+
unless @html
|
|
20
|
+
oxide_read(html: true, plain: false) unless @oxide_html
|
|
21
|
+
@html = @oxide_html.to_a if @oxide_html && (@oxide_html_used || doc_exists?)
|
|
22
|
+
end
|
|
23
|
+
super
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def oxide_html
|
|
27
|
+
return to_html unless @oxide_html && (@oxide_html_used || doc_exists?)
|
|
28
|
+
|
|
29
|
+
@oxide_html_used = true
|
|
30
|
+
@html || @oxide_html
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def oxide_read(html:, plain:)
|
|
36
|
+
return unless Oxide.enabled? && ROO_VERSIONS.include?(Roo::VERSION) && doc_exists?
|
|
37
|
+
|
|
38
|
+
plain, html = Native.shared_strings(@path, html, plain)
|
|
39
|
+
@array ||= plain
|
|
40
|
+
@oxide_html ||= html
|
|
41
|
+
rescue UnsupportedError
|
|
42
|
+
nil
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Roo
|
|
4
|
+
module Oxide
|
|
5
|
+
# Prepended to Roo::Excelx::Sheet: single-cell lookups, rows, columns, and
|
|
6
|
+
# the sheet's bounds read the lazy cells of SheetDoc#lazy_cells while
|
|
7
|
+
# #cells has not been built, so they build only the cells they read. Rows
|
|
8
|
+
# and columns build only the cells whose value needs one.
|
|
9
|
+
module Sheet
|
|
10
|
+
NO_CELLS = [].freeze
|
|
11
|
+
private_constant :NO_CELLS
|
|
12
|
+
|
|
13
|
+
# cells[[row, column]]
|
|
14
|
+
def cell_at(row, column)
|
|
15
|
+
(lazy = lazy_cells) ? lazy.cell_at(row, column) : cells[[row, column]]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def row(row_number)
|
|
19
|
+
lazy = lazy_cells
|
|
20
|
+
return lazy.row(row_number, first_column, last_column) if lazy && first_column
|
|
21
|
+
|
|
22
|
+
first_column.upto(last_column).map do |col|
|
|
23
|
+
cell_at(row_number, col)&.value
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def column(col_number)
|
|
28
|
+
lazy = lazy_cells
|
|
29
|
+
return lazy.column(col_number, first_row, last_row) if lazy && first_row
|
|
30
|
+
|
|
31
|
+
first_row.upto(last_row).map do |row|
|
|
32
|
+
cell_at(row, col_number)&.value
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def excelx_format(key)
|
|
37
|
+
cell = (lazy = lazy_cells) ? lazy[key] : cells[key]
|
|
38
|
+
styles.style_format(cell.style).to_s if cell
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# For Excelx#parse: a Hash per line of `lines`, holding the value of the
|
|
42
|
+
# cell at [line, column] under `key` for each [key, column] of `fields`.
|
|
43
|
+
def parse_rows(lines, fields)
|
|
44
|
+
lazy = lazy_cells
|
|
45
|
+
if lazy && fields.all? { |_, column| column.is_a?(Integer) }
|
|
46
|
+
lazy_parse_rows(lazy, lines, fields)
|
|
47
|
+
else
|
|
48
|
+
cells_parse_rows(lines, fields)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# The Native::Store behind the lazy cells while #cells is not built.
|
|
53
|
+
def lazy_cells
|
|
54
|
+
@sheet.lazy_cells(@rels) unless @cells
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def lazy_parse_rows(lazy, lines, fields)
|
|
60
|
+
first, last = fields.map(&:last).minmax
|
|
61
|
+
slots = fields.map { |key, column| [key, column - first] }.freeze
|
|
62
|
+
lines.map { |line| lazy.hash_row(line, first || 1, last || 0, slots) }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def cells_parse_rows(lines, fields)
|
|
66
|
+
slots = fields.map(&:last).uniq.each_with_index.to_h
|
|
67
|
+
by_line = cells_by_line(slots)
|
|
68
|
+
fields = fields.map { |key, column| [key, slots.fetch(column)] }
|
|
69
|
+
lines.map do |line|
|
|
70
|
+
line_cells = by_line.fetch(line, NO_CELLS)
|
|
71
|
+
fields.each_with_object({}) do |(key, slot), row|
|
|
72
|
+
cell = line_cells[slot]
|
|
73
|
+
row[key] = (cell.value if cell.respond_to?(:value)) # Roo::Excelx#safe_send, inline
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def cells_by_line(slots)
|
|
79
|
+
by_line = {}
|
|
80
|
+
cells.each do |(line, column), cell|
|
|
81
|
+
slot = slots[column] or next
|
|
82
|
+
(by_line[line] ||= Array.new(slots.size))[slot] = cell
|
|
83
|
+
end
|
|
84
|
+
by_line
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Custom padding stays in roo's loop over #each_cell.
|
|
88
|
+
def cells_for_row_element(row_element, options = {})
|
|
89
|
+
return super if options[:pad_cells] && !method(:pad_cells).owner.equal?(::Roo::Excelx::Sheet)
|
|
90
|
+
|
|
91
|
+
@sheet.native_row_cells(row_element, pad_cells: options[:pad_cells]) || super
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def first_last_row_col
|
|
95
|
+
@first_last_row_col ||= lazy_cells&.bounds || super
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Roo
|
|
4
|
+
module Oxide
|
|
5
|
+
# Prepended to Roo::Excelx::SheetDoc, where every worksheet read in roo
|
|
6
|
+
# starts: Sheet#cells (and with it #row, #each, #parse), the lazy cells
|
|
7
|
+
# behind Excelx#cell and the other single-cell lookups, and Sheet#each_row
|
|
8
|
+
# (#each_row_streaming). Offsets and row limits stay roo's code.
|
|
9
|
+
module SheetDoc
|
|
10
|
+
# Cells the native reader parses ahead of Ruby, per batch.
|
|
11
|
+
BATCH_CELLS = 16_384
|
|
12
|
+
|
|
13
|
+
# A sheet already read into a Native::Store is built from it even when
|
|
14
|
+
# the native reader has been turned off since, so the cells handed out
|
|
15
|
+
# stay the ones #cells holds.
|
|
16
|
+
def cells(relationships)
|
|
17
|
+
return super if @cells || !(native? || @oxide_store)
|
|
18
|
+
|
|
19
|
+
store = @oxide_store || nil
|
|
20
|
+
@oxide_store = nil
|
|
21
|
+
@cells = store ? store.cells : read_cells(relationships)
|
|
22
|
+
rescue UnsupportedError
|
|
23
|
+
super
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# The cells of #cells, each built when it is first read. nil when they
|
|
27
|
+
# have to be built all at once: when #cells already exists, when merged
|
|
28
|
+
# ranges are expanded, and when building some cell would raise, because
|
|
29
|
+
# roo raises for the whole sheet then.
|
|
30
|
+
def lazy_cells(relationships)
|
|
31
|
+
if @oxide_store.nil? && !@cells && !@options[:expand_merged_ranges] && native?
|
|
32
|
+
@oxide_store = read_store(relationships)
|
|
33
|
+
end
|
|
34
|
+
@oxide_store || nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Yields Native::Row objects; #each_cell turns one into cells when roo
|
|
38
|
+
# asks for it, so rows roo skips are never converted, as in roo.
|
|
39
|
+
def each_row_streaming(&)
|
|
40
|
+
return super unless native?
|
|
41
|
+
|
|
42
|
+
yielded = 0
|
|
43
|
+
reader = Native::Reader.new(sheet_source, true, BATCH_CELLS)
|
|
44
|
+
while (row = reader.next_row)
|
|
45
|
+
yield row
|
|
46
|
+
yielded += 1
|
|
47
|
+
end
|
|
48
|
+
nil
|
|
49
|
+
rescue UnsupportedError
|
|
50
|
+
# roo reads the sheet again; skip the rows already yielded.
|
|
51
|
+
skip = yielded
|
|
52
|
+
super { |row| skip.zero? ? yield(row) : skip -= 1 }
|
|
53
|
+
ensure
|
|
54
|
+
# Also when the caller stops early, as roo does for max_rows.
|
|
55
|
+
reader&.close
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def each_cell(row_xml, &)
|
|
59
|
+
return super unless row_xml.is_a?(Native::Row)
|
|
60
|
+
|
|
61
|
+
oxide_stream_converter.row_cells(row_xml, false).each(&)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# The cells #each_cell yields for a Native::Row, as a new Array; nil for
|
|
65
|
+
# rows roo reads itself, custom #each_cell, or roo-only padding.
|
|
66
|
+
def native_row_cells(row, pad_cells: false)
|
|
67
|
+
return unless row.is_a?(Native::Row) && method(:each_cell).owner.equal?(SheetDoc)
|
|
68
|
+
|
|
69
|
+
oxide_stream_converter.row_cells(row, pad_cells)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Roo::Oxide.each_row_values. `sheet` is the Roo::Excelx::Sheet that
|
|
73
|
+
# owns this document; it turns rows that roo reads itself into cells.
|
|
74
|
+
def each_row_values(sheet, &)
|
|
75
|
+
return each_roo_row_values(sheet, 0, &) unless native?
|
|
76
|
+
|
|
77
|
+
yielded = 0
|
|
78
|
+
reader = Native::Reader.new(sheet_source, true, BATCH_CELLS)
|
|
79
|
+
while (values = reader.next_values(oxide_stream_converter))
|
|
80
|
+
yield values
|
|
81
|
+
yielded += 1
|
|
82
|
+
end
|
|
83
|
+
nil
|
|
84
|
+
rescue UnsupportedError
|
|
85
|
+
each_roo_row_values(sheet, yielded, &)
|
|
86
|
+
ensure
|
|
87
|
+
reader&.close
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
|
|
92
|
+
# The values of the rows roo's own #each_row_streaming yields, after the
|
|
93
|
+
# first `skip`.
|
|
94
|
+
def each_roo_row_values(sheet, skip)
|
|
95
|
+
method(:each_row_streaming).super_method.call do |row|
|
|
96
|
+
next skip -= 1 unless skip.zero?
|
|
97
|
+
|
|
98
|
+
yield sheet.send(:cells_for_row_element, row, pad_cells: true).map { |cell| cell&.value }
|
|
99
|
+
end
|
|
100
|
+
nil
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def oxide_stream_converter
|
|
104
|
+
@oxide_stream_converter ||= Native::Converter.new(Context.new(@shared, hyperlinks(@relationships), true),
|
|
105
|
+
true)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def native?
|
|
109
|
+
@path && Oxide.enabled?
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Every cell, in roo's order.
|
|
113
|
+
def read_cells(relationships)
|
|
114
|
+
cells = {}
|
|
115
|
+
reader = Native::Reader.new(sheet_source, false, BATCH_CELLS)
|
|
116
|
+
converter = Native::Converter.new(context(relationships), false)
|
|
117
|
+
nil while reader.fill_cells(cells, converter)
|
|
118
|
+
expand_merged_ranges(cells) if @options[:expand_merged_ranges]
|
|
119
|
+
cells
|
|
120
|
+
ensure
|
|
121
|
+
reader&.close
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# A Native::Store, or false when the cells have to be built all at once.
|
|
125
|
+
# roo applies the hyperlinks to every cell on the first read, so later
|
|
126
|
+
# changes to the hash it hands out do not reach the cells.
|
|
127
|
+
def read_store(relationships)
|
|
128
|
+
Native::Store.read(sheet_source, context(relationships, hyperlinks(relationships).dup)) || false
|
|
129
|
+
rescue UnsupportedError
|
|
130
|
+
false
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def context(relationships, links = hyperlinks(relationships))
|
|
134
|
+
Context.new(@shared, links, @options[:empty_cell])
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Roo
|
|
4
|
+
module Oxide
|
|
5
|
+
# Prepended to Roo::Excelx::SheetDoc. roo finds a sheet's hyperlinks
|
|
6
|
+
# (#hyperlinks, behind every read of a sheet with a hyperlink
|
|
7
|
+
# relationship) and its merged ranges with XPath on the whole sheet.
|
|
8
|
+
# Native.sheet_parts resolves links without a Nokogiri document.
|
|
9
|
+
module SheetParts
|
|
10
|
+
# roo versions whose hyperlink and merge rules these methods reproduce.
|
|
11
|
+
ROO_VERSIONS = %w[4.0.0].freeze
|
|
12
|
+
|
|
13
|
+
def hyperlinks(relationships)
|
|
14
|
+
return super unless native? && ROO_VERSIONS.include?(Roo::VERSION)
|
|
15
|
+
return @hyperlinks if @hyperlinks
|
|
16
|
+
return @hyperlinks = {} if @options[:no_hyperlinks]
|
|
17
|
+
|
|
18
|
+
targets = relationships.oxide_hyperlink_targets
|
|
19
|
+
return @hyperlinks = {} unless targets
|
|
20
|
+
return super unless (parts = oxide_parts(targets))
|
|
21
|
+
|
|
22
|
+
@hyperlinks = parts.first
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def expand_merged_ranges(cells)
|
|
28
|
+
return super unless (parts = oxide_parts)
|
|
29
|
+
|
|
30
|
+
merges = {}
|
|
31
|
+
parts.last.each { |ref| merge_range(merges, ref, cells) }
|
|
32
|
+
merges.each { |dst, src| cells[dst] = cells[src] }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def merge_range(merges, ref, cells)
|
|
36
|
+
src, dst = ref.split(":").map { |key| ::Roo::Utils.ref_to_key(key) }
|
|
37
|
+
return unless cells[src]
|
|
38
|
+
|
|
39
|
+
(src[0]..dst[0]).each do |row|
|
|
40
|
+
(src[1]..dst[1]).each do |col|
|
|
41
|
+
merges[[row, col]] = src unless row == src[0] && col == src[1]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# [hyperlinks, merge_cells] from Native.sheet_parts, or nil when roo
|
|
47
|
+
# reads them from the whole document.
|
|
48
|
+
def oxide_parts(targets = {})
|
|
49
|
+
return unless native? && ROO_VERSIONS.include?(Roo::VERSION)
|
|
50
|
+
|
|
51
|
+
@oxide_parts = Native.sheet_parts(sheet_source, targets) if @oxide_parts.nil?
|
|
52
|
+
@oxide_parts || nil
|
|
53
|
+
rescue UnsupportedError
|
|
54
|
+
@oxide_parts = false
|
|
55
|
+
nil
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# roo's relationship nodes stay lazy; hyperlink reads need only targets.
|
|
60
|
+
module HyperlinkRelationships
|
|
61
|
+
def oxide_hyperlink_targets
|
|
62
|
+
return targets_from_roo if @relationships || !doc_exists?
|
|
63
|
+
|
|
64
|
+
Native.hyperlink_targets(@path)
|
|
65
|
+
rescue UnsupportedError
|
|
66
|
+
targets_from_roo
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def targets_from_roo
|
|
72
|
+
return unless include_type?("hyperlink")
|
|
73
|
+
|
|
74
|
+
to_a.transform_values { |relationship| relationship["Target"] }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
data/lib/roo/oxide.rb
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "roo"
|
|
4
|
+
require "roo/excelx"
|
|
5
|
+
require_relative "oxide/version"
|
|
6
|
+
|
|
7
|
+
if Roo.const_defined?(:Calamine, false) && !Roo::Calamine.equal?(Roo::Oxide)
|
|
8
|
+
raise LoadError, "Replace roo-calamine with roo-oxide in your Gemfile before loading roo/oxide"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
Roo::Calamine = Roo::Oxide unless Roo.const_defined?(:Calamine, false)
|
|
12
|
+
|
|
13
|
+
module Roo
|
|
14
|
+
# Reads `.xlsx` and `.xlsm` worksheets for Roo::Excelx with a native
|
|
15
|
+
# extension. Loading this file is all it takes; `Roo::Oxide.enabled =
|
|
16
|
+
# false` or `ROO_OXIDE=0` switches back to roo's own reader at runtime.
|
|
17
|
+
module Oxide
|
|
18
|
+
# Raised by the native reader for XML it does not reproduce exactly the
|
|
19
|
+
# way roo reads it. Roo::Oxide rescues it and lets roo read the sheet.
|
|
20
|
+
class UnsupportedError < StandardError; end
|
|
21
|
+
|
|
22
|
+
DISABLING_ENV_VALUES = %w[0 false off].freeze
|
|
23
|
+
private_constant :DISABLING_ENV_VALUES
|
|
24
|
+
|
|
25
|
+
@enabled = true
|
|
26
|
+
|
|
27
|
+
class << self
|
|
28
|
+
attr_writer :enabled
|
|
29
|
+
|
|
30
|
+
# Whether the native extension is loaded. It is `false` on Ruby
|
|
31
|
+
# implementations other than CRuby, such as JRuby.
|
|
32
|
+
def available?
|
|
33
|
+
defined?(Native::Reader) ? true : false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Whether the next worksheet read goes through the native reader.
|
|
37
|
+
def enabled?
|
|
38
|
+
environment = ENV.fetch("ROO_OXIDE") { ENV.fetch("ROO_CALAMINE", "") }
|
|
39
|
+
@enabled && available? && !DISABLING_ENV_VALUES.include?(environment.downcase)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# roo-oxide's own API, not roo's: yields each row of a worksheet as an
|
|
43
|
+
# Array of the values roo's cells return from `#value`, without building
|
|
44
|
+
# the cells. A row is what
|
|
45
|
+
# `Roo::Excelx#each_row_streaming(sheet:, pad_cells: true)` yields, with
|
|
46
|
+
# `cell&.value` in place of each cell: one entry per column from A up to
|
|
47
|
+
# the row's last cell, `nil` where the worksheet has no cell.
|
|
48
|
+
#
|
|
49
|
+
# `source` and `options` are what `Roo::Excelx.new` takes. The workbook
|
|
50
|
+
# is closed when the block returns. Without a block, returns an
|
|
51
|
+
# Enumerator.
|
|
52
|
+
def each_row_values(source, sheet: nil, **options, &block)
|
|
53
|
+
return enum_for(__method__, source, sheet:, **options) unless block
|
|
54
|
+
|
|
55
|
+
workbook = Roo::Excelx.new(source, options)
|
|
56
|
+
roo_sheet = workbook.sheet_for(sheet)
|
|
57
|
+
if available?
|
|
58
|
+
roo_sheet.instance_variable_get(:@sheet).each_row_values(roo_sheet, &block)
|
|
59
|
+
else
|
|
60
|
+
roo_sheet.each_row(pad_cells: true) { |cells| yield cells.map { |cell| cell&.value } }
|
|
61
|
+
end
|
|
62
|
+
nil
|
|
63
|
+
ensure
|
|
64
|
+
workbook&.close
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
if RUBY_ENGINE == "ruby"
|
|
71
|
+
begin
|
|
72
|
+
require "roo/oxide/#{RUBY_VERSION[/\d+\.\d+/]}/roo_oxide"
|
|
73
|
+
rescue LoadError
|
|
74
|
+
require "roo/oxide/roo_oxide"
|
|
75
|
+
end
|
|
76
|
+
require_relative "oxide/context"
|
|
77
|
+
require_relative "oxide/deferred_sheets"
|
|
78
|
+
require_relative "oxide/sheet_doc"
|
|
79
|
+
require_relative "oxide/sheet_parts"
|
|
80
|
+
require_relative "oxide/excelx"
|
|
81
|
+
require_relative "oxide/csv"
|
|
82
|
+
require_relative "oxide/formatters"
|
|
83
|
+
require_relative "oxide/row_index"
|
|
84
|
+
require_relative "oxide/row_iteration"
|
|
85
|
+
require_relative "oxide/sheet"
|
|
86
|
+
require_relative "oxide/shared_strings"
|
|
87
|
+
Roo::Excelx::SheetDoc.prepend(Roo::Oxide::DeferredSheetDoc)
|
|
88
|
+
Roo::Excelx::SheetDoc.prepend(Roo::Oxide::SheetDoc)
|
|
89
|
+
Roo::Excelx::SheetDoc.prepend(Roo::Oxide::SheetParts)
|
|
90
|
+
Roo::Excelx::Relationships.prepend(Roo::Oxide::HyperlinkRelationships)
|
|
91
|
+
Roo::Excelx::Sheet.prepend(Roo::Oxide::Sheet)
|
|
92
|
+
Roo::Excelx.prepend(Roo::Oxide::DeferredSheets)
|
|
93
|
+
Roo::Excelx.prepend(Roo::Oxide::Excelx)
|
|
94
|
+
Roo::Excelx.prepend(Roo::Oxide::SheetSelection)
|
|
95
|
+
Roo::Excelx::SharedStrings.prepend(Roo::Oxide::SharedStrings)
|
|
96
|
+
Roo::Excelx::Workbook.prepend(Roo::Oxide::MetadataDocument)
|
|
97
|
+
Roo::Excelx::Styles.prepend(Roo::Oxide::MetadataDocument)
|
|
98
|
+
Roo::Excelx.prepend(Roo::Oxide::CSV)
|
|
99
|
+
Roo::Excelx.prepend(Roo::Oxide::Formatters)
|
|
100
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: roo-oxide
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.2
|
|
5
|
+
platform: x86_64-linux
|
|
6
|
+
authors:
|
|
7
|
+
- Sebastian Sala
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-11-13 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: roo
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '4.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '4.0'
|
|
27
|
+
description: An unofficial acceleration layer built on top of Roo. Add roo-oxide to
|
|
28
|
+
the Gemfile; Roo is installed as a dependency and its spreadsheet API stays the
|
|
29
|
+
same. A Rust extension speeds up XLSX and XLSM reads while preserving Roo's cell
|
|
30
|
+
and value rules. Unsupported input uses Roo's own reader. Not affiliated with roo-rb.
|
|
31
|
+
email:
|
|
32
|
+
executables: []
|
|
33
|
+
extensions: []
|
|
34
|
+
extra_rdoc_files: []
|
|
35
|
+
files:
|
|
36
|
+
- CHANGELOG.md
|
|
37
|
+
- LICENSE
|
|
38
|
+
- README.md
|
|
39
|
+
- lib/roo/calamine.rb
|
|
40
|
+
- lib/roo/calamine/version.rb
|
|
41
|
+
- lib/roo/oxide.rb
|
|
42
|
+
- lib/roo/oxide/3.3/roo_oxide.so
|
|
43
|
+
- lib/roo/oxide/3.4/roo_oxide.so
|
|
44
|
+
- lib/roo/oxide/4.0/roo_oxide.so
|
|
45
|
+
- lib/roo/oxide/context.rb
|
|
46
|
+
- lib/roo/oxide/csv.rb
|
|
47
|
+
- lib/roo/oxide/deferred_sheets.rb
|
|
48
|
+
- lib/roo/oxide/excelx.rb
|
|
49
|
+
- lib/roo/oxide/formatters.rb
|
|
50
|
+
- lib/roo/oxide/row_index.rb
|
|
51
|
+
- lib/roo/oxide/row_iteration.rb
|
|
52
|
+
- lib/roo/oxide/shared_strings.rb
|
|
53
|
+
- lib/roo/oxide/sheet.rb
|
|
54
|
+
- lib/roo/oxide/sheet_doc.rb
|
|
55
|
+
- lib/roo/oxide/sheet_parts.rb
|
|
56
|
+
- lib/roo/oxide/version.rb
|
|
57
|
+
homepage: https://github.com/salasebas/roo-oxide
|
|
58
|
+
licenses:
|
|
59
|
+
- MIT
|
|
60
|
+
metadata:
|
|
61
|
+
homepage_uri: https://github.com/salasebas/roo-oxide
|
|
62
|
+
source_code_uri: https://github.com/salasebas/roo-oxide/tree/v0.0.2
|
|
63
|
+
changelog_uri: https://github.com/salasebas/roo-oxide/blob/v0.0.2/CHANGELOG.md
|
|
64
|
+
bug_tracker_uri: https://github.com/salasebas/roo-oxide/issues
|
|
65
|
+
rubygems_mfa_required: 'true'
|
|
66
|
+
post_install_message:
|
|
67
|
+
rdoc_options: []
|
|
68
|
+
require_paths:
|
|
69
|
+
- lib
|
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '3.3'
|
|
75
|
+
- - "<"
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: 4.1.dev
|
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 3.3.11
|
|
83
|
+
requirements: []
|
|
84
|
+
rubygems_version: 3.5.23
|
|
85
|
+
signing_key:
|
|
86
|
+
specification_version: 4
|
|
87
|
+
summary: Rust-powered native acceleration for Roo's XLSX and XLSM readers.
|
|
88
|
+
test_files: []
|