roo 2.1.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +4 -7
- data/lib/roo/base.rb +74 -77
- data/lib/roo/excelx/shared_strings.rb +10 -0
- data/lib/roo/spreadsheet.rb +2 -0
- data/lib/roo/version.rb +1 -1
- data/spec/helpers.rb +5 -0
- data/spec/lib/roo/base_spec.rb +212 -0
- data/spec/lib/roo/excelx_spec.rb +7 -0
- data/spec/spec_helper.rb +6 -1
- data/test/test_helper.rb +0 -4
- metadata +9 -8
- data/test/test_generic_spreadsheet.rb +0 -237
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53d37d09a786f9536fd5bb00c7cacf9888c8b032
|
4
|
+
data.tar.gz: 284974b328b26668c58e3b952a12b8777439037f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b0e6d58d52600710fc5feb49e7483fc81e4bca65fa9013a3fa1004f5526107392b02f982ae981676544e301056a0246b4b85e38d3959565174c247ce49695a9
|
7
|
+
data.tar.gz: 5c3beb6580bece8aa730d1f29b6316889ebb7ce5a7003d8f654edcb1c9800a9f939021fd0d88749489ffdee6ebf496739664e5fede43aeb0067a2a16ad46f2f5
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## [2.1.1] - 2015-08-02
|
2
|
+
### Fixed invalid new lines with _x000D_ character[#231](https://github.com/roo-rb/roo/pull/231)
|
3
|
+
### Fixed missing URI issue. [#245](https://github.com/roo-rb/roo/pull/245)
|
4
|
+
|
1
5
|
## [2.1.0] - 2015-07-18
|
2
6
|
### Added
|
3
7
|
- Added support for Excel 2007 `xlsm` files. [#232](https://github.com/roo-rb/roo/pull/232)
|
data/README.md
CHANGED
@@ -3,14 +3,11 @@
|
|
3
3
|
[![Build Status](https://img.shields.io/travis/roo-rb/roo.svg?style=flat-square)](https://travis-ci.org/roo-rb/roo) [![Code Climate](https://img.shields.io/codeclimate/github/roo-rb/roo.svg?style=flat-square)](https://codeclimate.com/github/roo-rb/roo) [![Coverage Status](https://img.shields.io/coveralls/roo-rb/roo.svg?style=flat-square)](https://coveralls.io/r/roo-rb/roo) [![Gem Version](https://img.shields.io/gem/v/roo.svg?style=flat-square)](https://rubygems.org/gems/roo)
|
4
4
|
|
5
5
|
Roo implements read access for all common spreadsheet types. It can handle:
|
6
|
-
|
7
|
-
*
|
8
|
-
* OpenOffice / LibreOffice
|
6
|
+
* Excel 2007 - 2013 formats (xlsx, xlsm)
|
7
|
+
* LibreOffice / OpenOffice.org formats (ods)
|
9
8
|
* CSV
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
In addition, the [roo-xls](https://github.com/roo-rb/roo-xls) and [roo-google](https://github.com/roo-rb/roo-google) gems exist to extend Roo to support reading classic Excel formats (i.e. `.xls` and ``Excel2003XML``) and read/write access for Google spreadsheets.
|
9
|
+
* Excel 97, Excel 2002 XML, and Excel 2003 XML formats when using the [roo-xls](https://github.com/roo-rb/roo-xls) gem (xls, xml)
|
10
|
+
* Google spreadsheets with read/write access when using [roo-google](https://github.com/roo-rb/roo-google)
|
14
11
|
|
15
12
|
## Installation
|
16
13
|
|
data/lib/roo/base.rb
CHANGED
@@ -91,7 +91,7 @@ class Roo::Base
|
|
91
91
|
first_column = [first_column, key.last.to_i].min
|
92
92
|
last_column = [last_column, key.last.to_i].max
|
93
93
|
end if @cell[sheet]
|
94
|
-
{first_row: first_row, first_column: first_column, last_row: last_row, last_column: last_column}
|
94
|
+
{ first_row: first_row, first_column: first_column, last_row: last_row, last_column: last_column }
|
95
95
|
end
|
96
96
|
|
97
97
|
%w(first_row last_row first_column last_column).each do |key|
|
@@ -117,22 +117,23 @@ class Roo::Base
|
|
117
117
|
result = "--- \n"
|
118
118
|
from_row.upto(to_row) do |row|
|
119
119
|
from_column.upto(to_column) do |col|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
result << " value: #{value} \n"
|
120
|
+
next if empty?(row, col, sheet)
|
121
|
+
|
122
|
+
result << "cell_#{row}_#{col}: \n"
|
123
|
+
prefix.each do|k, v|
|
124
|
+
result << " #{k}: #{v} \n"
|
125
|
+
end
|
126
|
+
result << " row: #{row} \n"
|
127
|
+
result << " col: #{col} \n"
|
128
|
+
result << " celltype: #{celltype(row, col, sheet)} \n"
|
129
|
+
value = cell(row, col, sheet)
|
130
|
+
if celltype(row, col, sheet) == :time
|
131
|
+
value = integer_to_timestring(value)
|
133
132
|
end
|
133
|
+
result << " value: #{value} \n"
|
134
134
|
end
|
135
135
|
end
|
136
|
+
|
136
137
|
result
|
137
138
|
end
|
138
139
|
|
@@ -170,7 +171,7 @@ class Roo::Base
|
|
170
171
|
end
|
171
172
|
|
172
173
|
def inspect
|
173
|
-
"<##{
|
174
|
+
"<##{self.class}:#{object_id.to_s(8)} #{instance_variables.join(' ')}>"
|
174
175
|
end
|
175
176
|
|
176
177
|
# find a row either by row number or a condition
|
@@ -217,7 +218,7 @@ class Roo::Base
|
|
217
218
|
row, col = normalize(row, col)
|
218
219
|
cell_type = cell_type_by_value(value)
|
219
220
|
set_value(row, col, value, sheet)
|
220
|
-
set_type(row, col, cell_type
|
221
|
+
set_type(row, col, cell_type, sheet)
|
221
222
|
end
|
222
223
|
|
223
224
|
def cell_type_by_value(value)
|
@@ -225,7 +226,7 @@ class Roo::Base
|
|
225
226
|
when Fixnum then :float
|
226
227
|
when String, Float then :string
|
227
228
|
else
|
228
|
-
|
229
|
+
fail ArgumentError, "Type for #{value} not set"
|
229
230
|
end
|
230
231
|
end
|
231
232
|
|
@@ -256,13 +257,13 @@ class Roo::Base
|
|
256
257
|
sheets.each do|sheet|
|
257
258
|
self.default_sheet = sheet
|
258
259
|
result << 'Sheet ' + n.to_s + ":\n"
|
259
|
-
|
260
|
-
result << ' - empty -'
|
261
|
-
else
|
260
|
+
if first_row
|
262
261
|
result << " First row: #{first_row}\n"
|
263
262
|
result << " Last row: #{last_row}\n"
|
264
263
|
result << " First column: #{::Roo::Utils.number_to_letter(first_column)}\n"
|
265
264
|
result << " Last column: #{::Roo::Utils.number_to_letter(last_column)}"
|
265
|
+
else
|
266
|
+
result << ' - empty -'
|
266
267
|
end
|
267
268
|
result << "\n" if sheet != sheets.last
|
268
269
|
n += 1
|
@@ -282,12 +283,12 @@ class Roo::Base
|
|
282
283
|
# sonst gibt es Fehler bei leeren Blaettern
|
283
284
|
first_row.upto(last_row) do |row|
|
284
285
|
first_column.upto(last_column) do |col|
|
285
|
-
|
286
|
-
|
286
|
+
next if empty?(row, col)
|
287
|
+
|
288
|
+
x.cell(cell(row, col),
|
287
289
|
row: row,
|
288
290
|
column: col,
|
289
291
|
type: celltype(row, col))
|
290
|
-
end
|
291
292
|
end
|
292
293
|
end
|
293
294
|
end
|
@@ -318,7 +319,7 @@ class Roo::Base
|
|
318
319
|
# access different worksheets by calling spreadsheet.sheet(1)
|
319
320
|
# or spreadsheet.sheet('SHEETNAME')
|
320
321
|
def sheet(index, name = false)
|
321
|
-
self.default_sheet = String
|
322
|
+
self.default_sheet = index.is_a?(::String) ? index : sheets[index]
|
322
323
|
name ? [default_sheet, self] : self
|
323
324
|
end
|
324
325
|
|
@@ -352,25 +353,23 @@ class Roo::Base
|
|
352
353
|
# control characters and white spaces around columns
|
353
354
|
|
354
355
|
def each(options = {})
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
else
|
361
|
-
clean_sheet_if_need(options)
|
362
|
-
search_or_set_header(options)
|
363
|
-
headers = @headers ||
|
364
|
-
Hash[(first_column..last_column).map do |col|
|
365
|
-
[cell(@header_line, col), col]
|
366
|
-
end]
|
367
|
-
|
368
|
-
@header_line.upto(last_row) do |line|
|
369
|
-
yield(Hash[headers.map { |k, v| [k, cell(line, v)] }])
|
370
|
-
end
|
356
|
+
return to_enum(:each, options) unless block_given?
|
357
|
+
|
358
|
+
if options.empty?
|
359
|
+
1.upto(last_row) do |line|
|
360
|
+
yield row(line)
|
371
361
|
end
|
372
362
|
else
|
373
|
-
|
363
|
+
clean_sheet_if_need(options)
|
364
|
+
search_or_set_header(options)
|
365
|
+
headers = @headers ||
|
366
|
+
Hash[(first_column..last_column).map do |col|
|
367
|
+
[cell(@header_line, col), col]
|
368
|
+
end]
|
369
|
+
|
370
|
+
@header_line.upto(last_row) do |line|
|
371
|
+
yield(Hash[headers.map { |k, v| [k, cell(line, v)] }])
|
372
|
+
end
|
374
373
|
end
|
375
374
|
end
|
376
375
|
|
@@ -409,23 +408,24 @@ class Roo::Base
|
|
409
408
|
filename = File.basename(filename, File.extname(filename))
|
410
409
|
end
|
411
410
|
|
412
|
-
if uri?(filename) && qs_begin = filename.rindex('?')
|
411
|
+
if uri?(filename) && (qs_begin = filename.rindex('?'))
|
413
412
|
filename = filename[0..qs_begin - 1]
|
414
413
|
end
|
415
414
|
exts = Array(exts)
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
415
|
+
|
416
|
+
return if exts.include?(File.extname(filename).downcase)
|
417
|
+
|
418
|
+
case warning_level
|
419
|
+
when :error
|
420
|
+
warn file_type_warning_message(filename, exts)
|
421
|
+
fail TypeError, "#{filename} is not #{name} file"
|
422
|
+
when :warning
|
423
|
+
warn "are you sure, this is #{name} spreadsheet file?"
|
424
|
+
warn file_type_warning_message(filename, exts)
|
425
|
+
when :ignore
|
426
|
+
# ignore
|
427
|
+
else
|
428
|
+
fail "#{warning_level} illegal state of file_warning"
|
429
429
|
end
|
430
430
|
end
|
431
431
|
|
@@ -476,9 +476,9 @@ class Roo::Base
|
|
476
476
|
return if is_stream?(filename)
|
477
477
|
filename = download_uri(filename, tmpdir) if uri?(filename)
|
478
478
|
filename = unzip(filename, tmpdir) if packed == :zip
|
479
|
-
|
480
|
-
|
481
|
-
|
479
|
+
|
480
|
+
fail IOError, "file #{filename} does not exist" unless File.file?(filename)
|
481
|
+
|
482
482
|
filename
|
483
483
|
end
|
484
484
|
|
@@ -536,11 +536,8 @@ class Roo::Base
|
|
536
536
|
end
|
537
537
|
|
538
538
|
def make_tmpdir(prefix = nil, root = nil, &block)
|
539
|
-
prefix =
|
540
|
-
|
541
|
-
else
|
542
|
-
TEMP_PREFIX
|
543
|
-
end
|
539
|
+
prefix = "#{TEMP_PREFIX}#{prefix}"
|
540
|
+
|
544
541
|
::Dir.mktmpdir(prefix, root || ENV['ROO_TMP'], &block).tap do |result|
|
545
542
|
block_given? || track_tmpdir!(result)
|
546
543
|
end
|
@@ -588,9 +585,9 @@ class Roo::Base
|
|
588
585
|
fail ArgumentError
|
589
586
|
end
|
590
587
|
end
|
591
|
-
|
592
|
-
|
593
|
-
|
588
|
+
|
589
|
+
col = ::Roo::Utils.letter_to_number(col) if col.is_a?(::String)
|
590
|
+
|
594
591
|
[row, col]
|
595
592
|
end
|
596
593
|
|
@@ -641,7 +638,7 @@ class Roo::Base
|
|
641
638
|
fail RangeError, "sheet index #{sheet} not found"
|
642
639
|
end
|
643
640
|
when String
|
644
|
-
unless sheets.include?
|
641
|
+
unless sheets.include?(sheet)
|
645
642
|
fail RangeError, "sheet '#{sheet}' not found"
|
646
643
|
end
|
647
644
|
else
|
@@ -670,14 +667,14 @@ class Roo::Base
|
|
670
667
|
# parameter is nil the output goes to STDOUT
|
671
668
|
def write_csv_content(file = nil, sheet = nil, separator = ',')
|
672
669
|
file ||= STDOUT
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
670
|
+
return unless first_row(sheet) # The sheet is empty
|
671
|
+
|
672
|
+
1.upto(last_row(sheet)) do |row|
|
673
|
+
1.upto(last_column(sheet)) do |col|
|
674
|
+
file.print(separator) if col > 1
|
675
|
+
file.print cell_to_csv(row, col, sheet)
|
676
|
+
end
|
677
|
+
file.print("\n")
|
681
678
|
end
|
682
679
|
end
|
683
680
|
|
@@ -729,9 +726,9 @@ class Roo::Base
|
|
729
726
|
# converts an integer value to a time string like '02:05:06'
|
730
727
|
def integer_to_timestring(content)
|
731
728
|
h = (content / 3600.0).floor
|
732
|
-
content
|
729
|
+
content -= h * 3600
|
733
730
|
m = (content / 60.0).floor
|
734
|
-
content
|
731
|
+
content -= m * 60
|
735
732
|
s = content
|
736
733
|
sprintf('%02d:%02d:%02d', h, m, s)
|
737
734
|
end
|
@@ -13,9 +13,19 @@ module Roo
|
|
13
13
|
|
14
14
|
private
|
15
15
|
|
16
|
+
def fix_invalid_shared_strings(doc)
|
17
|
+
invalid = { '_x000D_' => "\n" }
|
18
|
+
xml = doc.to_s
|
19
|
+
|
20
|
+
if xml[/#{invalid.keys.join('|')}/]
|
21
|
+
@doc = ::Nokogiri::XML(xml.gsub(/#{invalid.keys.join('|')}/, invalid))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
16
25
|
def extract_shared_strings
|
17
26
|
return [] unless doc_exists?
|
18
27
|
|
28
|
+
fix_invalid_shared_strings(doc)
|
19
29
|
# read the shared strings xml document
|
20
30
|
doc.xpath('/sst/si').map do |si|
|
21
31
|
shared_string = ''
|
data/lib/roo/spreadsheet.rb
CHANGED
data/lib/roo/version.rb
CHANGED
data/spec/helpers.rb
ADDED
data/spec/lib/roo/base_spec.rb
CHANGED
@@ -1,4 +1,216 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Roo::Base do
|
4
|
+
let(:klass) do
|
5
|
+
Class.new(Roo::Base) do
|
6
|
+
def initialize(filename, data = {})
|
7
|
+
super(filename)
|
8
|
+
@data ||= data
|
9
|
+
end
|
10
|
+
|
11
|
+
def read_cells(sheet = default_sheet)
|
12
|
+
return if @cells_read[sheet]
|
13
|
+
type_map = { String => :string, Date => :date, Numeric => :float }
|
14
|
+
|
15
|
+
@cell[sheet] = @data
|
16
|
+
@cell_type[sheet] = Hash[@data.map { |k, v| [k, type_map.find {|type,_| v.is_a?(type) }.last ] }]
|
17
|
+
@first_row[sheet] = @data.map { |k, _| k[0] }.min
|
18
|
+
@last_row[sheet] = @data.map { |k, _| k[0] }.max
|
19
|
+
@first_column[sheet] = @data.map { |k, _| k[1] }.min
|
20
|
+
@last_column[sheet] = @data.map { |k, _| k[1] }.max
|
21
|
+
@cells_read[sheet] = true
|
22
|
+
end
|
23
|
+
|
24
|
+
def cell(row, col, sheet = nil)
|
25
|
+
sheet ||= default_sheet
|
26
|
+
read_cells(sheet)
|
27
|
+
@cell[sheet][[row, col]]
|
28
|
+
end
|
29
|
+
|
30
|
+
def celltype(row, col, sheet = nil)
|
31
|
+
sheet ||= default_sheet
|
32
|
+
read_cells(sheet)
|
33
|
+
@cell_type[sheet][[row, col]]
|
34
|
+
end
|
35
|
+
|
36
|
+
def sheets
|
37
|
+
['my_sheet', 'blank sheet']
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
let(:spreadsheet_data) do
|
43
|
+
{
|
44
|
+
[5, 1] => Date.civil(1961, 11, 21),
|
45
|
+
|
46
|
+
[8, 3] => 'thisisc8',
|
47
|
+
[8, 7] => 'thisisg8',
|
48
|
+
|
49
|
+
[12, 1] => 41.0,
|
50
|
+
[12, 2] => 42.0,
|
51
|
+
[12, 3] => 43.0,
|
52
|
+
[12, 4] => 44.0,
|
53
|
+
[12, 5] => 45.0,
|
54
|
+
|
55
|
+
[15, 3] => 43.0,
|
56
|
+
[15, 4] => 44.0,
|
57
|
+
[15, 5] => 45.0,
|
58
|
+
|
59
|
+
[16, 2] => '"Hello world!"',
|
60
|
+
[16, 3] => 'forty-three',
|
61
|
+
[16, 4] => 'forty-four',
|
62
|
+
[16, 5] => 'forty-five'
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
let(:spreadsheet) { klass.new('some_file', spreadsheet_data) }
|
67
|
+
|
68
|
+
describe '#uri?' do
|
69
|
+
it 'should return true when passed a filename starting with http(s)://' do
|
70
|
+
expect(spreadsheet.send(:uri?, 'http://example.com/')).to be_truthy
|
71
|
+
expect(spreadsheet.send(:uri?, 'https://example.com/')).to be_truthy
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should return false when passed a filename which does not start with http(s)://' do
|
75
|
+
expect(spreadsheet.send(:uri?, 'example.com')).to be_falsy
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should return false when passed non-String object such as Tempfile' do
|
79
|
+
expect(spreadsheet.send(:uri?, Tempfile.new('test'))).to be_falsy
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#set' do
|
84
|
+
it 'should not update cell when setting an invalid type' do
|
85
|
+
spreadsheet.set(1, 1, 1)
|
86
|
+
expect { spreadsheet.set(1, 1, :invalid_type) }.to raise_error(ArgumentError)
|
87
|
+
expect(spreadsheet.cell(1, 1)).to eq(1)
|
88
|
+
expect(spreadsheet.celltype(1, 1)).to eq(:float)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#first_row' do
|
93
|
+
it 'should return the first row' do
|
94
|
+
expect(spreadsheet.first_row).to eq(5)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#last_row' do
|
99
|
+
it 'should return the last row' do
|
100
|
+
expect(spreadsheet.last_row).to eq(16)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#first_column' do
|
105
|
+
it 'should return the first column' do
|
106
|
+
expect(spreadsheet.first_column).to eq(1)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#first_column_as_letter' do
|
111
|
+
it 'should return the first column as a letter' do
|
112
|
+
expect(spreadsheet.first_column_as_letter).to eq('A')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '#last_column' do
|
117
|
+
it 'should return the last column' do
|
118
|
+
expect(spreadsheet.last_column).to eq(7)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe '#last_column_as_letter' do
|
123
|
+
it 'should return the last column as a letter' do
|
124
|
+
expect(spreadsheet.last_column_as_letter).to eq('G')
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '#row' do
|
129
|
+
it 'should return the specified row' do
|
130
|
+
expect(spreadsheet.row(12)).to eq([41.0, 42.0, 43.0, 44.0, 45.0, nil, nil])
|
131
|
+
expect(spreadsheet.row(16)).to eq([nil, '"Hello world!"', 'forty-three', 'forty-four', 'forty-five', nil, nil])
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '#empty?' do
|
136
|
+
it 'should return true when empty' do
|
137
|
+
expect(spreadsheet.empty?(1, 1)).to be_truthy
|
138
|
+
expect(spreadsheet.empty?(8, 3)).to be_falsy
|
139
|
+
expect(spreadsheet.empty?('A', 11)).to be_truthy
|
140
|
+
expect(spreadsheet.empty?('A', 12)).to be_falsy
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe '#reload' do
|
145
|
+
it 'should return reinitialize the spreadsheet' do
|
146
|
+
spreadsheet.reload
|
147
|
+
expect(spreadsheet.instance_variable_get(:@cell).empty?).to be_truthy
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#each' do
|
152
|
+
it 'should return an enumerator with all the rows' do
|
153
|
+
each = spreadsheet.each
|
154
|
+
expect(each).to be_a(Enumerator)
|
155
|
+
expect(each.to_a.last).to eq([nil, '"Hello world!"', 'forty-three', 'forty-four', 'forty-five', nil, nil])
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe '#to_yaml' do
|
160
|
+
it 'should convert the spreadsheet to yaml' do
|
161
|
+
expect(spreadsheet.to_yaml({}, 5, 1, 5, 1)).to eq("--- \n" + yaml_entry(5, 1, 'date', '1961-11-21'))
|
162
|
+
expect(spreadsheet.to_yaml({}, 8, 3, 8, 3)).to eq("--- \n" + yaml_entry(8, 3, 'string', 'thisisc8'))
|
163
|
+
|
164
|
+
expect(spreadsheet.to_yaml({}, 12, 3, 12, 3)).to eq("--- \n" + yaml_entry(12, 3, 'float', 43.0))
|
165
|
+
|
166
|
+
expect(spreadsheet.to_yaml({}, 12, 3, 12)).to eq(
|
167
|
+
"--- \n" + yaml_entry(12, 3, 'float', 43.0) +
|
168
|
+
yaml_entry(12, 4, 'float', 44.0) +
|
169
|
+
yaml_entry(12, 5, 'float', 45.0))
|
170
|
+
|
171
|
+
expect(spreadsheet.to_yaml({}, 12, 3)).to eq(
|
172
|
+
"--- \n" + yaml_entry(12, 3, 'float', 43.0) +
|
173
|
+
yaml_entry(12, 4, 'float', 44.0) +
|
174
|
+
yaml_entry(12, 5, 'float', 45.0) +
|
175
|
+
yaml_entry(15, 3, 'float', 43.0) +
|
176
|
+
yaml_entry(15, 4, 'float', 44.0) +
|
177
|
+
yaml_entry(15, 5, 'float', 45.0) +
|
178
|
+
yaml_entry(16, 3, 'string', 'forty-three') +
|
179
|
+
yaml_entry(16, 4, 'string', 'forty-four') +
|
180
|
+
yaml_entry(16, 5, 'string', 'forty-five'))
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
let(:expected_csv) do
|
185
|
+
<<EOS
|
186
|
+
,,,,,,
|
187
|
+
,,,,,,
|
188
|
+
,,,,,,
|
189
|
+
,,,,,,
|
190
|
+
1961-11-21,,,,,,
|
191
|
+
,,,,,,
|
192
|
+
,,,,,,
|
193
|
+
,,"thisisc8",,,,"thisisg8"
|
194
|
+
,,,,,,
|
195
|
+
,,,,,,
|
196
|
+
,,,,,,
|
197
|
+
41,42,43,44,45,,
|
198
|
+
,,,,,,
|
199
|
+
,,,,,,
|
200
|
+
,,43,44,45,,
|
201
|
+
,"""Hello world!""","forty-three","forty-four","forty-five",,
|
202
|
+
EOS
|
203
|
+
end
|
204
|
+
|
205
|
+
let(:expected_csv_with_semicolons) { expected_csv.gsub(/\,/, ';') }
|
206
|
+
|
207
|
+
describe '#to_csv' do
|
208
|
+
it 'should convert the spreadsheet to csv' do
|
209
|
+
expect(spreadsheet.to_csv).to eq(expected_csv)
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'should convert the spreadsheet to csv using the separator when is passed on the parameter' do
|
213
|
+
expect(spreadsheet.to_csv(nil, ';')).to eq(expected_csv_with_semicolons)
|
214
|
+
end
|
215
|
+
end
|
4
216
|
end
|
data/spec/lib/roo/excelx_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -45,10 +45,6 @@ def file_diff(fn1,fn2)
|
|
45
45
|
result
|
46
46
|
end
|
47
47
|
|
48
|
-
def yaml_entry(row,col,type,value)
|
49
|
-
"cell_#{row}_#{col}: \n row: #{row} \n col: #{col} \n celltype: #{type} \n value: #{value} \n"
|
50
|
-
end
|
51
|
-
|
52
48
|
class File
|
53
49
|
def File.delete_if_exist(filename)
|
54
50
|
if File.exist?(filename)
|
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.1.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Preymesser
|
@@ -11,17 +11,17 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2015-
|
14
|
+
date: 2015-08-01 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: nokogiri
|
18
|
-
prerelease: false
|
19
18
|
requirement: !ruby/object:Gem::Requirement
|
20
19
|
requirements:
|
21
20
|
- - "~>"
|
22
21
|
- !ruby/object:Gem::Version
|
23
22
|
version: '1'
|
24
23
|
type: :runtime
|
24
|
+
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
@@ -29,7 +29,6 @@ dependencies:
|
|
29
29
|
version: '1'
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: rubyzip
|
32
|
-
prerelease: false
|
33
32
|
requirement: !ruby/object:Gem::Requirement
|
34
33
|
requirements:
|
35
34
|
- - "~>"
|
@@ -39,6 +38,7 @@ dependencies:
|
|
39
38
|
- !ruby/object:Gem::Version
|
40
39
|
version: 2.0.0
|
41
40
|
type: :runtime
|
41
|
+
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
@@ -49,13 +49,13 @@ dependencies:
|
|
49
49
|
version: 2.0.0
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
51
|
name: rake
|
52
|
-
prerelease: false
|
53
52
|
requirement: !ruby/object:Gem::Requirement
|
54
53
|
requirements:
|
55
54
|
- - "~>"
|
56
55
|
- !ruby/object:Gem::Version
|
57
56
|
version: '10.1'
|
58
57
|
type: :development
|
58
|
+
prerelease: false
|
59
59
|
version_requirements: !ruby/object:Gem::Requirement
|
60
60
|
requirements:
|
61
61
|
- - "~>"
|
@@ -63,7 +63,6 @@ dependencies:
|
|
63
63
|
version: '10.1'
|
64
64
|
- !ruby/object:Gem::Dependency
|
65
65
|
name: minitest
|
66
|
-
prerelease: false
|
67
66
|
requirement: !ruby/object:Gem::Requirement
|
68
67
|
requirements:
|
69
68
|
- - "~>"
|
@@ -73,6 +72,7 @@ dependencies:
|
|
73
72
|
- !ruby/object:Gem::Version
|
74
73
|
version: 5.4.3
|
75
74
|
type: :development
|
75
|
+
prerelease: false
|
76
76
|
version_requirements: !ruby/object:Gem::Requirement
|
77
77
|
requirements:
|
78
78
|
- - "~>"
|
@@ -131,6 +131,7 @@ files:
|
|
131
131
|
- spec/fixtures/vcr_cassettes/google_drive.yml
|
132
132
|
- spec/fixtures/vcr_cassettes/google_drive_access_token.yml
|
133
133
|
- spec/fixtures/vcr_cassettes/google_drive_set.yml
|
134
|
+
- spec/helpers.rb
|
134
135
|
- spec/lib/roo/base_spec.rb
|
135
136
|
- spec/lib/roo/csv_spec.rb
|
136
137
|
- spec/lib/roo/excelx/format_spec.rb
|
@@ -141,7 +142,6 @@ files:
|
|
141
142
|
- spec/lib/roo/utils_spec.rb
|
142
143
|
- spec/spec_helper.rb
|
143
144
|
- test/all_ss.rb
|
144
|
-
- test/test_generic_spreadsheet.rb
|
145
145
|
- test/test_helper.rb
|
146
146
|
- test/test_roo.rb
|
147
147
|
homepage: http://github.com/roo-rb/roo
|
@@ -164,8 +164,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
164
|
version: '0'
|
165
165
|
requirements: []
|
166
166
|
rubyforge_project:
|
167
|
-
rubygems_version: 2.4.
|
167
|
+
rubygems_version: 2.4.5
|
168
168
|
signing_key:
|
169
169
|
specification_version: 4
|
170
170
|
summary: Roo can access the contents of various spreadsheet files.
|
171
171
|
test_files: []
|
172
|
+
has_rdoc:
|
@@ -1,237 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
require File.dirname(__FILE__) + '/test_helper'
|
3
|
-
|
4
|
-
class TestBase < Minitest::Test
|
5
|
-
def setup
|
6
|
-
@klass = Class.new(Roo::Base) do
|
7
|
-
def initialize(filename = 'some_file')
|
8
|
-
super
|
9
|
-
@filename = filename
|
10
|
-
end
|
11
|
-
|
12
|
-
def read_cells(sheet = nil)
|
13
|
-
@cells_read[sheet] = true
|
14
|
-
end
|
15
|
-
|
16
|
-
def cell(row, col, sheet = nil)
|
17
|
-
sheet ||= default_sheet
|
18
|
-
@cell[sheet][[row, col]]
|
19
|
-
end
|
20
|
-
|
21
|
-
def celltype(row, col, sheet = nil)
|
22
|
-
sheet ||= default_sheet
|
23
|
-
@cell_type[sheet][[row, col]]
|
24
|
-
end
|
25
|
-
|
26
|
-
def sheets
|
27
|
-
['my_sheet', 'blank sheet']
|
28
|
-
end
|
29
|
-
end
|
30
|
-
@oo = @klass.new
|
31
|
-
setup_test_sheet(@oo)
|
32
|
-
end
|
33
|
-
|
34
|
-
context 'private method Roo::Base.uri?(filename)' do
|
35
|
-
should 'return true when passed a filename starts with http(s)://' do
|
36
|
-
assert_equal true, @oo.send(:uri?, 'http://example.com/')
|
37
|
-
assert_equal true, @oo.send(:uri?, 'https://example.com/')
|
38
|
-
end
|
39
|
-
|
40
|
-
should 'return false when passed a filename which does not start with http(s)://' do
|
41
|
-
assert_equal false, @oo.send(:uri?, 'example.com')
|
42
|
-
end
|
43
|
-
|
44
|
-
should 'return false when passed non-String object such as Tempfile' do
|
45
|
-
assert_equal false, @oo.send(:uri?, Tempfile.new('test'))
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_setting_invalid_type_does_not_update_cell
|
50
|
-
@oo.set(1, 1, 1)
|
51
|
-
assert_raises(ArgumentError) { @oo.set(1, 1, :invalid_type) }
|
52
|
-
assert_equal 1, @oo.cell(1, 1)
|
53
|
-
assert_equal :float, @oo.celltype(1, 1)
|
54
|
-
end
|
55
|
-
|
56
|
-
def test_first_row
|
57
|
-
assert_equal 5, @oo.first_row
|
58
|
-
end
|
59
|
-
|
60
|
-
def test_last_row
|
61
|
-
assert_equal 16, @oo.last_row
|
62
|
-
end
|
63
|
-
|
64
|
-
def test_first_column
|
65
|
-
assert_equal 1, @oo.first_column
|
66
|
-
end
|
67
|
-
|
68
|
-
def test_first_column_as_letter
|
69
|
-
assert_equal 'A', @oo.first_column_as_letter
|
70
|
-
end
|
71
|
-
|
72
|
-
def test_last_column
|
73
|
-
assert_equal 7, @oo.last_column
|
74
|
-
end
|
75
|
-
|
76
|
-
def test_last_column_as_letter
|
77
|
-
assert_equal 'G', @oo.last_column_as_letter
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_rows
|
81
|
-
assert_equal [41.0, 42.0, 43.0, 44.0, 45.0, nil, nil], @oo.row(12)
|
82
|
-
assert_equal [nil, '"Hello world!"', 'dreiundvierzig', 'vierundvierzig', 'fuenfundvierzig', nil, nil], @oo.row(16)
|
83
|
-
end
|
84
|
-
|
85
|
-
def test_empty_eh
|
86
|
-
assert @oo.empty?(1, 1)
|
87
|
-
assert !@oo.empty?(8, 3)
|
88
|
-
assert @oo.empty?('A', 11)
|
89
|
-
assert !@oo.empty?('A', 12)
|
90
|
-
end
|
91
|
-
|
92
|
-
def test_reload
|
93
|
-
@oo.reload
|
94
|
-
assert @oo.instance_variable_get(:@cell).empty?
|
95
|
-
end
|
96
|
-
|
97
|
-
def test_each
|
98
|
-
oo_each = @oo.each
|
99
|
-
assert_instance_of Enumerator, oo_each
|
100
|
-
assert_equal [nil, '"Hello world!"', 'dreiundvierzig', 'vierundvierzig', 'fuenfundvierzig', nil, nil], oo_each.to_a.last
|
101
|
-
end
|
102
|
-
|
103
|
-
def test_to_yaml
|
104
|
-
assert_equal "--- \n" + yaml_entry(5, 1, 'date', '1961-11-21'), @oo.to_yaml({}, 5, 1, 5, 1)
|
105
|
-
assert_equal "--- \n" + yaml_entry(8, 3, 'string', 'thisisc8'), @oo.to_yaml({}, 8, 3, 8, 3)
|
106
|
-
assert_equal "--- \n" + yaml_entry(12, 3, 'float', 43.0), @oo.to_yaml({}, 12, 3, 12, 3)
|
107
|
-
assert_equal \
|
108
|
-
"--- \n" + yaml_entry(12, 3, 'float', 43.0) +
|
109
|
-
yaml_entry(12, 4, 'float', 44.0) +
|
110
|
-
yaml_entry(12, 5, 'float', 45.0), @oo.to_yaml({}, 12, 3, 12)
|
111
|
-
assert_equal \
|
112
|
-
"--- \n" + yaml_entry(12, 3, 'float', 43.0) +
|
113
|
-
yaml_entry(12, 4, 'float', 44.0) +
|
114
|
-
yaml_entry(12, 5, 'float', 45.0) +
|
115
|
-
yaml_entry(15, 3, 'float', 43.0) +
|
116
|
-
yaml_entry(15, 4, 'float', 44.0) +
|
117
|
-
yaml_entry(15, 5, 'float', 45.0) +
|
118
|
-
yaml_entry(16, 3, 'string', 'dreiundvierzig') +
|
119
|
-
yaml_entry(16, 4, 'string', 'vierundvierzig') +
|
120
|
-
yaml_entry(16, 5, 'string', 'fuenfundvierzig'), @oo.to_yaml({}, 12, 3)
|
121
|
-
end
|
122
|
-
|
123
|
-
def test_to_csv
|
124
|
-
assert_equal expected_csv, @oo.to_csv
|
125
|
-
end
|
126
|
-
|
127
|
-
def test_to_csv_with_separator
|
128
|
-
assert_equal expected_csv_with_semicolons, @oo.to_csv(nil, ';')
|
129
|
-
end
|
130
|
-
|
131
|
-
protected
|
132
|
-
|
133
|
-
def setup_test_sheet(workbook = nil)
|
134
|
-
workbook ||= @oo
|
135
|
-
set_sheet_values(workbook)
|
136
|
-
set_sheet_types(workbook)
|
137
|
-
set_cells_read(workbook)
|
138
|
-
end
|
139
|
-
|
140
|
-
def set_sheet_values(workbook)
|
141
|
-
workbook.instance_variable_get(:@cell)[workbook.default_sheet] = {
|
142
|
-
[5, 1] => Date.civil(1961, 11, 21).to_s,
|
143
|
-
|
144
|
-
[8, 3] => 'thisisc8',
|
145
|
-
[8, 7] => 'thisisg8',
|
146
|
-
|
147
|
-
[12, 1] => 41.0,
|
148
|
-
[12, 2] => 42.0,
|
149
|
-
[12, 3] => 43.0,
|
150
|
-
[12, 4] => 44.0,
|
151
|
-
[12, 5] => 45.0,
|
152
|
-
|
153
|
-
[15, 3] => 43.0,
|
154
|
-
[15, 4] => 44.0,
|
155
|
-
[15, 5] => 45.0,
|
156
|
-
|
157
|
-
[16, 2] => '"Hello world!"',
|
158
|
-
[16, 3] => 'dreiundvierzig',
|
159
|
-
[16, 4] => 'vierundvierzig',
|
160
|
-
[16, 5] => 'fuenfundvierzig'
|
161
|
-
}
|
162
|
-
end
|
163
|
-
|
164
|
-
def set_sheet_types(workbook)
|
165
|
-
workbook.instance_variable_get(:@cell_type)[workbook.default_sheet] = {
|
166
|
-
[5, 1] => :date,
|
167
|
-
|
168
|
-
[8, 3] => :string,
|
169
|
-
[8, 7] => :string,
|
170
|
-
|
171
|
-
[12, 1] => :float,
|
172
|
-
[12, 2] => :float,
|
173
|
-
[12, 3] => :float,
|
174
|
-
[12, 4] => :float,
|
175
|
-
[12, 5] => :float,
|
176
|
-
|
177
|
-
[15, 3] => :float,
|
178
|
-
[15, 4] => :float,
|
179
|
-
[15, 5] => :float,
|
180
|
-
|
181
|
-
[16, 2] => :string,
|
182
|
-
[16, 3] => :string,
|
183
|
-
[16, 4] => :string,
|
184
|
-
[16, 5] => :string
|
185
|
-
}
|
186
|
-
end
|
187
|
-
|
188
|
-
def set_first_row(workbook)
|
189
|
-
row_hash = workbook.instance_variable_get(:@first_row)
|
190
|
-
row_hash[workbook.default_sheet] = workbook.instance_variable_get(:@cell)[workbook.default_sheet].map { |k, _v| k[0] }.min
|
191
|
-
end
|
192
|
-
|
193
|
-
def set_last_row(workbook)
|
194
|
-
row_hash = workbook.instance_variable_get(:@last_row)
|
195
|
-
row_hash[workbook.default_sheet] = workbook.instance_variable_get(:@cell)[workbook.default_sheet].map { |k, _v| k[0] }.max
|
196
|
-
end
|
197
|
-
|
198
|
-
def set_first_col(workbook)
|
199
|
-
col_hash = workbook.instance_variable_get(:@first_column)
|
200
|
-
col_hash[workbook.default_sheet] = workbook.instance_variable_get(:@cell)[workbook.default_sheet].map { |k, _v| k[1] }.min
|
201
|
-
end
|
202
|
-
|
203
|
-
def set_last_col(workbook)
|
204
|
-
col_hash = workbook.instance_variable_get(:@last_column)
|
205
|
-
col_hash[workbook.default_sheet] = workbook.instance_variable_get(:@cell)[workbook.default_sheet].map { |k, _v| k[1] }.max
|
206
|
-
end
|
207
|
-
|
208
|
-
def set_cells_read(workbook)
|
209
|
-
read_hash = workbook.instance_variable_get(:@cells_read)
|
210
|
-
read_hash[workbook.default_sheet] = true
|
211
|
-
end
|
212
|
-
|
213
|
-
def expected_csv
|
214
|
-
<<EOS
|
215
|
-
,,,,,,
|
216
|
-
,,,,,,
|
217
|
-
,,,,,,
|
218
|
-
,,,,,,
|
219
|
-
1961-11-21,,,,,,
|
220
|
-
,,,,,,
|
221
|
-
,,,,,,
|
222
|
-
,,"thisisc8",,,,"thisisg8"
|
223
|
-
,,,,,,
|
224
|
-
,,,,,,
|
225
|
-
,,,,,,
|
226
|
-
41,42,43,44,45,,
|
227
|
-
,,,,,,
|
228
|
-
,,,,,,
|
229
|
-
,,43,44,45,,
|
230
|
-
,"""Hello world!""","dreiundvierzig","vierundvierzig","fuenfundvierzig",,
|
231
|
-
EOS
|
232
|
-
end
|
233
|
-
|
234
|
-
def expected_csv_with_semicolons
|
235
|
-
expected_csv.gsub(/\,/, ';')
|
236
|
-
end
|
237
|
-
end
|