roo 2.8.3 → 2.10.0
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/.github/workflows/pull-request.yml +15 -0
- data/.github/workflows/ruby.yml +34 -0
- data/CHANGELOG.md +23 -0
- data/Gemfile +1 -0
- data/README.md +15 -3
- data/lib/roo/base.rb +5 -3
- data/lib/roo/csv.rb +10 -4
- data/lib/roo/excelx/cell/number.rb +12 -1
- data/lib/roo/excelx/cell/time.rb +1 -1
- data/lib/roo/excelx/sheet_doc.rb +20 -15
- data/lib/roo/excelx/workbook.rb +1 -0
- data/lib/roo/excelx.rb +13 -7
- data/lib/roo/open_office.rb +5 -2
- data/lib/roo/spreadsheet.rb +8 -2
- data/lib/roo/version.rb +1 -1
- data/roo.gemspec +9 -2
- data/spec/lib/roo/base_spec.rb +8 -0
- data/spec/lib/roo/excelx/cell/time_spec.rb +15 -0
- data/spec/lib/roo/excelx_spec.rb +44 -1
- data/spec/lib/roo/spreadsheet_spec.rb +1 -1
- data/spec/lib/roo/utils_spec.rb +0 -9
- data/test/excelx/cell/test_attr_reader_default.rb +1 -1
- data/test/excelx/cell/test_number.rb +2 -0
- data/test/roo/test_excelx.rb +30 -0
- data/test/test_roo.rb +30 -0
- metadata +28 -12
- data/.travis.yml +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d43d60129a4ccbb82fe7438993aab2d6c0d7818be11c0dc28f96b76bdaedd960
|
4
|
+
data.tar.gz: 2fce78021ad19c23a840dff9647c227a917b6537591df6c1c249c62d2045356b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df1b92404e2835b8265c0dfded00d0fc57502e87cea3fec2798adced13bf0b4cbf04732404371ea534071740cc60f4db2b6f5c110da8006d44ad41fc47b4d728
|
7
|
+
data.tar.gz: b6062d76dafda4cd64870ef100803e61ac8e32f565a5f3a0ffafee7a674e7dfada71e6e243fe7f37545efb7457be99a39a5c035498df85a8dbd02151dffca593
|
@@ -0,0 +1,15 @@
|
|
1
|
+
name: Changelog
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
changelog:
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
steps:
|
11
|
+
- uses: actions/checkout@v2
|
12
|
+
- uses: amoniacou/changelog-enforcer@v1.4.0
|
13
|
+
with:
|
14
|
+
changeLogPath: 'CHANGELOG.md'
|
15
|
+
skipLabel: 'Skip-Changelog'
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: Ruby
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
- master
|
6
|
+
pull_request:
|
7
|
+
branches:
|
8
|
+
- master
|
9
|
+
jobs:
|
10
|
+
build:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
strategy:
|
13
|
+
fail-fast: false
|
14
|
+
matrix:
|
15
|
+
ruby:
|
16
|
+
- '2.7'
|
17
|
+
- '3.0'
|
18
|
+
- '3.1'
|
19
|
+
- ruby-head
|
20
|
+
- jruby-9.3.3.0
|
21
|
+
include:
|
22
|
+
- ruby: ruby-head
|
23
|
+
env:
|
24
|
+
RUBYOPT: '--jit'
|
25
|
+
steps:
|
26
|
+
- uses: actions/checkout@v2
|
27
|
+
- uses: ruby/setup-ruby@v1
|
28
|
+
with:
|
29
|
+
ruby-version: ${{ matrix.ruby }}
|
30
|
+
bundler-cache: true
|
31
|
+
- run: bundle exec rake
|
32
|
+
env:
|
33
|
+
LONG_RUN: true
|
34
|
+
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
## Unreleased
|
2
2
|
|
3
|
+
### Changed/Added
|
4
|
+
|
5
|
+
## [2.10.0] 2023-02-07
|
6
|
+
|
7
|
+
### Changed/Added
|
8
|
+
- Fix gsub! usage for open office documents on a frozen string [581](https://github.com/roo-rb/roo/pull/581)
|
9
|
+
- Add support for boolean values in open office files that were generated via Google Sheets [580](https://github.com/roo-rb/roo/pull/580)
|
10
|
+
- Roo::Base#each_with_pagename returns Enumerator Object [576](https://github.com/roo-rb/roo/pull/576)
|
11
|
+
|
12
|
+
## [2.9.0] 2022-03-19
|
13
|
+
|
14
|
+
### Changed/Added
|
15
|
+
- Ruby 3.x Support [555](https://github.com/roo-rb/roo/pull/555)
|
16
|
+
- Ignore all richdata at 'xl/richData' of XSLX [552](https://github.com/roo-rb/roo/pull/552)
|
17
|
+
- Only copy if cell is present when `expand_merged_ranges: true` [557](https://github.com/roo-rb/roo/pull/557)
|
18
|
+
- Fixes issue where the contents of hidden sheet was returned when parsing visible sheets only. [536](https://github.com/roo-rb/roo/pull/536)
|
19
|
+
- Add formats [525](https://github.com/roo-rb/roo/pull/525)
|
20
|
+
- Fix warnings caused by Ruby 2.7 update [530](https://github.com/roo-rb/roo/pull/530)
|
21
|
+
- Add formats [525](https://github.com/roo-rb/roo/pull/525)
|
22
|
+
|
23
|
+
### Removed
|
24
|
+
- Support for ruby 2.4, 2.5, 2.6(excluded jRuby)
|
25
|
+
|
3
26
|
## [2.8.3] 2020-02-03
|
4
27
|
### Changed/Added
|
5
28
|
- Updated rubyzip version. Now minimal version is 1.3.0 [515](https://github.com/roo-rb/roo/pull/515) - [CVE-2019-16892](https://github.com/rubyzip/rubyzip/pull/403)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -18,7 +18,7 @@ Install as a gem
|
|
18
18
|
Or add it to your Gemfile
|
19
19
|
|
20
20
|
```ruby
|
21
|
-
gem "roo", "~> 2.
|
21
|
+
gem "roo", "~> 2.10.0"
|
22
22
|
```
|
23
23
|
## Usage
|
24
24
|
|
@@ -249,7 +249,7 @@ ods.formula('A', 2)
|
|
249
249
|
csv = Roo::CSV.new("mycsv.csv")
|
250
250
|
```
|
251
251
|
|
252
|
-
Because Roo uses the
|
252
|
+
Because Roo uses the standard CSV library, you can use options available to that library to parse csv files. You can pass options using the ``csv_options`` key.
|
253
253
|
|
254
254
|
For instance, you can load tab-delimited files (``.tsv``), and you can use a particular encoding when opening the file.
|
255
255
|
|
@@ -262,6 +262,18 @@ csv = Roo::CSV.new("mytsv.tsv", csv_options: {col_sep: "\t"})
|
|
262
262
|
csv = Roo::CSV.new("mycsv.csv", csv_options: {encoding: Encoding::ISO_8859_1})
|
263
263
|
```
|
264
264
|
|
265
|
+
You can also open csv files through the Roo::Spreadsheet class (useful if you accept both CSV and Excel types from a user file upload, for example).
|
266
|
+
|
267
|
+
```ruby
|
268
|
+
# Load a spreadsheet from a file path
|
269
|
+
# Roo figures out the right parser based on file extension
|
270
|
+
spreadsheet = Roo::Spreadsheet.open(csv_or_xlsx_file)
|
271
|
+
|
272
|
+
# Load a csv and auto-strip the BOM (byte order mark)
|
273
|
+
# csv files saved from MS Excel typically have the BOM marker at the beginning of the file
|
274
|
+
spreadsheet = Roo::Spreadsheet.open("mycsv.csv", { csv_options: { encoding: 'bom|utf-8' } })
|
275
|
+
```
|
276
|
+
|
265
277
|
## Upgrading from Roo 1.13.x
|
266
278
|
If you use ``.xls`` or Google spreadsheets, you will need to install ``roo-xls`` or ``roo-google`` to continue using that functionality.
|
267
279
|
|
@@ -271,7 +283,7 @@ Roo's public methods have stayed relatively consistent between 1.13.x and 2.0.0,
|
|
271
283
|
|
272
284
|
## Contributing
|
273
285
|
### Features
|
274
|
-
1. Fork it ( https://github.com/
|
286
|
+
1. Fork it ( https://github.com/roo-rb/roo/fork )
|
275
287
|
2. Install it (`bundle install --with local_development`)
|
276
288
|
3. Create your feature branch (`git checkout -b my-new-feature`)
|
277
289
|
4. Commit your changes (`git commit -am 'My new feature'`)
|
data/lib/roo/base.rb
CHANGED
@@ -250,8 +250,10 @@ class Roo::Base
|
|
250
250
|
|
251
251
|
# iterate through all worksheets of a document
|
252
252
|
def each_with_pagename
|
253
|
-
|
254
|
-
|
253
|
+
Enumerator.new do |yielder|
|
254
|
+
sheets.each do |s|
|
255
|
+
yielder << sheet(s, true)
|
256
|
+
end
|
255
257
|
end
|
256
258
|
end
|
257
259
|
|
@@ -544,7 +546,7 @@ class Roo::Base
|
|
544
546
|
tempfilename = File.join(tmpdir, find_basename(uri))
|
545
547
|
begin
|
546
548
|
File.open(tempfilename, "wb") do |file|
|
547
|
-
open(uri, "User-Agent" => "Ruby/#{RUBY_VERSION}") do |net|
|
549
|
+
URI.open(uri, "User-Agent" => "Ruby/#{RUBY_VERSION}") do |net|
|
548
550
|
file.write(net.read)
|
549
551
|
end
|
550
552
|
end
|
data/lib/roo/csv.rb
CHANGED
@@ -90,17 +90,23 @@ module Roo
|
|
90
90
|
def each_row(options, &block)
|
91
91
|
if uri?(filename)
|
92
92
|
each_row_using_tempdir(options, &block)
|
93
|
-
elsif is_stream?(filename_or_stream)
|
94
|
-
::CSV.new(filename_or_stream, options).each(&block)
|
95
93
|
else
|
96
|
-
|
94
|
+
csv_foreach(filename_or_stream, options, &block)
|
97
95
|
end
|
98
96
|
end
|
99
97
|
|
100
98
|
def each_row_using_tempdir(options, &block)
|
101
99
|
::Dir.mktmpdir(Roo::TEMP_PREFIX, ENV["ROO_TMP"]) do |tmpdir|
|
102
100
|
tmp_filename = download_uri(filename, tmpdir)
|
103
|
-
|
101
|
+
csv_foreach(tmp_filename, options, &block)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def csv_foreach(path_or_io, options, &block)
|
106
|
+
if is_stream?(path_or_io)
|
107
|
+
::CSV.new(path_or_io, **options).each(&block)
|
108
|
+
else
|
109
|
+
::CSV.foreach(path_or_io, **options, &block)
|
104
110
|
end
|
105
111
|
end
|
106
112
|
|
@@ -48,7 +48,7 @@ module Roo
|
|
48
48
|
when /^(0+)$/ then "%0#{$1.size}d"
|
49
49
|
when /^0\.(0+)$/ then "%.#{$1.size}f"
|
50
50
|
when '#,##0' then number_format('%.0f')
|
51
|
-
when
|
51
|
+
when /^#,##0.(0+)$/ then number_format("%.#{$1.size}f")
|
52
52
|
when '0%'
|
53
53
|
proc do |number|
|
54
54
|
Kernel.format('%d%%', number.to_f * 100)
|
@@ -64,7 +64,18 @@ module Roo
|
|
64
64
|
when '#,##0.00;[Red](#,##0.00)' then number_format('%.2f', '[Red](%.2f)')
|
65
65
|
# FIXME: not quite sure what the format should look like in this case.
|
66
66
|
when '##0.0E+0' then '%.1E'
|
67
|
+
when "_-* #,##0.00\\ _€_-;\\-* #,##0.00\\ _€_-;_-* \"-\"??\\ _€_-;_-@_-" then number_format('%.2f', '-%.2f')
|
67
68
|
when '@' then proc { |number| number }
|
69
|
+
when /^(?:_\()?"([^"]*)"(?:\* )?([^_]+)/
|
70
|
+
proc do |number|
|
71
|
+
formatted_number = generate_formatter($2).call(number)
|
72
|
+
"#{$1}#{formatted_number}"
|
73
|
+
end
|
74
|
+
when /^_[- \(]\[\$([^-]*)[^#@]+([^_]+)/
|
75
|
+
proc do |number|
|
76
|
+
formatted_number = generate_formatter($2).call(number)
|
77
|
+
"#{$1}#{formatted_number}"
|
78
|
+
end
|
68
79
|
else
|
69
80
|
raise "Unknown format: #{format.inspect}"
|
70
81
|
end
|
data/lib/roo/excelx/cell/time.rb
CHANGED
@@ -13,7 +13,7 @@ module Roo
|
|
13
13
|
super
|
14
14
|
@format = excelx_type.last
|
15
15
|
@datetime = create_datetime(base_date, value)
|
16
|
-
@value = link ? Roo::Link.new(link, value) : (value.to_f * 86_400).to_i
|
16
|
+
@value = link ? Roo::Link.new(link, value) : (value.to_f * 86_400).round.to_i
|
17
17
|
end
|
18
18
|
|
19
19
|
def formatted_value
|
data/lib/roo/excelx/sheet_doc.rb
CHANGED
@@ -101,12 +101,7 @@ module Roo
|
|
101
101
|
cell_xml_children.each do |cell|
|
102
102
|
case cell.name
|
103
103
|
when 'is'
|
104
|
-
content =
|
105
|
-
cell.children.each do |inline_str|
|
106
|
-
if inline_str.name == 't'
|
107
|
-
content << inline_str.content
|
108
|
-
end
|
109
|
-
end
|
104
|
+
content = cell.search('t').map(&:content).join
|
110
105
|
unless content.empty?
|
111
106
|
return Excelx::Cell.cell_class(:string).new(content, formula, style, hyperlink, coordinate)
|
112
107
|
end
|
@@ -197,11 +192,12 @@ module Roo
|
|
197
192
|
# Extract merged ranges from xml
|
198
193
|
merges = {}
|
199
194
|
doc.xpath('/worksheet/mergeCells/mergeCell').each do |mergecell_xml|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
195
|
+
src, dst = mergecell_xml["ref"].split(/:/).map { |ref| ::Roo::Utils.ref_to_key(ref) }
|
196
|
+
next unless cells[src]
|
197
|
+
for row in src[0]..dst[0] do
|
198
|
+
for col in src[1]..dst[1] do
|
199
|
+
next if row == src[0] && col == src[1]
|
200
|
+
merges[[row, col]] = src
|
205
201
|
end
|
206
202
|
end
|
207
203
|
end
|
@@ -215,10 +211,19 @@ module Roo
|
|
215
211
|
extracted_cells = {}
|
216
212
|
empty_cell = @options[:empty_cell]
|
217
213
|
|
218
|
-
doc.xpath('/worksheet/sheetData/row
|
219
|
-
|
220
|
-
|
221
|
-
|
214
|
+
doc.xpath('/worksheet/sheetData/row').each.with_index(1) do |row_xml, ycoord|
|
215
|
+
row_xml.xpath('c').each.with_index(1) do |cell_xml, xcoord|
|
216
|
+
r = cell_xml['r']
|
217
|
+
coordinate =
|
218
|
+
if r.nil?
|
219
|
+
::Roo::Excelx::Coordinate.new(ycoord, xcoord)
|
220
|
+
else
|
221
|
+
::Roo::Utils.extract_coordinate(r)
|
222
|
+
end
|
223
|
+
|
224
|
+
cell = cell_from_xml(cell_xml, hyperlinks(relationships)[coordinate], coordinate, empty_cell)
|
225
|
+
extracted_cells[coordinate] = cell if cell
|
226
|
+
end
|
222
227
|
end
|
223
228
|
|
224
229
|
expand_merged_ranges(extracted_cells) if @options[:expand_merged_ranges]
|
data/lib/roo/excelx/workbook.rb
CHANGED
@@ -32,6 +32,7 @@ module Roo
|
|
32
32
|
doc.xpath('//definedName').each_with_object({}) do |defined_name, hash|
|
33
33
|
# "Sheet1!$C$5"
|
34
34
|
sheet, coordinates = defined_name.text.split('!$', 2)
|
35
|
+
next unless coordinates
|
35
36
|
col, row = coordinates.split('$')
|
36
37
|
name = defined_name['name']
|
37
38
|
hash[name] = Label.new(name, sheet, row, col)
|
data/lib/roo/excelx.rb
CHANGED
@@ -60,15 +60,16 @@ module Roo
|
|
60
60
|
@filename = local_filename(filename_or_stream, @tmpdir, packed)
|
61
61
|
process_zipfile(@filename || filename_or_stream)
|
62
62
|
|
63
|
-
@sheet_names =
|
64
|
-
unless options[:only_visible_sheets] && sheet['state'] == 'hidden'
|
65
|
-
sheet['name']
|
66
|
-
end
|
67
|
-
end.compact
|
63
|
+
@sheet_names = []
|
68
64
|
@sheets = []
|
69
65
|
@sheets_by_name = {}
|
70
|
-
|
71
|
-
|
66
|
+
|
67
|
+
workbook.sheets.each_with_index do |sheet, index|
|
68
|
+
next if options[:only_visible_sheets] && sheet['state'] == 'hidden'
|
69
|
+
|
70
|
+
sheet_name = sheet['name']
|
71
|
+
@sheet_names << sheet_name
|
72
|
+
@sheets_by_name[sheet_name] = @sheets[index] = Sheet.new(sheet_name, @shared, index, sheet_options)
|
72
73
|
end
|
73
74
|
|
74
75
|
if cell_max
|
@@ -428,6 +429,11 @@ module Roo
|
|
428
429
|
entries.each do |entry|
|
429
430
|
path =
|
430
431
|
case entry.name.downcase
|
432
|
+
when /richdata/
|
433
|
+
# FIXME: Ignore richData as parsing is not implemented yet and can cause
|
434
|
+
# Zip::DestinationFileExistsError when including a second "styles.xml" entry
|
435
|
+
# see http://schemas.microsoft.com/office/spreadsheetml/2017/richdata2
|
436
|
+
nil
|
431
437
|
when /sharedstrings.xml$/
|
432
438
|
"#{@tmpdir}/roo_sharedStrings.xml"
|
433
439
|
when /styles.xml$/
|
data/lib/roo/open_office.rb
CHANGED
@@ -423,7 +423,10 @@ module Roo
|
|
423
423
|
@style[sheet][key] = style_name
|
424
424
|
case @cell_type[sheet][key]
|
425
425
|
when :float
|
426
|
-
|
426
|
+
value = (table_cell.attributes['value'].to_s.include?(".") || table_cell.children.first.text.include?(".")) ? v.to_f : v.to_i
|
427
|
+
value = 'true' if formula == '=TRUE()'
|
428
|
+
value = 'false' if formula == '=FALSE()'
|
429
|
+
@cell[sheet][key] = value
|
427
430
|
when :percentage
|
428
431
|
@cell[sheet][key] = v.to_f
|
429
432
|
when :string
|
@@ -517,7 +520,7 @@ module Roo
|
|
517
520
|
str_v += child.content #.text
|
518
521
|
end
|
519
522
|
end
|
520
|
-
str_v.gsub
|
523
|
+
str_v = str_v.gsub(/'/, "'") # special case not supported by unescapeHTML
|
521
524
|
str_v = CGI.unescapeHTML(str_v)
|
522
525
|
end # == 'p'
|
523
526
|
end
|
data/lib/roo/spreadsheet.rb
CHANGED
@@ -24,8 +24,14 @@ module Roo
|
|
24
24
|
options[:file_warning] = :ignore
|
25
25
|
extension.tr('.', '').downcase.to_sym
|
26
26
|
else
|
27
|
-
|
28
|
-
|
27
|
+
parsed_path =
|
28
|
+
if path =~ /\A#{::URI::DEFAULT_PARSER.make_regexp}\z/
|
29
|
+
# path is 7th match
|
30
|
+
Regexp.last_match[7]
|
31
|
+
else
|
32
|
+
path
|
33
|
+
end
|
34
|
+
::File.extname(parsed_path).tr('.', '').downcase.to_sym
|
29
35
|
end
|
30
36
|
end
|
31
37
|
end
|
data/lib/roo/version.rb
CHANGED
data/roo.gemspec
CHANGED
@@ -17,12 +17,19 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.files.reject! { |fn| fn.include?('test/files') }
|
18
18
|
spec.require_paths = ['lib']
|
19
19
|
|
20
|
-
|
20
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
21
|
+
spec.required_ruby_version = ">= 2.6.0"
|
22
|
+
else
|
23
|
+
spec.required_ruby_version = ">= 2.7.0"
|
24
|
+
end
|
21
25
|
|
22
26
|
spec.add_dependency 'nokogiri', '~> 1'
|
23
27
|
spec.add_dependency 'rubyzip', '>= 1.3.0', '< 3.0.0'
|
24
28
|
|
25
|
-
spec.add_development_dependency 'rake'
|
29
|
+
spec.add_development_dependency 'rake'
|
26
30
|
spec.add_development_dependency 'minitest', '~> 5.4', '>= 5.4.3'
|
27
31
|
spec.add_development_dependency 'rack', '~> 1.6', '< 2.0.0'
|
32
|
+
if RUBY_VERSION >= '3.0.0'
|
33
|
+
spec.add_development_dependency 'matrix'
|
34
|
+
end
|
28
35
|
end
|
data/spec/lib/roo/base_spec.rb
CHANGED
@@ -182,6 +182,14 @@ describe Roo::Base do
|
|
182
182
|
end
|
183
183
|
end
|
184
184
|
|
185
|
+
describe '#each_with_pagename' do
|
186
|
+
it 'should return an enumerator with all the rows' do
|
187
|
+
each_with_pagename = spreadsheet.each_with_pagename
|
188
|
+
expect(each_with_pagename).to be_a(Enumerator)
|
189
|
+
expect(each_with_pagename.to_a.last).to eq([spreadsheet.default_sheet, spreadsheet])
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
185
193
|
describe '#each' do
|
186
194
|
it 'should return an enumerator with all the rows' do
|
187
195
|
each = spreadsheet.each
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Roo::Excelx::Cell::Time do
|
4
|
+
it "should set the cell value to the correct number of seconds" do
|
5
|
+
value = 0.05513888888888888 # '1:19:24'
|
6
|
+
excelx_type = [:numeric_or_formula, "h:mm:ss"]
|
7
|
+
base_timestamp = Date.new(1899, 12, 30).to_time.to_i
|
8
|
+
time_cell = Roo::Excelx::Cell::Time.new(value, nil, excelx_type, 1, nil, base_timestamp, nil)
|
9
|
+
expect(time_cell.value).to eq(1*60*60 + 19*60 + 24) # '1:19:24' in seconds
|
10
|
+
# use case from https://github.com/roo-rb/roo/issues/310
|
11
|
+
value = 0.523761574074074 # '12:34:13' in seconds
|
12
|
+
time_cell = Roo::Excelx::Cell::Time.new(value, nil, excelx_type, 1, nil, base_timestamp, nil)
|
13
|
+
expect(time_cell.value).to eq(12*60*60 + 34*60 + 13) # 12:34:13 in seconds
|
14
|
+
end
|
15
|
+
end
|
data/spec/lib/roo/excelx_spec.rb
CHANGED
@@ -86,6 +86,14 @@ describe Roo::Excelx do
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
+
describe 'for a workbook with hidden sheets' do
|
90
|
+
let(:path) { 'test/files/hidden_sheets.xlsx' }
|
91
|
+
|
92
|
+
it 'returns the cell contents from the visible sheet' do
|
93
|
+
expect(Roo::Excelx.new(path, only_visible_sheets: true).cell('A', 1)).to eq "visible sheet 1"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
89
97
|
describe '#parse' do
|
90
98
|
let(:path) { 'test/files/numeric-link.xlsx' }
|
91
99
|
|
@@ -318,6 +326,30 @@ describe Roo::Excelx do
|
|
318
326
|
expect(subject.formatted_value(4, 1)).to eq '05010'
|
319
327
|
end
|
320
328
|
end
|
329
|
+
|
330
|
+
context 'contains US currency' do
|
331
|
+
let(:path) { 'test/files/currency-us.xlsx' }
|
332
|
+
|
333
|
+
it 'returns a zero-padded number' do
|
334
|
+
expect(subject.formatted_value(4, 1)).to eq '$20.51'
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
context 'contains euro currency' do
|
339
|
+
let(:path) { 'test/files/currency-euro.xlsx' }
|
340
|
+
|
341
|
+
it 'returns a zero-padded number' do
|
342
|
+
expect(subject.formatted_value(4, 1)).to eq '€20.51'
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
context 'contains uk currency' do
|
347
|
+
let(:path) { 'test/files/currency-uk.xlsx' }
|
348
|
+
|
349
|
+
it 'returns a zero-padded number' do
|
350
|
+
expect(subject.formatted_value(4, 1)).to eq '£20.51'
|
351
|
+
end
|
352
|
+
end
|
321
353
|
end
|
322
354
|
|
323
355
|
describe '#row' do
|
@@ -601,6 +633,17 @@ describe Roo::Excelx do
|
|
601
633
|
end
|
602
634
|
end
|
603
635
|
|
636
|
+
describe 'opening a file with filters' do
|
637
|
+
let(:path) { 'test/files/wrong_coordinates.xlsx' }
|
638
|
+
subject(:xlsx) do
|
639
|
+
Roo::Spreadsheet.open(path)
|
640
|
+
end
|
641
|
+
|
642
|
+
it 'should properly extract defined_names' do
|
643
|
+
expect(subject.sheet(0).workbook.defined_names.length).to eq(1)
|
644
|
+
end
|
645
|
+
end
|
646
|
+
|
604
647
|
describe 'images' do
|
605
648
|
let(:path) { 'test/files/images.xlsx' }
|
606
649
|
|
@@ -653,4 +696,4 @@ describe 'Roo::Excelx with options set' do
|
|
653
696
|
end
|
654
697
|
end
|
655
698
|
end
|
656
|
-
end
|
699
|
+
end
|
@@ -25,7 +25,7 @@ describe Roo::Spreadsheet do
|
|
25
25
|
let(:filename) { tempfile.path }
|
26
26
|
|
27
27
|
it 'loads the proper type' do
|
28
|
-
expect(Roo::CSV).to receive(:new).with(filename, file_warning: :ignore).and_call_original
|
28
|
+
expect(Roo::CSV).to receive(:new).with(filename, {file_warning: :ignore}).and_call_original
|
29
29
|
expect(Roo::Spreadsheet.open(tempfile, extension: :csv)).to be_a(Roo::CSV)
|
30
30
|
end
|
31
31
|
end
|
data/spec/lib/roo/utils_spec.rb
CHANGED
@@ -43,15 +43,6 @@ RSpec.describe ::Roo::Utils do
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
context '.split_coordinate' do
|
47
|
-
it "returns the expected result" do
|
48
|
-
expect(described_class.split_coordinate('A1')).to eq [1, 1]
|
49
|
-
expect(described_class.split_coordinate('B2')).to eq [2, 2]
|
50
|
-
expect(described_class.split_coordinate('R2')).to eq [2, 18]
|
51
|
-
expect(described_class.split_coordinate('AR31')).to eq [31, 18 + 26]
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
46
|
context '.extract_coordinate' do
|
56
47
|
it "returns the expected result" do
|
57
48
|
expect(described_class.extract_coordinate('A1')).to eq [1, 1]
|
@@ -66,6 +66,7 @@ class TestRooExcelxCellNumber < Minitest::Test
|
|
66
66
|
['0.000000000', '1042.000000000'],
|
67
67
|
['#,##0', '1,042'],
|
68
68
|
['#,##0.00', '1,042.00'],
|
69
|
+
['#,##0.000', '1,042.000'],
|
69
70
|
['0%', '104200%'],
|
70
71
|
['0.00%', '104200.00%'],
|
71
72
|
['0.00E+00', '1.04E+03'],
|
@@ -74,6 +75,7 @@ class TestRooExcelxCellNumber < Minitest::Test
|
|
74
75
|
['#,##0.00;(#,##0.00)', '1,042.00'],
|
75
76
|
['#,##0.00;[Red](#,##0.00)', '1,042.00'],
|
76
77
|
['##0.0E+0', '1.0E+03'],
|
78
|
+
["_-* #,##0.00\\ _€_-;\\-* #,##0.00\\ _€_-;_-* \"-\"??\\ _€_-;_-@_-", '1,042.00'],
|
77
79
|
['@', '1042']
|
78
80
|
].each do |style_format, result|
|
79
81
|
cell = Roo::Excelx::Cell::Number.new '1042', nil, [style_format], nil, nil, nil
|
data/test/roo/test_excelx.rb
CHANGED
@@ -133,6 +133,20 @@ class TestRworkbookExcelx < Minitest::Test
|
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
136
|
+
def test_expand_merged_range_doesnt_insert_nil_values
|
137
|
+
options = { expand_merged_ranges: true }
|
138
|
+
xlsx = roo_class.new(File.join(TESTDIR, "merged_ranges.xlsx"), options)
|
139
|
+
|
140
|
+
refute_includes xlsx.sheet_for(0).cells.values, nil, "`nil` was copied into the cells hash from an empty merged range"
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_expand_merged_range_doesnt_raise_issue_506
|
144
|
+
# Issue 506 sent an example test.xlsx file that would raise an error upon parsing.
|
145
|
+
xl = Roo::Spreadsheet.open(File.join(TESTDIR, "expand_merged_ranges_issue_506.xlsx"), expand_merged_ranges: true)
|
146
|
+
data = xl.parse(one: /one/i, two: /two/i, clean: true)
|
147
|
+
assert_equal [{:one=>"John", :two=>"Johnson"}, {:one=>"Sam", :two=>nil}, {:one=>"Dave", :two=>nil}], data
|
148
|
+
end
|
149
|
+
|
136
150
|
def test_noexpand_merged_range
|
137
151
|
xlsx = roo_class.new(File.join(TESTDIR, "merged_ranges.xlsx"))
|
138
152
|
|
@@ -320,6 +334,22 @@ class TestRworkbookExcelx < Minitest::Test
|
|
320
334
|
end
|
321
335
|
end
|
322
336
|
|
337
|
+
def test_parsing_xlsx_with_richtext
|
338
|
+
xlsx = roo_class.new(File.join(TESTDIR, "richtext_example.xlsx"))
|
339
|
+
|
340
|
+
assert_equal "Example richtext", xlsx.cell("a", 1)
|
341
|
+
assert_equal "Example richtext", xlsx.cell("b", 1)
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_implicit_coordinates
|
345
|
+
xlsx = roo_class.new(File.join(TESTDIR, 'implicit_coordinates.xlsx'))
|
346
|
+
|
347
|
+
assert_equal 'Test', xlsx.cell('a', 1)
|
348
|
+
assert_equal 'A2', xlsx.cell('a', 2)
|
349
|
+
assert_equal 'B2', xlsx.cell(2, 2)
|
350
|
+
assert_equal 'C2', xlsx.cell('c', 2)
|
351
|
+
end
|
352
|
+
|
323
353
|
def roo_class
|
324
354
|
Roo::Excelx
|
325
355
|
end
|
data/test/test_roo.rb
CHANGED
@@ -274,6 +274,24 @@ class TestRoo < Minitest::Test
|
|
274
274
|
end
|
275
275
|
end
|
276
276
|
|
277
|
+
def test_cell_boolean_from_google_sheets
|
278
|
+
with_each_spreadsheet(:name=>'boolean-from-google-sheets', :format=>[:openoffice, :excelx]) do |oo|
|
279
|
+
if oo.class == Roo::Excelx
|
280
|
+
assert_equal true, oo.cell(1, 1), "failure in #{oo.class}"
|
281
|
+
assert_equal false, oo.cell(2, 1), "failure in #{oo.class}"
|
282
|
+
|
283
|
+
cell = oo.sheet_for(oo.default_sheet).cells[[1, 1,]]
|
284
|
+
assert_equal 'TRUE', cell.formatted_value
|
285
|
+
|
286
|
+
cell = oo.sheet_for(oo.default_sheet).cells[[2, 1,]]
|
287
|
+
assert_equal 'FALSE', cell.formatted_value
|
288
|
+
else
|
289
|
+
assert_equal "true", oo.cell(1,1), "failure in #{oo.class}"
|
290
|
+
assert_equal "false", oo.cell(2,1), "failure in #{oo.class}"
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
277
295
|
def test_cell_multiline
|
278
296
|
with_each_spreadsheet(:name=>'paragraph', :format=>[:openoffice, :excelx]) do |oo|
|
279
297
|
assert_equal "This is a test\nof a multiline\nCell", oo.cell(1,1)
|
@@ -282,6 +300,18 @@ class TestRoo < Minitest::Test
|
|
282
300
|
end
|
283
301
|
end
|
284
302
|
|
303
|
+
def test_apostrophe_replacement
|
304
|
+
with_each_spreadsheet(:name=>'apostrophe', :format=>[:openoffice]) do |oo|
|
305
|
+
assert_equal "'", oo.cell(1,1)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def test_frozen_string_usage
|
310
|
+
with_each_spreadsheet(:name=>'frozen_string', :format=>[:openoffice]) do |oo|
|
311
|
+
assert_equal "", oo.cell(1,1)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
285
315
|
def test_row_whitespace
|
286
316
|
# auf dieses Dokument habe ich keinen Zugriff TODO:
|
287
317
|
# TODO: No access to document whitespace?
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Preymesser
|
@@ -10,10 +10,10 @@ authors:
|
|
10
10
|
- Oleksandr Simonov
|
11
11
|
- Steven Daniels
|
12
12
|
- Anmol Chopra
|
13
|
-
autorequire:
|
13
|
+
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date:
|
16
|
+
date: 2023-02-07 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: nokogiri
|
@@ -53,16 +53,16 @@ dependencies:
|
|
53
53
|
name: rake
|
54
54
|
requirement: !ruby/object:Gem::Requirement
|
55
55
|
requirements:
|
56
|
-
- - "
|
56
|
+
- - ">="
|
57
57
|
- !ruby/object:Gem::Version
|
58
|
-
version: '
|
58
|
+
version: '0'
|
59
59
|
type: :development
|
60
60
|
prerelease: false
|
61
61
|
version_requirements: !ruby/object:Gem::Requirement
|
62
62
|
requirements:
|
63
|
-
- - "
|
63
|
+
- - ">="
|
64
64
|
- !ruby/object:Gem::Version
|
65
|
-
version: '
|
65
|
+
version: '0'
|
66
66
|
- !ruby/object:Gem::Dependency
|
67
67
|
name: minitest
|
68
68
|
requirement: !ruby/object:Gem::Requirement
|
@@ -103,6 +103,20 @@ dependencies:
|
|
103
103
|
- - "<"
|
104
104
|
- !ruby/object:Gem::Version
|
105
105
|
version: 2.0.0
|
106
|
+
- !ruby/object:Gem::Dependency
|
107
|
+
name: matrix
|
108
|
+
requirement: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
type: :development
|
114
|
+
prerelease: false
|
115
|
+
version_requirements: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
106
120
|
description: |-
|
107
121
|
Roo can access the contents of various spreadsheet files. It can handle
|
108
122
|
* OpenOffice
|
@@ -119,10 +133,11 @@ files:
|
|
119
133
|
- ".codeclimate.yml"
|
120
134
|
- ".github/issue_template.md"
|
121
135
|
- ".github/pull_request_template.md"
|
136
|
+
- ".github/workflows/pull-request.yml"
|
137
|
+
- ".github/workflows/ruby.yml"
|
122
138
|
- ".gitignore"
|
123
139
|
- ".rubocop.yml"
|
124
140
|
- ".simplecov"
|
125
|
-
- ".travis.yml"
|
126
141
|
- CHANGELOG.md
|
127
142
|
- Gemfile
|
128
143
|
- Guardfile
|
@@ -181,6 +196,7 @@ files:
|
|
181
196
|
- spec/helpers.rb
|
182
197
|
- spec/lib/roo/base_spec.rb
|
183
198
|
- spec/lib/roo/csv_spec.rb
|
199
|
+
- spec/lib/roo/excelx/cell/time_spec.rb
|
184
200
|
- spec/lib/roo/excelx/format_spec.rb
|
185
201
|
- spec/lib/roo/excelx/relationships_spec.rb
|
186
202
|
- spec/lib/roo/excelx/sheet_doc_spec.rb
|
@@ -225,7 +241,7 @@ homepage: https://github.com/roo-rb/roo
|
|
225
241
|
licenses:
|
226
242
|
- MIT
|
227
243
|
metadata: {}
|
228
|
-
post_install_message:
|
244
|
+
post_install_message:
|
229
245
|
rdoc_options: []
|
230
246
|
require_paths:
|
231
247
|
- lib
|
@@ -233,15 +249,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
233
249
|
requirements:
|
234
250
|
- - ">="
|
235
251
|
- !ruby/object:Gem::Version
|
236
|
-
version: 2.
|
252
|
+
version: 2.7.0
|
237
253
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
238
254
|
requirements:
|
239
255
|
- - ">="
|
240
256
|
- !ruby/object:Gem::Version
|
241
257
|
version: '0'
|
242
258
|
requirements: []
|
243
|
-
rubygems_version: 3.
|
244
|
-
signing_key:
|
259
|
+
rubygems_version: 3.4.2
|
260
|
+
signing_key:
|
245
261
|
specification_version: 4
|
246
262
|
summary: Roo can access the contents of various spreadsheet files.
|
247
263
|
test_files: []
|
data/.travis.yml
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
rvm:
|
3
|
-
- 2.3
|
4
|
-
- 2.4
|
5
|
-
- 2.5
|
6
|
-
- 2.6
|
7
|
-
- ruby-head
|
8
|
-
- jruby-9.1.6.0
|
9
|
-
env:
|
10
|
-
- LONG_RUN=true
|
11
|
-
matrix:
|
12
|
-
include:
|
13
|
-
- rvm: 2.6
|
14
|
-
env: RUBYOPT=--jit LONG_RUN=true
|
15
|
-
- rvm: ruby-head
|
16
|
-
env: RUBYOPT=--jit LONG_RUN=true
|
17
|
-
allow_failures:
|
18
|
-
- rvm: ruby-head
|
19
|
-
- rvm: ruby-head
|
20
|
-
env: RUBYOPT=--jit LONG_RUN=true
|
21
|
-
- rvm: jruby-9.1.6.0
|
22
|
-
bundler_args: --without local_development
|