roo-xls 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +5 -1
- data/Gemfile +3 -1
- data/README.md +5 -3
- data/lib/roo/xls/excel.rb +46 -42
- data/lib/roo/xls/excel_2003_xml.rb +4 -3
- data/lib/roo/xls/version.rb +1 -1
- data/roo-xls.gemspec +6 -1
- data/test/test_roo_excel.rb +10 -1
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72a5eeec41696350e22d685b1337489727f9211c
|
4
|
+
data.tar.gz: d149d0621aec472b1b64ef3b817ef167d7cfd785
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4c1534cb3cbe004cc8bfe510c88f9565adbf4e9e607c42961a49827dbc579ce06b630716eb9804d04076afb0ee79b5269a02b333eb0a096a97b4bbbfa417e4d
|
7
|
+
data.tar.gz: faf978fc060d3bf38ff0011bc8ff239ffa9067835ad2cee1fa9f7c09aeb64a181136c7365e70ddb7c5015e9ac24e076cd7473414e6d8fcec60feb5cb12dd1458
|
data/.travis.yml
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 2.0
|
3
|
+
- 2.0
|
4
4
|
- 2.1
|
5
|
+
- 2.2
|
6
|
+
- 2.3
|
7
|
+
- 2.4.0
|
5
8
|
- ruby-head
|
6
9
|
- jruby-19mode # JRuby in 1.9 mode
|
7
10
|
- rbx-2
|
8
11
|
matrix:
|
9
12
|
allow_failures:
|
10
13
|
- rvm: ruby-head
|
14
|
+
- rvm: rbx-2
|
11
15
|
bundler_args: --without local_development
|
data/Gemfile
CHANGED
@@ -4,11 +4,13 @@ source 'https://rubygems.org'
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
if ENV['TRAVIS']
|
7
|
-
gem 'roo', '>= 2.0.0beta1',
|
7
|
+
gem 'roo', '>= 2.0.0beta1', git: 'https://github.com/roo-rb/roo.git'
|
8
8
|
else
|
9
9
|
gem 'roo', '>= 2.0.0beta1', path: ::File.expand_path('../../roo', __FILE__)
|
10
10
|
end
|
11
11
|
|
12
|
+
gem 'activesupport', '~> 4.2.0' if RUBY_VERSION < '2.2'
|
13
|
+
|
12
14
|
group :test do
|
13
15
|
# additional testing libs
|
14
16
|
gem 'webmock'
|
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
# Roo::Xls
|
1
|
+
# Roo::Xls
|
2
|
+
|
3
|
+
[![Build Status](https://img.shields.io/travis/roo-rb/roo-xls.svg?style=flat-square)](https://travis-ci.org/roo-rb/roo-xls) [![Code Climate](https://img.shields.io/codeclimate/github/roo-rb/roo-xls.svg?style=flat-square)](https://codeclimate.com/github/roo-rb/roo-xls) [![Coverage Status](https://img.shields.io/coveralls/roo-rb/roo-xls.svg?style=flat-square)](https://coveralls.io/r/roo-rb/roo-xls) [![Gem Version](https://img.shields.io/gem/v/roo-xls.svg?style=flat-square)](https://rubygems.org/gems/roo-xls)
|
2
4
|
|
3
5
|
This library extends Roo to add support for handling class Excel files, including:
|
4
6
|
|
@@ -10,7 +12,7 @@ of a formula but not the formula itself.
|
|
10
12
|
|
11
13
|
## License
|
12
14
|
|
13
|
-
While Roo and Roo::Xls are licensed under the MIT / Expat license, please note that the
|
15
|
+
While Roo and Roo::Xls are licensed under the MIT / Expat license, please note that the `spreadsheet` gem [is released under](https://github.com/zdavatz/spreadsheet/blob/master/LICENSE.txt) the GPLv3 license. Please be aware that the author of the `spreadsheet` gem [claims you need a commercial license](http://spreadsheet.ch/2014/10/24/using-ruby-spreadsheet-on-heroku-with-dynos/) to use it as part of a public-facing, closed-source service, an interpretation [at odds with the FSF's intent and interpretation of the license](http://www.gnu.org/licenses/gpl-faq.html#UnreleasedMods).
|
14
16
|
|
15
17
|
## Installation
|
16
18
|
|
@@ -34,7 +36,7 @@ TODO: Write usage instructions here
|
|
34
36
|
|
35
37
|
## Contributing
|
36
38
|
|
37
|
-
1. Fork it ( https://github.com/
|
39
|
+
1. Fork it ( https://github.com/roo-rb/roo-xls/fork )
|
38
40
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
39
41
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
40
42
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/lib/roo/xls/excel.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'roo/xls/version'
|
2
2
|
require 'roo/base'
|
3
3
|
require 'spreadsheet'
|
4
|
+
require 'tmpdir'
|
4
5
|
|
5
6
|
module Roo
|
6
7
|
# Class for handling Excel-Spreadsheets
|
7
8
|
class Excel < Roo::Base
|
8
|
-
FORMULAS_MESSAGE = 'the spreadsheet gem does not support
|
9
|
+
FORMULAS_MESSAGE = 'the spreadsheet gem does not support formulas, so roo can not.'
|
9
10
|
CHARGUESS =
|
10
11
|
begin
|
11
12
|
require 'charguess'
|
@@ -23,18 +24,25 @@ module Roo
|
|
23
24
|
file_warning = options[:file_warning] || :error
|
24
25
|
mode = options[:mode] || 'rb+'
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
if is_stream?(filename)
|
28
|
+
@workbook = ::Spreadsheet.open(filename, mode)
|
29
|
+
else
|
30
|
+
file_type_check(filename, '.xls', 'an Excel', file_warning, packed)
|
31
|
+
Dir.mktmpdir do |tmpdir|
|
32
|
+
filename = download_uri(filename, tmpdir) if uri?(filename)
|
33
|
+
if filename.is_a?(::String) && filename[0, 7] == 'stream:'
|
34
|
+
filename = open_from_stream(filename[7..-1], tmpdir)
|
35
|
+
end
|
36
|
+
filename = unzip(filename, tmpdir) if packed == :zip
|
31
37
|
|
32
|
-
|
33
|
-
|
34
|
-
|
38
|
+
@filename = filename
|
39
|
+
unless File.file?(@filename)
|
40
|
+
raise IOError, "file #{@filename} does not exist"
|
41
|
+
end
|
42
|
+
@workbook = ::Spreadsheet.open(filename, mode)
|
35
43
|
end
|
36
|
-
@workbook = ::Spreadsheet.open(filename, mode)
|
37
44
|
end
|
45
|
+
|
38
46
|
super(filename, options)
|
39
47
|
@formula = {}
|
40
48
|
@fonts = {}
|
@@ -57,7 +65,7 @@ module Roo
|
|
57
65
|
|
58
66
|
# this method lets you find the worksheet with the most data
|
59
67
|
def longest_sheet
|
60
|
-
sheet(worksheets.inject do|m, o|
|
68
|
+
sheet(worksheets.inject do |m, o|
|
61
69
|
o.row_count > m.row_count ? o : m
|
62
70
|
end.name)
|
63
71
|
end
|
@@ -67,20 +75,16 @@ module Roo
|
|
67
75
|
validate_sheet!(sheet)
|
68
76
|
|
69
77
|
read_cells(sheet)
|
70
|
-
|
78
|
+
raise 'should be read' unless @cells_read[sheet]
|
71
79
|
row, col = normalize(row, col)
|
72
80
|
if celltype(row, col, sheet) == :date
|
73
81
|
yyyy, mm, dd = @cell[sheet][[row, col]].split('-')
|
74
82
|
return Date.new(yyyy.to_i, mm.to_i, dd.to_i)
|
75
83
|
end
|
76
84
|
if celltype(row, col, sheet) == :string
|
77
|
-
|
85
|
+
platform_specific_encoding(@cell[sheet][[row, col]])
|
78
86
|
else
|
79
|
-
|
80
|
-
return @cell[sheet][[row, col]]
|
81
|
-
else
|
82
|
-
return nil
|
83
|
-
end
|
87
|
+
@cell[sheet] && @cell[sheet][[row, col]]
|
84
88
|
end
|
85
89
|
end
|
86
90
|
|
@@ -109,13 +113,13 @@ module Roo
|
|
109
113
|
|
110
114
|
# returns NO formula in excel spreadsheets
|
111
115
|
def formula(_row, _col, _sheet = nil)
|
112
|
-
|
116
|
+
raise NotImplementedError, FORMULAS_MESSAGE
|
113
117
|
end
|
114
118
|
alias_method :formula?, :formula
|
115
119
|
|
116
120
|
# returns NO formulas in excel spreadsheets
|
117
121
|
def formulas(_sheet = nil)
|
118
|
-
|
122
|
+
raise NotImplementedError, FORMULAS_MESSAGE
|
119
123
|
end
|
120
124
|
|
121
125
|
# Given a cell, return the cell's font
|
@@ -136,18 +140,18 @@ module Roo
|
|
136
140
|
|
137
141
|
# converts name of a sheet to index (0,1,2,..)
|
138
142
|
def sheet_no(name)
|
139
|
-
return name - 1 if name.is_a?(
|
143
|
+
return name - 1 if name.is_a?(Integer)
|
140
144
|
i = 0
|
141
145
|
worksheets.each do |worksheet|
|
142
146
|
return i if name == normalize_string(worksheet.name)
|
143
147
|
i += 1
|
144
148
|
end
|
145
|
-
|
149
|
+
raise StandardError, "sheet '#{name}' not found"
|
146
150
|
end
|
147
151
|
|
148
152
|
def normalize_string(value)
|
149
153
|
value = every_second_null?(value) ? remove_every_second_null(value) : value
|
150
|
-
if CHARGUESS && encoding = CharGuess.guess(value)
|
154
|
+
if CHARGUESS && (encoding = CharGuess.guess(value))
|
151
155
|
encoding.encode Encoding::UTF_8
|
152
156
|
else
|
153
157
|
platform_specific_encoding(value)
|
@@ -164,9 +168,7 @@ module Roo
|
|
164
168
|
else
|
165
169
|
value
|
166
170
|
end
|
167
|
-
if every_second_null?(result)
|
168
|
-
result = remove_every_second_null(result)
|
169
|
-
end
|
171
|
+
result = remove_every_second_null(result) if every_second_null?(result)
|
170
172
|
result
|
171
173
|
end
|
172
174
|
|
@@ -198,8 +200,8 @@ module Roo
|
|
198
200
|
@cell_type[sheet] = {} unless @cell_type[sheet]
|
199
201
|
@cell_type[sheet][key] = value_type
|
200
202
|
@formula[sheet] = {} unless @formula[sheet]
|
201
|
-
@formula[sheet][key] = formula
|
202
|
-
@cell[sheet]
|
203
|
+
@formula[sheet][key] = formula if formula
|
204
|
+
@cell[sheet] = {} unless @cell[sheet]
|
203
205
|
@fonts[sheet] = {} unless @fonts[sheet]
|
204
206
|
@fonts[sheet][key] = font
|
205
207
|
|
@@ -250,7 +252,7 @@ module Roo
|
|
250
252
|
worksheet.each(0) do |row|
|
251
253
|
(0..row.size).each do |cell_index|
|
252
254
|
cell = row.at(cell_index)
|
253
|
-
next if cell.nil?
|
255
|
+
next if cell.nil? # skip empty cells
|
254
256
|
next if cell.class == ::Spreadsheet::Formula && cell.value.nil? # skip empty formula cells
|
255
257
|
value_type, v =
|
256
258
|
if date_or_time?(row, cell_index)
|
@@ -299,17 +301,18 @@ module Roo
|
|
299
301
|
f = cell * 24.0 * 60.0 * 60.0
|
300
302
|
secs = f.round
|
301
303
|
h = (secs / 3600.0).floor
|
302
|
-
secs
|
304
|
+
secs -= 3600 * h
|
303
305
|
m = (secs / 60.0).floor
|
304
|
-
secs
|
306
|
+
secs -= 60 * m
|
305
307
|
s = secs
|
306
308
|
value = h * 3600 + m * 60 + s
|
307
309
|
else
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
310
|
+
datetime =
|
311
|
+
if row.at(idx).class == ::Spreadsheet::Formula
|
312
|
+
row.send(:_datetime, cell)
|
313
|
+
else
|
314
|
+
row.datetime(idx)
|
315
|
+
end
|
313
316
|
if datetime.hour != 0 ||
|
314
317
|
datetime.min != 0 ||
|
315
318
|
datetime.sec != 0
|
@@ -317,11 +320,12 @@ module Roo
|
|
317
320
|
value = datetime
|
318
321
|
else
|
319
322
|
value_type = :date
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
323
|
+
value =
|
324
|
+
if row.at(idx).class == ::Spreadsheet::Formula
|
325
|
+
row.send(:_date, cell)
|
326
|
+
else
|
327
|
+
row.date(idx)
|
328
|
+
end
|
325
329
|
value = sprintf('%04d-%02d-%02d', value.year, value.month, value.day)
|
326
330
|
end
|
327
331
|
end
|
@@ -333,7 +337,7 @@ module Roo
|
|
333
337
|
def read_cell(row, idx)
|
334
338
|
cell = read_cell_content(row, idx)
|
335
339
|
case cell
|
336
|
-
when Float, Integer
|
340
|
+
when Float, Integer
|
337
341
|
value_type = :float
|
338
342
|
value = cell.to_f
|
339
343
|
when ::Spreadsheet::Link
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'date'
|
2
2
|
require 'base64'
|
3
3
|
require 'nokogiri'
|
4
|
+
require 'tmpdir'
|
4
5
|
|
5
6
|
class Roo::Excel2003XML < Roo::Base
|
6
7
|
# initialization and opening of a spreadsheet file
|
@@ -9,14 +10,14 @@ class Roo::Excel2003XML < Roo::Base
|
|
9
10
|
packed = options[:packed]
|
10
11
|
file_warning = options[:file_warning] || :error
|
11
12
|
|
12
|
-
|
13
|
+
Dir.mktmpdir do |tmpdir|
|
13
14
|
filename = download_uri(filename, tmpdir) if uri?(filename)
|
14
15
|
filename = unzip(filename, tmpdir) if packed == :zip
|
15
16
|
|
16
17
|
file_type_check(filename, '.xml', 'an Excel 2003 XML', file_warning)
|
17
18
|
@filename = filename
|
18
19
|
unless File.file?(@filename)
|
19
|
-
|
20
|
+
raise IOError, "file #{@filename} does not exist"
|
20
21
|
end
|
21
22
|
@doc = ::Roo::Utils.load_xml(@filename)
|
22
23
|
end
|
@@ -240,7 +241,7 @@ class Roo::Excel2003XML < Roo::Base
|
|
240
241
|
end
|
241
242
|
end
|
242
243
|
unless sheet_found
|
243
|
-
|
244
|
+
raise RangeError, "Unable to find sheet #{sheet} for reading"
|
244
245
|
end
|
245
246
|
@cells_read[sheet] = true
|
246
247
|
end
|
data/lib/roo/xls/version.rb
CHANGED
data/roo-xls.gemspec
CHANGED
@@ -19,9 +19,14 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency "roo", ">= 2.0.0beta1", "< 3"
|
22
|
-
spec.add_dependency "nokogiri"
|
23
22
|
spec.add_dependency "spreadsheet", "> 0.9.0"
|
24
23
|
|
24
|
+
if RUBY_VERSION >= '2.1'
|
25
|
+
spec.add_dependency "nokogiri"
|
26
|
+
else
|
27
|
+
spec.add_dependency "nokogiri", "~> 1.6.0"
|
28
|
+
end
|
29
|
+
|
25
30
|
spec.add_development_dependency "bundler", ">= 1.7"
|
26
31
|
spec.add_development_dependency "rake", ">= 10.0"
|
27
32
|
end
|
data/test/test_roo_excel.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# -- encoding : utf-8 --
|
2
2
|
require 'test_helper'
|
3
|
+
require 'stringio'
|
3
4
|
|
4
5
|
class TestRooExcel < MiniTest::Test
|
5
6
|
def with_spreadsheet(name)
|
@@ -1034,7 +1035,7 @@ Sheet 3:
|
|
1034
1035
|
i += 1
|
1035
1036
|
end
|
1036
1037
|
if letter == '' || number == 0
|
1037
|
-
|
1038
|
+
raise ArgumentError
|
1038
1039
|
end
|
1039
1040
|
[letter, number]
|
1040
1041
|
end
|
@@ -1090,4 +1091,12 @@ Sheet 3:
|
|
1090
1091
|
# assert_equal 'ist "e" im Nenner von H(s)', excel.cell('b', 5)
|
1091
1092
|
# end
|
1092
1093
|
# end
|
1094
|
+
|
1095
|
+
def test_excel_via_stringio
|
1096
|
+
io = StringIO.new(
|
1097
|
+
File.read(File.join(TESTDIR, 'simple_spreadsheet.xls')))
|
1098
|
+
spreadsheet = ::Roo::Spreadsheet.open(io, extension: '.xls')
|
1099
|
+
spreadsheet.default_sheet = spreadsheet.sheets.first
|
1100
|
+
assert_equal 'Task 1', spreadsheet.cell('f', 4)
|
1101
|
+
end
|
1093
1102
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roo-xls
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Preymesser
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2017-05-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: roo
|
@@ -33,33 +33,33 @@ dependencies:
|
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '3'
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
|
-
name:
|
36
|
+
name: spreadsheet
|
37
37
|
requirement: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - "
|
39
|
+
- - ">"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
41
|
+
version: 0.9.0
|
42
42
|
type: :runtime
|
43
43
|
prerelease: false
|
44
44
|
version_requirements: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - "
|
46
|
+
- - ">"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version:
|
48
|
+
version: 0.9.0
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
|
-
name:
|
50
|
+
name: nokogiri
|
51
51
|
requirement: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- - "
|
53
|
+
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: 0
|
55
|
+
version: '0'
|
56
56
|
type: :runtime
|
57
57
|
prerelease: false
|
58
58
|
version_requirements: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
|
-
- - "
|
60
|
+
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: 0
|
62
|
+
version: '0'
|
63
63
|
- !ruby/object:Gem::Dependency
|
64
64
|
name: bundler
|
65
65
|
requirement: !ruby/object:Gem::Requirement
|
@@ -204,7 +204,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
204
|
version: '0'
|
205
205
|
requirements: []
|
206
206
|
rubyforge_project:
|
207
|
-
rubygems_version: 2.
|
207
|
+
rubygems_version: 2.5.1
|
208
208
|
signing_key:
|
209
209
|
specification_version: 4
|
210
210
|
summary: Roo::Excel can access the contents of classic xls files.
|