roo-calamine 0.0.1

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.
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Roo
4
+ module Calamine
5
+ # The answers the native reader needs from roo while it builds cells. Each
6
+ # one comes from the roo object or method that SheetDoc#cell_from_xml uses,
7
+ # so formats, shared strings, and errors are roo's own.
8
+ class Context
9
+ attr_reader :hyperlinks, :empty_cell
10
+
11
+ def initialize(shared, hyperlinks, empty_cell)
12
+ @shared = shared
13
+ @hyperlinks = hyperlinks
14
+ @empty_cell = empty_cell
15
+ end
16
+
17
+ def base_date
18
+ @shared.base_date
19
+ end
20
+
21
+ def base_timestamp
22
+ @shared.base_timestamp
23
+ end
24
+
25
+ def style(index)
26
+ format = @shared.styles.style_format(index)
27
+ [format.to_s, Roo::Excelx::Format.to_type(format)]
28
+ end
29
+
30
+ def style_index(text)
31
+ text.to_i
32
+ end
33
+
34
+ def coordinate(reference)
35
+ Roo::Utils.extract_coordinate(reference)
36
+ end
37
+
38
+ # roo's own memoized shared-string arrays: plain text, and the HTML that
39
+ # SharedStrings#use_html? tests (nil when the HTML wrapper is disabled).
40
+ def shared_strings
41
+ strings = @shared.shared_strings
42
+ html_disabled = strings.instance_variable_get(:@options)[:disable_html_wrapper]
43
+ [strings.to_a, (strings.to_html unless html_disabled)]
44
+ end
45
+
46
+ def shared_string(text)
47
+ shared_string_at(@shared.shared_strings, text.to_i)
48
+ end
49
+
50
+ private
51
+
52
+ def shared_string_at(strings, index)
53
+ strings.use_html?(index) ? strings.to_html[index] : strings[index]
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Roo
4
+ module Calamine
5
+ # Prepended to Roo::Excelx::SheetDoc, where every worksheet read in roo
6
+ # starts: Sheet#cells (and with it #cell, #row, #each, #parse) and
7
+ # Sheet#each_row (#each_row_streaming). Everything else, including roo's
8
+ # padding, offset, and row limits, stays roo's code.
9
+ module SheetDoc
10
+ # Cells the native reader parses ahead of Ruby, per batch.
11
+ BATCH_CELLS = 16_384
12
+
13
+ def cells(relationships)
14
+ return super if @cells || !native?
15
+
16
+ cells = {}
17
+ reader = Native::Reader.new(@path, false, BATCH_CELLS)
18
+ converter = Native::Converter.new(Context.new(@shared, hyperlinks(relationships), @options[:empty_cell]), false)
19
+ nil while reader.fill_cells(cells, converter)
20
+ expand_merged_ranges(cells) if @options[:expand_merged_ranges]
21
+ @cells = cells
22
+ rescue UnsupportedError
23
+ super
24
+ ensure
25
+ reader&.close
26
+ end
27
+
28
+ # Yields Native::Row objects; #each_cell turns one into cells when roo
29
+ # asks for it, so rows roo skips are never converted, as in roo.
30
+ def each_row_streaming(&)
31
+ return super unless native?
32
+
33
+ yielded = 0
34
+ reader = Native::Reader.new(@path, true, BATCH_CELLS)
35
+ while (rows = reader.next_rows)
36
+ rows.each do |row|
37
+ yield row
38
+ yielded += 1
39
+ end
40
+ end
41
+ nil
42
+ rescue UnsupportedError
43
+ # roo reads the sheet again; skip the rows already yielded.
44
+ skip = yielded
45
+ super { |row| skip.zero? ? yield(row) : skip -= 1 }
46
+ ensure
47
+ # Also when the caller stops early, as roo does for max_rows.
48
+ reader&.close
49
+ end
50
+
51
+ def each_cell(row_xml, &)
52
+ return super unless row_xml.is_a?(Native::Row)
53
+
54
+ @calamine_stream_converter ||= Native::Converter.new(Context.new(@shared, hyperlinks(@relationships), true),
55
+ true)
56
+ @calamine_stream_converter.row_cells(row_xml).each(&)
57
+ end
58
+
59
+ private
60
+
61
+ def native?
62
+ @path && Calamine.enabled?
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Roo
4
+ module Calamine
5
+ VERSION = "0.0.1"
6
+ end
7
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "roo"
4
+ require "roo/excelx"
5
+ require_relative "calamine/version"
6
+
7
+ module Roo
8
+ # Reads `.xlsx` and `.xlsm` worksheets for Roo::Excelx with a native
9
+ # extension. Loading this file is all it takes; `Roo::Calamine.enabled =
10
+ # false` or `ROO_CALAMINE=0` switches back to roo's own reader at runtime.
11
+ module Calamine
12
+ # Raised by the native reader for XML it does not reproduce exactly the
13
+ # way roo reads it. Roo::Calamine rescues it and lets roo read the sheet.
14
+ class UnsupportedError < StandardError; end
15
+
16
+ DISABLING_ENV_VALUES = %w[0 false off].freeze
17
+ private_constant :DISABLING_ENV_VALUES
18
+
19
+ @enabled = true
20
+
21
+ class << self
22
+ attr_writer :enabled
23
+
24
+ # Whether the native extension is loaded. It is `false` on Ruby
25
+ # implementations other than CRuby, such as JRuby.
26
+ def available?
27
+ defined?(Native::Reader) ? true : false
28
+ end
29
+
30
+ # Whether the next worksheet read goes through the native reader.
31
+ def enabled?
32
+ @enabled && available? && !DISABLING_ENV_VALUES.include?(ENV.fetch("ROO_CALAMINE", "").downcase)
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ if RUBY_ENGINE == "ruby"
39
+ begin
40
+ require "roo/calamine/#{RUBY_VERSION[/\d+\.\d+/]}/roo_calamine"
41
+ rescue LoadError
42
+ require "roo/calamine/roo_calamine"
43
+ end
44
+ require_relative "calamine/context"
45
+ require_relative "calamine/sheet_doc"
46
+ Roo::Excelx::SheetDoc.prepend(Roo::Calamine::SheetDoc)
47
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: roo-calamine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sebastian Sala
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rb_sys
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 0.9.130
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.9.130
26
+ - !ruby/object:Gem::Dependency
27
+ name: roo
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '4.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '4.0'
40
+ description: Unofficial plugin for roo. Add it to the Gemfile and Roo::Excelx reads
41
+ worksheets through a Rust extension instead of Nokogiri, building the same Roo::Excelx::Cell
42
+ objects. Anything the native reader does not reproduce exactly goes to roo's own
43
+ code. Not affiliated with roo-rb.
44
+ executables: []
45
+ extensions:
46
+ - ext/roo_calamine/extconf.rb
47
+ extra_rdoc_files: []
48
+ files:
49
+ - CHANGELOG.md
50
+ - Cargo.lock
51
+ - Cargo.toml
52
+ - LICENSE
53
+ - README.md
54
+ - ext/roo_calamine/Cargo.toml
55
+ - ext/roo_calamine/extconf.rb
56
+ - ext/roo_calamine/src/convert.rs
57
+ - ext/roo_calamine/src/lib.rs
58
+ - ext/roo_calamine/src/reader.rs
59
+ - lib/roo/calamine.rb
60
+ - lib/roo/calamine/context.rb
61
+ - lib/roo/calamine/sheet_doc.rb
62
+ - lib/roo/calamine/version.rb
63
+ homepage: https://github.com/salasebas/roo-calamine
64
+ licenses:
65
+ - MIT
66
+ metadata:
67
+ homepage_uri: https://github.com/salasebas/roo-calamine
68
+ source_code_uri: https://github.com/salasebas/roo-calamine/tree/v0.0.1
69
+ changelog_uri: https://github.com/salasebas/roo-calamine/blob/v0.0.1/CHANGELOG.md
70
+ bug_tracker_uri: https://github.com/salasebas/roo-calamine/issues
71
+ rubygems_mfa_required: 'true'
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '3.3'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 3.3.11
85
+ requirements: []
86
+ rubygems_version: 3.6.9
87
+ specification_version: 4
88
+ summary: A native reader that makes roo read .xlsx and .xlsm files faster, with the
89
+ same results.
90
+ test_files: []