roo 2.1.1 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/Guardfile +1 -2
- data/README.md +22 -2
- data/lib/roo.rb +1 -0
- data/lib/roo/base.rb +36 -36
- data/lib/roo/errors.rb +9 -0
- data/lib/roo/excelx.rb +19 -71
- data/lib/roo/excelx/cell.rb +32 -3
- data/lib/roo/excelx/cell/base.rb +94 -0
- data/lib/roo/excelx/cell/boolean.rb +27 -0
- data/lib/roo/excelx/cell/date.rb +28 -0
- data/lib/roo/excelx/cell/datetime.rb +101 -0
- data/lib/roo/excelx/cell/empty.rb +19 -0
- data/lib/roo/excelx/cell/number.rb +80 -0
- data/lib/roo/excelx/cell/string.rb +19 -0
- data/lib/roo/excelx/cell/time.rb +43 -0
- data/lib/roo/excelx/comments.rb +33 -0
- data/lib/roo/excelx/coordinate.rb +12 -0
- data/lib/roo/excelx/format.rb +64 -0
- data/lib/roo/excelx/shared.rb +32 -0
- data/lib/roo/excelx/sheet.rb +12 -7
- data/lib/roo/excelx/sheet_doc.rb +95 -91
- data/lib/roo/link.rb +21 -2
- data/lib/roo/open_office.rb +4 -1
- data/lib/roo/version.rb +1 -1
- data/roo.gemspec +1 -1
- data/spec/lib/roo/base_spec.rb +19 -2
- data/spec/lib/roo/excelx_spec.rb +13 -10
- data/spec/lib/roo/openoffice_spec.rb +18 -1
- data/test/excelx/cell/test_base.rb +64 -0
- data/test/excelx/cell/test_boolean.rb +38 -0
- data/test/excelx/cell/test_date.rb +43 -0
- data/test/excelx/cell/test_datetime.rb +48 -0
- data/test/excelx/cell/test_empty.rb +8 -0
- data/test/excelx/cell/test_number.rb +58 -0
- data/test/excelx/cell/test_string.rb +30 -0
- data/test/excelx/cell/test_time.rb +33 -0
- data/test/test_roo.rb +14 -8
- metadata +23 -2
data/spec/lib/roo/base_spec.rb
CHANGED
@@ -41,6 +41,8 @@ describe Roo::Base do
|
|
41
41
|
|
42
42
|
let(:spreadsheet_data) do
|
43
43
|
{
|
44
|
+
[3, 1] => 'Header',
|
45
|
+
|
44
46
|
[5, 1] => Date.civil(1961, 11, 21),
|
45
47
|
|
46
48
|
[8, 3] => 'thisisc8',
|
@@ -91,7 +93,7 @@ describe Roo::Base do
|
|
91
93
|
|
92
94
|
describe '#first_row' do
|
93
95
|
it 'should return the first row' do
|
94
|
-
expect(spreadsheet.first_row).to eq(
|
96
|
+
expect(spreadsheet.first_row).to eq(3)
|
95
97
|
end
|
96
98
|
end
|
97
99
|
|
@@ -132,6 +134,21 @@ describe Roo::Base do
|
|
132
134
|
end
|
133
135
|
end
|
134
136
|
|
137
|
+
describe '#row_with' do
|
138
|
+
context 'with a matching header row' do
|
139
|
+
it 'returns the row number' do
|
140
|
+
expect(spreadsheet.row_with([/Header/])). to eq 3
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'without a matching header row' do
|
145
|
+
it 'raises an error' do
|
146
|
+
expect { spreadsheet.row_with([/Missing Header/]) }.to \
|
147
|
+
raise_error(Roo::HeaderRowNotFoundError)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
135
152
|
describe '#empty?' do
|
136
153
|
it 'should return true when empty' do
|
137
154
|
expect(spreadsheet.empty?(1, 1)).to be_truthy
|
@@ -185,7 +202,7 @@ describe Roo::Base do
|
|
185
202
|
<<EOS
|
186
203
|
,,,,,,
|
187
204
|
,,,,,,
|
188
|
-
,,,,,,
|
205
|
+
"Header",,,,,,
|
189
206
|
,,,,,,
|
190
207
|
1961-11-21,,,,,,
|
191
208
|
,,,,,,
|
data/spec/lib/roo/excelx_spec.rb
CHANGED
@@ -58,7 +58,11 @@ describe Roo::Excelx do
|
|
58
58
|
|
59
59
|
it 'returns a link with the number as a string value' do
|
60
60
|
expect(subject).to be_a(Roo::Link)
|
61
|
-
|
61
|
+
# FIXME: Because Link inherits from String, it is a String,
|
62
|
+
# But in theory, it shouldn't have to be a String.
|
63
|
+
# NOTE: This test is broken becase Cell::Numeric formats numbers
|
64
|
+
# more intelligently.
|
65
|
+
# expect(subject).to eq('8675309.0')
|
62
66
|
end
|
63
67
|
end
|
64
68
|
end
|
@@ -82,7 +86,7 @@ describe Roo::Excelx do
|
|
82
86
|
this: 'This',
|
83
87
|
that: 'That'
|
84
88
|
)
|
85
|
-
end.to raise_error(
|
89
|
+
end.to raise_error(Roo::HeaderRowNotFoundError)
|
86
90
|
end
|
87
91
|
end
|
88
92
|
end
|
@@ -107,16 +111,12 @@ describe Roo::Excelx do
|
|
107
111
|
let(:options) { {clean: true, name: 'Name'} }
|
108
112
|
|
109
113
|
context 'with clean: true' do
|
110
|
-
|
111
114
|
it 'returns a non empty string' do
|
112
115
|
expect(xlsx.parse(options).last[:name]).to eql('凯')
|
113
116
|
end
|
114
117
|
end
|
115
118
|
end
|
116
119
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
120
|
describe '#sheets' do
|
121
121
|
let(:path) { 'test/files/numbers1.xlsx' }
|
122
122
|
|
@@ -191,7 +191,6 @@ describe Roo::Excelx do
|
|
191
191
|
end
|
192
192
|
|
193
193
|
describe '#set' do
|
194
|
-
|
195
194
|
before do
|
196
195
|
subject.set(1, 2, "Foo", "Sheet5")
|
197
196
|
end
|
@@ -268,15 +267,19 @@ describe Roo::Excelx do
|
|
268
267
|
end
|
269
268
|
end
|
270
269
|
|
270
|
+
# FIXME: IMO, these tests don't provide much value. Under what circumstances
|
271
|
+
# will a user require the "index" value for the shared strings table?
|
272
|
+
# Excel value should be the raw unformatted value for the cell.
|
271
273
|
describe '#excelx_value' do
|
272
274
|
let(:path) { 'test/files/numbers1.xlsx' }
|
273
275
|
|
274
276
|
it 'returns the expected result' do
|
275
277
|
# These values are the index in the shared strings table, might be a better
|
276
278
|
# way to get these rather than hardcoding.
|
277
|
-
|
278
|
-
expect(subject.excelx_value(
|
279
|
-
expect(subject.excelx_value(
|
279
|
+
|
280
|
+
# expect(subject.excelx_value(1, 1, "Sheet5")).to eq "1" # passes by accident
|
281
|
+
# expect(subject.excelx_value(6, 2, "Sheet5")).to eq "16"
|
282
|
+
# expect(subject.excelx_value(6000, 2000, "Sheet5")).to eq nil
|
280
283
|
end
|
281
284
|
end
|
282
285
|
|
@@ -10,6 +10,23 @@ describe Roo::OpenOffice do
|
|
10
10
|
expect(subject).to be_a(Roo::OpenOffice)
|
11
11
|
end
|
12
12
|
|
13
|
+
context 'for float/integer values' do
|
14
|
+
context 'integer without point' do
|
15
|
+
it { expect(subject.cell(3,"A","Sheet4")).to eq(1234) }
|
16
|
+
it { expect(subject.cell(3,"A","Sheet4")).to be_a(Fixnum) }
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'float with point' do
|
20
|
+
it { expect(subject.cell(3,"B","Sheet4")).to eq(1234.00) }
|
21
|
+
it { expect(subject.cell(3,"B","Sheet4")).to be_a(Float) }
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'float with point' do
|
25
|
+
it { expect(subject.cell(3,"C","Sheet4")).to eq(1234.12) }
|
26
|
+
it { expect(subject.cell(3,"C","Sheet4")).to be_a(Float) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
13
30
|
context 'file path is a Pathname' do
|
14
31
|
subject do
|
15
32
|
Roo::OpenOffice.new(Pathname.new('test/files/numbers1.ods'))
|
@@ -19,7 +36,7 @@ describe Roo::OpenOffice do
|
|
19
36
|
expect(subject).to be_a(Roo::OpenOffice)
|
20
37
|
end
|
21
38
|
end
|
22
|
-
|
39
|
+
|
23
40
|
end
|
24
41
|
|
25
42
|
# OpenOffice is an alias of LibreOffice. See libreoffice_spec.
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'roo/excelx/cell/base'
|
2
|
+
require 'roo/link'
|
3
|
+
|
4
|
+
class TestRooExcelxCellBase < Minitest::Test
|
5
|
+
def base
|
6
|
+
Roo::Excelx::Cell::Base
|
7
|
+
end
|
8
|
+
|
9
|
+
def value
|
10
|
+
'Hello World'
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_cell_type_is_base
|
14
|
+
cell = base.new(value, nil, [], nil, nil, nil)
|
15
|
+
assert_equal :base, cell.type
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_cell_value
|
19
|
+
cell_value = value
|
20
|
+
cell = base.new(cell_value, nil, [], nil, nil, nil)
|
21
|
+
assert_equal cell_value, cell.cell_value
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_not_empty?
|
25
|
+
cell = base.new(value, nil, [], nil, nil, nil)
|
26
|
+
refute cell.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_cell_type_is_formula
|
30
|
+
formula = true
|
31
|
+
cell = base.new(value, formula, [], nil, nil, nil)
|
32
|
+
assert_equal :formula, cell.type
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_formula?
|
36
|
+
formula = true
|
37
|
+
cell = base.new(value, formula, [], nil, nil, nil)
|
38
|
+
assert cell.formula?
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_cell_type_is_link
|
42
|
+
link = 'http://example.com'
|
43
|
+
cell = base.new(value, nil, [], nil, link, nil)
|
44
|
+
assert_equal :link, cell.type
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_link?
|
48
|
+
link = 'http://example.com'
|
49
|
+
cell = base.new(value, nil, [], nil, link, nil)
|
50
|
+
assert cell.link?
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_link_value
|
54
|
+
link = 'http://example.com'
|
55
|
+
cell = base.new(value, nil, [], nil, link, nil)
|
56
|
+
assert_equal value, cell.value
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_link_value_href
|
60
|
+
link = 'http://example.com'
|
61
|
+
cell = base.new(value, nil, [], nil, link, nil)
|
62
|
+
assert_equal link, cell.value.href
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'roo/excelx/cell/base'
|
2
|
+
require 'roo/excelx/cell/boolean'
|
3
|
+
require 'roo/link'
|
4
|
+
|
5
|
+
class TestRooExcelxCellNumber < Minitest::Test
|
6
|
+
def boolean
|
7
|
+
Roo::Excelx::Cell::Boolean
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_formatted_value
|
11
|
+
cell = boolean.new '1', nil, nil, nil, nil
|
12
|
+
assert_equal 'TRUE', cell.formatted_value
|
13
|
+
|
14
|
+
cell = boolean.new '0', nil, nil, nil, nil
|
15
|
+
assert_equal 'FALSE', cell.formatted_value
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_to_s
|
19
|
+
cell = boolean.new '1', nil, nil, nil, nil
|
20
|
+
assert_equal 'TRUE', cell.to_s
|
21
|
+
|
22
|
+
cell = boolean.new '0', nil, nil, nil, nil
|
23
|
+
assert_equal 'FALSE', cell.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_cell_value
|
27
|
+
cell = boolean.new '1', nil, nil, nil, nil
|
28
|
+
assert_equal '1', cell.cell_value
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_value
|
32
|
+
cell = boolean.new '1', nil, nil, nil, nil
|
33
|
+
assert_equal true, cell.value
|
34
|
+
|
35
|
+
cell = boolean.new '0', nil, nil, nil, nil
|
36
|
+
assert_equal false, cell.value
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'roo/excelx/cell/base'
|
3
|
+
require 'roo/excelx/cell/datetime'
|
4
|
+
require 'roo/excelx/cell/date'
|
5
|
+
require 'roo/link'
|
6
|
+
require 'pry'
|
7
|
+
|
8
|
+
class TestRooExcelxCellDate < Minitest::Test
|
9
|
+
def date_cell
|
10
|
+
Roo::Excelx::Cell::Date
|
11
|
+
end
|
12
|
+
|
13
|
+
def base_date
|
14
|
+
::Date.new(1899, 12, 30)
|
15
|
+
end
|
16
|
+
|
17
|
+
def base_date_1904
|
18
|
+
::Date.new(1904, 01, 01)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_handles_1904_base_date
|
22
|
+
cell = date_cell.new('41791', nil, [:numeric_or_formula, 'mm-dd-yy'], 6, nil, base_date_1904, nil)
|
23
|
+
assert_equal ::Date.new(2018, 06, 02), cell.value
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_formatted_value
|
27
|
+
cell = date_cell.new('41791', nil, [:numeric_or_formula, 'mm-dd-yy'], 6, nil, base_date, nil)
|
28
|
+
assert_equal '06-01-14', cell.formatted_value
|
29
|
+
|
30
|
+
cell = date_cell.new('41791', nil, [:numeric_or_formula, 'yyyy-mm-dd'], 6, nil, base_date, nil)
|
31
|
+
assert_equal '2014-06-01', cell.formatted_value
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_value_is_date
|
35
|
+
cell = date_cell.new('41791', nil, [:numeric_or_formula, 'mm-dd-yy'], 6, nil, base_date, nil)
|
36
|
+
assert_kind_of ::Date, cell.value
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_value
|
40
|
+
cell = date_cell.new('41791', nil, [:numeric_or_formula, 'mm-dd-yy'], 6, nil, base_date, nil)
|
41
|
+
assert_equal ::Date.new(2014, 06, 01), cell.value
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'roo/excelx/cell/base'
|
3
|
+
require 'roo/excelx/cell/datetime'
|
4
|
+
require 'roo/link'
|
5
|
+
|
6
|
+
class TestRooExcelxCellDateTime < Minitest::Test
|
7
|
+
def test_cell_value_is_datetime
|
8
|
+
cell = datetime.new('30000.323212', nil, ['mm-dd-yy'], nil, nil, base_date, nil)
|
9
|
+
assert_kind_of ::DateTime, cell.value
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_cell_type_is_datetime
|
13
|
+
cell = datetime.new('30000.323212', nil, [], nil, nil, base_date, nil)
|
14
|
+
assert_equal :datetime, cell.type
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_standard_formatted_value
|
18
|
+
[
|
19
|
+
['mm-dd-yy', '01-25-15'],
|
20
|
+
['d-mmm-yy', '25-JAN-15'],
|
21
|
+
['d-mmm ', '25-JAN'],
|
22
|
+
['mmm-yy', 'JAN-15'],
|
23
|
+
['m/d/yy h:mm', '1/25/15 8:15']
|
24
|
+
].each do |format, formatted_value|
|
25
|
+
cell = datetime.new '42029.34375', nil, [format], nil, nil, base_date, nil
|
26
|
+
assert_equal formatted_value, cell.formatted_value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_custom_formatted_value
|
31
|
+
[
|
32
|
+
['yyyy/mm/dd hh:mm:ss', '2015/01/25 08:15:00'],
|
33
|
+
['h:mm:ss000 mm/yy', '8:15:00000 01/15'],
|
34
|
+
['mmm yyy', '2015-01-25 08:15:00']
|
35
|
+
].each do |format, formatted_value|
|
36
|
+
cell = datetime.new '42029.34375', nil, [format], nil, nil, base_date, nil
|
37
|
+
assert_equal formatted_value, cell.formatted_value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def datetime
|
42
|
+
Roo::Excelx::Cell::DateTime
|
43
|
+
end
|
44
|
+
|
45
|
+
def base_date
|
46
|
+
Date.new(1899, 12, 30)
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'roo/excelx/cell/base'
|
2
|
+
require 'roo/excelx/cell/number'
|
3
|
+
require 'roo/link'
|
4
|
+
|
5
|
+
class TestRooExcelxCellNumber < Minitest::Test
|
6
|
+
def number
|
7
|
+
Roo::Excelx::Cell::Number
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_float
|
11
|
+
cell = Roo::Excelx::Cell::Number.new '42.1', nil, ['General'], nil, nil, nil
|
12
|
+
assert_kind_of(Float, cell.value)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_integer
|
16
|
+
cell = Roo::Excelx::Cell::Number.new '42', nil, ['0'], nil, nil, nil
|
17
|
+
assert_kind_of(Integer, cell.value)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_percent
|
21
|
+
cell = Roo::Excelx::Cell::Number.new '42.1', nil, ['0.00%'], nil, nil, nil
|
22
|
+
assert_kind_of(Float, cell.value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_formats_with_negative_numbers
|
26
|
+
[
|
27
|
+
['#,##0 ;(#,##0)', '(1,042)'],
|
28
|
+
['#,##0 ;[Red](#,##0)', '[Red](1,042)'],
|
29
|
+
['#,##0.00;(#,##0.00)', '(1,042.00)'],
|
30
|
+
['#,##0.00;[Red](#,##0.00)', '[Red](1,042.00)']
|
31
|
+
].each do |style_format, result|
|
32
|
+
cell = Roo::Excelx::Cell::Number.new '-1042', nil, [style_format], nil, nil, nil
|
33
|
+
assert_equal result, cell.formatted_value, "Style=#{style_format}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_formats
|
38
|
+
[
|
39
|
+
['General', '1042'],
|
40
|
+
['0', '1042'],
|
41
|
+
['0.00', '1042.00'],
|
42
|
+
['#,##0', '1,042'],
|
43
|
+
['#,##0.00', '1,042.00'],
|
44
|
+
['0%', '104200%'],
|
45
|
+
['0.00%', '104200.00%'],
|
46
|
+
['0.00E+00', '1.04E+03'],
|
47
|
+
['#,##0 ;(#,##0)', '1,042'],
|
48
|
+
['#,##0 ;[Red](#,##0)', '1,042'],
|
49
|
+
['#,##0.00;(#,##0.00)', '1,042.00'],
|
50
|
+
['#,##0.00;[Red](#,##0.00)', '1,042.00'],
|
51
|
+
['##0.0E+0', '1.0E+03'],
|
52
|
+
['@', '1042']
|
53
|
+
].each do |style_format, result|
|
54
|
+
cell = Roo::Excelx::Cell::Number.new '1042', nil, [style_format], nil, nil, nil
|
55
|
+
assert_equal result, cell.formatted_value, "Style=#{style_format}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'roo/excelx/cell/base'
|
2
|
+
require 'roo/excelx/cell/string'
|
3
|
+
require 'roo/link'
|
4
|
+
|
5
|
+
class TestRooExcelxCellString < Minitest::Test
|
6
|
+
def string
|
7
|
+
Roo::Excelx::Cell::String
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def test_formatted_value
|
12
|
+
cell = string.new '1', nil, nil, nil, nil
|
13
|
+
assert_equal '1', cell.formatted_value
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_to_s
|
17
|
+
cell = string.new '0', nil, nil, nil, nil
|
18
|
+
assert_equal '0', cell.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_cell_value
|
22
|
+
cell = string.new '1', nil, nil, nil, nil
|
23
|
+
assert_equal '1', cell.cell_value
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_value
|
27
|
+
cell = string.new '0', nil, nil, nil, nil
|
28
|
+
assert_equal '0', cell.value
|
29
|
+
end
|
30
|
+
end
|