sheets 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -1
- data/.travis.yml +6 -0
- data/README.md +12 -4
- data/Rakefile +51 -3
- data/lib/sheets/parsers/excel_parser.rb +16 -0
- data/lib/sheets/parsers/nokogiri_ods_parser.rb +47 -0
- data/lib/sheets/parsers/nokogiri_xlsx_parser.rb +79 -0
- data/lib/sheets/version.rb +1 -1
- data/sheets.gemspec +2 -4
- data/test/data/simple.csv +10 -10
- data/test/parsers/basic_parsers_test.rb +27 -2
- data/test/renderers/basic_renderers_test.rb +1 -1
- data/test/results.json +13 -0
- metadata +31 -76
- data/lib/sheets/parsers/roo_parser.rb +0 -29
- data/lib/sheets/parsers/roo_patches.rb +0 -5
- data/lib/sheets/parsers/roo_patches/roo_patch_28885.rb +0 -116
- data/lib/sheets/parsers/roo_patches/roo_patch_29045.rb +0 -2
- data/test/parsers/roo_parser_test.rb +0 -8
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -14,7 +14,7 @@ Your application only needs to care about the layout of the spreadsheet, and the
|
|
14
14
|
Usage
|
15
15
|
----------
|
16
16
|
|
17
|
-
Install via Rubygems:
|
17
|
+
Install via Rubygems:
|
18
18
|
|
19
19
|
gem install sheets
|
20
20
|
|
@@ -80,6 +80,13 @@ Renderers subclass Sheets::Renderers::Base, live in the Sheets::Renderers namesp
|
|
80
80
|
|
81
81
|
Renderers are given access to the results of Sheets::Base#to_array as @data. See lib/sheets/renderers/* for examples.
|
82
82
|
|
83
|
+
Test Suite Results
|
84
|
+
-----
|
85
|
+
|
86
|
+
Sheets uses Travis-CI for Continuous Integration.
|
87
|
+
|
88
|
+
[![Build Status](http://travis-ci.org/bspaulding/Sheets.png)](http://travis-ci.org/bspaulding/Sheets)
|
89
|
+
|
83
90
|
License
|
84
91
|
----------
|
85
92
|
|
@@ -90,7 +97,8 @@ Please note that Sheets is dependent upon the Spreadsheet gem, which is licensed
|
|
90
97
|
Credits
|
91
98
|
----------
|
92
99
|
|
93
|
-
Sheets takes
|
100
|
+
Sheets takes advantage of the work done in these gems:
|
94
101
|
|
95
|
-
* [
|
96
|
-
* [
|
102
|
+
* [spreadsheet](http://rubygems.org/gems/spreadsheet)
|
103
|
+
* [rubyzip](http://rubygems.org/gems/rubyzip)
|
104
|
+
* [nokogiri](http://rubygems.org/gems/nokogiri)
|
data/Rakefile
CHANGED
@@ -1,7 +1,55 @@
|
|
1
|
+
# require 'rubygems'
|
1
2
|
require 'bundler'
|
2
3
|
Bundler::GemHelper.install_tasks
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
testing_rubies = %w[1.8.7 1.9.2 ree ree-1.8.7-2010.01 jruby rbx]
|
6
|
+
|
7
|
+
task :default => :test
|
8
|
+
|
9
|
+
namespace :test do
|
10
|
+
task :current do
|
11
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), 'test', 'test_helper.rb')
|
12
|
+
Dir[ File.join(File.expand_path(File.dirname(__FILE__)), 'test', '**', '*_test.rb') ].each {|file| require file }
|
13
|
+
end
|
14
|
+
|
15
|
+
task :all do
|
16
|
+
File.delete('test/results.json') if File.exists?('test/results.json')
|
17
|
+
system "rvm --json #{testing_rubies.join(',')} rake test > test/results.json"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
task :test => ['test:current']
|
22
|
+
|
23
|
+
namespace :install do
|
24
|
+
def ruby_installed?(ruby)
|
25
|
+
!%x[rvm use #{ruby}].include?('not installed')
|
26
|
+
end
|
27
|
+
|
28
|
+
task :rubies do
|
29
|
+
testing_rubies.each do |ruby|
|
30
|
+
puts ruby
|
31
|
+
puts "----------"
|
32
|
+
|
33
|
+
ruby_installed?(ruby) ? puts('- Installed.') : system("rvm install #{ruby}")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
task :bundles => :rubies do
|
38
|
+
testing_rubies.each do |ruby|
|
39
|
+
puts ruby
|
40
|
+
puts "----------"
|
41
|
+
|
42
|
+
puts '- Installing bundler...'
|
43
|
+
system "rvm #{ruby} gem install --no-rdoc --no-ri bundler"
|
44
|
+
|
45
|
+
puts '- Installing bundle...'
|
46
|
+
system "rvm #{ruby} exec bundle install"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
namespace :clean do
|
52
|
+
task :rbx do
|
53
|
+
Dir[ File.join(File.expand_path(File.dirname(__FILE__)), '**', '*.rbc') ].each {|file| File.delete(file) }
|
54
|
+
end
|
7
55
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spreadsheet'
|
2
|
+
|
3
|
+
class Sheets::Parsers::ExcelParser < Sheets::Parsers::Base
|
4
|
+
parses :xls
|
5
|
+
|
6
|
+
def to_array
|
7
|
+
workbook = Spreadsheet.open(@file_path)
|
8
|
+
worksheet = workbook.worksheet(0)
|
9
|
+
# worksheet.collect {|row| row.collect {|cell| cell } }
|
10
|
+
worksheet.collect do |row|
|
11
|
+
cells = []
|
12
|
+
row.count.times {|cell_index| cells << row[cell_index].to_s }
|
13
|
+
cells
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'zip/zip'
|
3
|
+
|
4
|
+
class Sheets::Parsers::NokogiriOdsParser < Sheets::Parsers::Base
|
5
|
+
parses :ods
|
6
|
+
|
7
|
+
def to_array
|
8
|
+
rows.collect do |row|
|
9
|
+
table_cells = []
|
10
|
+
row.xpath('table:table-cell').each do |cell|
|
11
|
+
repeat = cell.attributes["number-columns-repeated"].text.to_i if cell.attributes["number-columns-repeated"]
|
12
|
+
repeat ||= 1
|
13
|
+
repeat.times { table_cells << cell }
|
14
|
+
end
|
15
|
+
|
16
|
+
table_cells.collect {|cell| value_for_cell(cell) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# returns the zipfile object for the document
|
23
|
+
def zipfile
|
24
|
+
@zipfile ||= Zip::ZipFile.open( @file_path )
|
25
|
+
end
|
26
|
+
|
27
|
+
def content_doc
|
28
|
+
@content_doc ||= Nokogiri::XML( zipfile.read('content.xml') )
|
29
|
+
end
|
30
|
+
|
31
|
+
def rows
|
32
|
+
@rows ||= content_doc.xpath('//table:table/table:table-row')
|
33
|
+
end
|
34
|
+
|
35
|
+
def value_for_cell(cell_element)
|
36
|
+
value_type = cell_element.attributes["value-type"]
|
37
|
+
send("#{value_type}_value_for_cell", cell_element)
|
38
|
+
end
|
39
|
+
|
40
|
+
def string_value_for_cell(cell_element)
|
41
|
+
cell_element.xpath('text:p').text
|
42
|
+
end
|
43
|
+
|
44
|
+
def float_value_for_cell(cell_element)
|
45
|
+
cell_element.xpath('text:p').text.to_f.to_s
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'zip/zip'
|
3
|
+
|
4
|
+
class Sheets::Parsers::NokogiriXlsxParser < Sheets::Parsers::Base
|
5
|
+
parses :xlsx
|
6
|
+
|
7
|
+
def to_array
|
8
|
+
# Create Matrices
|
9
|
+
matrices = worksheets.collect do |worksheet|
|
10
|
+
worksheet.css('sheetData>row').collect do |row|
|
11
|
+
row.css('c').collect do |cell|
|
12
|
+
cell_value = cell.css('v').text
|
13
|
+
|
14
|
+
if cell.attribute('t')
|
15
|
+
celltype = cell.attribute('t').value
|
16
|
+
if celltype == 's'
|
17
|
+
# Load Shared String Value
|
18
|
+
cell_value = shared_strings[cell_value.to_i]
|
19
|
+
elsif celltype == 'b'
|
20
|
+
cell_value = (cell_value == "1") ? "TRUE" : "FALSE"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
if cell.attribute('s') && cell.attribute('s').value == "1"
|
25
|
+
cell_value = (base_date + cell_value.to_f).strftime('%Y-%m-%d') # Date conversion
|
26
|
+
end
|
27
|
+
|
28
|
+
if cell_value.match(/\A[0-9]+\.?[0-9]*\Z/)
|
29
|
+
cell_value = cell_value.to_f.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
cell_value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
matrices.first
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# returns the zipfile object for the document
|
43
|
+
def zipfile
|
44
|
+
@zipfile ||= Zip::ZipFile.open( @file_path )
|
45
|
+
end
|
46
|
+
|
47
|
+
# returns a nokogiri document for the workbook
|
48
|
+
def workbook
|
49
|
+
@workbook ||= Nokogiri::XML( zipfile.read("xl/workbook.xml") )
|
50
|
+
end
|
51
|
+
|
52
|
+
# returns an array of strings for the sharedStrings.
|
53
|
+
def shared_strings
|
54
|
+
@shared_strings ||= Nokogiri::XML( zipfile.read("xl/sharedStrings.xml") ).css('si>t').collect(&:text)
|
55
|
+
end
|
56
|
+
|
57
|
+
# returns an array of strings containing the worksheet ids from the workbook
|
58
|
+
def worksheet_ids
|
59
|
+
@sheet_ids ||= workbook.css('sheets>sheet').collect {|sheet| sheet.attribute('sheetId').value }
|
60
|
+
end
|
61
|
+
|
62
|
+
# returns an array of nokogiri documents for each worksheet
|
63
|
+
def worksheets
|
64
|
+
@worksheets ||= worksheet_ids.collect {|sheet_id| Nokogiri::XML( zipfile.read("xl/worksheets/sheet#{sheet_id}.xml") ) }
|
65
|
+
end
|
66
|
+
|
67
|
+
# returns a date object representing the start of the serial date system for this sheet
|
68
|
+
# Either 1900-01-01 or 1904-01-01
|
69
|
+
def base_date
|
70
|
+
@base_date ||= lambda do
|
71
|
+
date_base_element = workbook.search('workbookPr').attribute('date1904')
|
72
|
+
if date_base_element && date_base_element.value.to_i == 1
|
73
|
+
Date.parse('1904-01-01')
|
74
|
+
else
|
75
|
+
Date.parse('1900-01-01')
|
76
|
+
end
|
77
|
+
end.call
|
78
|
+
end
|
79
|
+
end
|
data/lib/sheets/version.rb
CHANGED
data/sheets.gemspec
CHANGED
@@ -15,12 +15,10 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.rubyforge_project = "sheets"
|
16
16
|
|
17
17
|
s.add_dependency('spreadsheet', '>= 0.6.5.2')
|
18
|
-
s.add_dependency('roo', '= 1.9.3')
|
19
|
-
# These are the dependencies roo forgot:
|
20
|
-
s.add_dependency('builder', '>= 3.0.0')
|
21
18
|
s.add_dependency('rubyzip', '>= 0.9.4')
|
22
19
|
s.add_dependency('nokogiri', '>= 1.4.3.1')
|
23
|
-
|
20
|
+
|
21
|
+
s.add_development_dependency('rake', '0.9.2')
|
24
22
|
|
25
23
|
s.files = `git ls-files`.split("\n")
|
26
24
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/test/data/simple.csv
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
Date,Impressions,Clicks,Actions
|
2
|
-
2011-01-01,10,10,10
|
3
|
-
2011-01-02,10,10,10
|
4
|
-
2011-01-03,10,10,10
|
5
|
-
2011-01-04,10,10,10
|
6
|
-
2011-01-05,10,10,10
|
7
|
-
2011-01-06,10,10,10
|
8
|
-
2011-01-07,10,10,10
|
9
|
-
2011-01-08,10,10,10
|
10
|
-
2011-01-09,10,10,10
|
11
|
-
2011-01-10,10,10,10
|
2
|
+
2011-01-01,10.0,10.0,10.0
|
3
|
+
2011-01-02,10.0,10.0,10.0
|
4
|
+
2011-01-03,10.0,10.0,10.0
|
5
|
+
2011-01-04,10.0,10.0,10.0
|
6
|
+
2011-01-05,10.0,10.0,10.0
|
7
|
+
2011-01-06,10.0,10.0,10.0
|
8
|
+
2011-01-07,10.0,10.0,10.0
|
9
|
+
2011-01-08,10.0,10.0,10.0
|
10
|
+
2011-01-09,10.0,10.0,10.0
|
11
|
+
2011-01-10,10.0,10.0,10.0
|
@@ -1,4 +1,4 @@
|
|
1
|
-
parser_classes = (Sheets::Parsers.constants - ["Base"]).map {|constant_name| Sheets::Parsers.const_get(constant_name) }
|
1
|
+
parser_classes = (Sheets::Parsers.constants.map(&:to_s) - ["Base"]).map {|constant_name| Sheets::Parsers.const_get(constant_name) }
|
2
2
|
|
3
3
|
test_classes_for_collection parser_classes do |parser_class|
|
4
4
|
define_method :test_provides_formats do
|
@@ -10,9 +10,34 @@ test_classes_for_collection parser_classes do |parser_class|
|
|
10
10
|
end
|
11
11
|
|
12
12
|
parser_class.formats.each do |format|
|
13
|
-
define_method "test_#{format}
|
13
|
+
define_method "test_#{format}_responds_to_to_array" do
|
14
14
|
parser = parser_class.new([], format, nil)
|
15
15
|
assert parser.respond_to?("to_array"), "#{parser.inspect} doesn't respond to to_array"
|
16
16
|
end
|
17
|
+
|
18
|
+
define_method "test_#{format}_to_array_matches_sample_data" do
|
19
|
+
example_data = [
|
20
|
+
[ "Date", "Impressions", "Clicks", "Actions" ],
|
21
|
+
[ "2011-01-01", "10.0", "10.0", "10.0" ],
|
22
|
+
[ "2011-01-02", "10.0", "10.0", "10.0" ],
|
23
|
+
[ "2011-01-03", "10.0", "10.0", "10.0" ],
|
24
|
+
[ "2011-01-04", "10.0", "10.0", "10.0" ],
|
25
|
+
[ "2011-01-05", "10.0", "10.0", "10.0" ],
|
26
|
+
[ "2011-01-06", "10.0", "10.0", "10.0" ],
|
27
|
+
[ "2011-01-07", "10.0", "10.0", "10.0" ],
|
28
|
+
[ "2011-01-08", "10.0", "10.0", "10.0" ],
|
29
|
+
[ "2011-01-09", "10.0", "10.0", "10.0" ],
|
30
|
+
[ "2011-01-10", "10.0", "10.0", "10.0" ]
|
31
|
+
]
|
32
|
+
|
33
|
+
file_path = File.expand_path( File.join('test', 'data', "simple.#{format}") )
|
34
|
+
parser = parser_class.new( File.read(file_path), format, file_path )
|
35
|
+
result = parser.to_array
|
36
|
+
|
37
|
+
# Normalize to parsed dates to avoid Date type conflict 'failures'
|
38
|
+
result[1..-1].collect {|row| row[0] = Date.parse(row[0]).strftime('%Y-%m-%d') }
|
39
|
+
|
40
|
+
assert_equal example_data, result, "#{parser_class}#to_array for format #{format} doesn't match example data."
|
41
|
+
end
|
17
42
|
end
|
18
43
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
renderer_classes = (Sheets::Renderers.constants - ["Base"]).map {|constant_name| Sheets::Renderers.const_get(constant_name) }
|
1
|
+
renderer_classes = (Sheets::Renderers.constants.map(&:to_s) - ["Base"]).map {|constant_name| Sheets::Renderers.const_get(constant_name) }
|
2
2
|
|
3
3
|
test_classes_for_collection renderer_classes do |renderer_class|
|
4
4
|
define_method :test_provides_formats do
|
data/test/results.json
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
{
|
2
|
+
"totals": { "rubies": 6, "successes": 6, "errors": 0 },
|
3
|
+
"successful": ["ruby-1.8.7-p334", "ruby-1.9.2-p180", "ree-1.8.7-2011.03", "ree-1.8.7-2010.01", "jruby-1.6.1", "rbx-head"],
|
4
|
+
"errors": [],
|
5
|
+
"rubies": {
|
6
|
+
{"ruby-1.8.7-p334": 0},
|
7
|
+
{"ruby-1.9.2-p180": 0},
|
8
|
+
{"ree-1.8.7-2011.03": 0},
|
9
|
+
{"ree-1.8.7-2010.01": 0},
|
10
|
+
{"jruby-1.6.1": 0},
|
11
|
+
{"rbx-head": 0}
|
12
|
+
}
|
13
|
+
}
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sheets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
4
|
+
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 1
|
7
|
+
- 1
|
8
8
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.0
|
9
|
+
version: 1.1.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Bradley J. Spaulding
|
@@ -15,107 +14,67 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2011-
|
17
|
+
date: 2011-11-29 00:00:00 -05:00
|
19
18
|
default_executable:
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
|
-
|
23
|
-
prerelease: false
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
21
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
26
22
|
requirements:
|
27
23
|
- - ">="
|
28
24
|
- !ruby/object:Gem::Version
|
29
|
-
hash: 111
|
30
25
|
segments:
|
31
26
|
- 0
|
32
27
|
- 6
|
33
28
|
- 5
|
34
29
|
- 2
|
35
30
|
version: 0.6.5.2
|
36
|
-
|
37
|
-
|
38
|
-
- !ruby/object:Gem::Dependency
|
39
|
-
name: roo
|
40
|
-
prerelease: false
|
41
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
|
-
requirements:
|
44
|
-
- - "="
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
hash: 53
|
47
|
-
segments:
|
48
|
-
- 1
|
49
|
-
- 9
|
50
|
-
- 3
|
51
|
-
version: 1.9.3
|
52
|
-
type: :runtime
|
53
|
-
version_requirements: *id002
|
54
|
-
- !ruby/object:Gem::Dependency
|
55
|
-
name: builder
|
31
|
+
requirement: *id001
|
32
|
+
name: spreadsheet
|
56
33
|
prerelease: false
|
57
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
|
-
requirements:
|
60
|
-
- - ">="
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
hash: 7
|
63
|
-
segments:
|
64
|
-
- 3
|
65
|
-
- 0
|
66
|
-
- 0
|
67
|
-
version: 3.0.0
|
68
34
|
type: :runtime
|
69
|
-
version_requirements: *id003
|
70
35
|
- !ruby/object:Gem::Dependency
|
71
|
-
|
72
|
-
prerelease: false
|
73
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
36
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
75
37
|
requirements:
|
76
38
|
- - ">="
|
77
39
|
- !ruby/object:Gem::Version
|
78
|
-
hash: 51
|
79
40
|
segments:
|
80
41
|
- 0
|
81
42
|
- 9
|
82
43
|
- 4
|
83
44
|
version: 0.9.4
|
45
|
+
requirement: *id002
|
46
|
+
name: rubyzip
|
47
|
+
prerelease: false
|
84
48
|
type: :runtime
|
85
|
-
version_requirements: *id004
|
86
49
|
- !ruby/object:Gem::Dependency
|
87
|
-
|
88
|
-
prerelease: false
|
89
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
50
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
91
51
|
requirements:
|
92
52
|
- - ">="
|
93
53
|
- !ruby/object:Gem::Version
|
94
|
-
hash: 113
|
95
54
|
segments:
|
96
55
|
- 1
|
97
56
|
- 4
|
98
57
|
- 3
|
99
58
|
- 1
|
100
59
|
version: 1.4.3.1
|
60
|
+
requirement: *id003
|
61
|
+
name: nokogiri
|
62
|
+
prerelease: false
|
101
63
|
type: :runtime
|
102
|
-
version_requirements: *id005
|
103
64
|
- !ruby/object:Gem::Dependency
|
104
|
-
|
105
|
-
prerelease: false
|
106
|
-
requirement: &id006 !ruby/object:Gem::Requirement
|
107
|
-
none: false
|
65
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
108
66
|
requirements:
|
109
|
-
- - "
|
67
|
+
- - "="
|
110
68
|
- !ruby/object:Gem::Version
|
111
|
-
hash: 25
|
112
69
|
segments:
|
113
70
|
- 0
|
114
|
-
-
|
115
|
-
-
|
116
|
-
version: 0.
|
117
|
-
|
118
|
-
|
71
|
+
- 9
|
72
|
+
- 2
|
73
|
+
version: 0.9.2
|
74
|
+
requirement: *id004
|
75
|
+
name: rake
|
76
|
+
prerelease: false
|
77
|
+
type: :development
|
119
78
|
description: Work with spreadsheets easily in a native ruby format.
|
120
79
|
email:
|
121
80
|
- brad.spaulding@gmail.com
|
@@ -127,6 +86,7 @@ extra_rdoc_files: []
|
|
127
86
|
|
128
87
|
files:
|
129
88
|
- .gitignore
|
89
|
+
- .travis.yml
|
130
90
|
- Gemfile
|
131
91
|
- LICENSE.txt
|
132
92
|
- README.md
|
@@ -136,10 +96,9 @@ files:
|
|
136
96
|
- lib/sheets/parseable.rb
|
137
97
|
- lib/sheets/parsers/base.rb
|
138
98
|
- lib/sheets/parsers/csv_parser.rb
|
139
|
-
- lib/sheets/parsers/
|
140
|
-
- lib/sheets/parsers/
|
141
|
-
- lib/sheets/parsers/
|
142
|
-
- lib/sheets/parsers/roo_patches/roo_patch_29045.rb
|
99
|
+
- lib/sheets/parsers/excel_parser.rb
|
100
|
+
- lib/sheets/parsers/nokogiri_ods_parser.rb
|
101
|
+
- lib/sheets/parsers/nokogiri_xlsx_parser.rb
|
143
102
|
- lib/sheets/renderable.rb
|
144
103
|
- lib/sheets/renderers/base.rb
|
145
104
|
- lib/sheets/renderers/csv_renderer.rb
|
@@ -156,11 +115,11 @@ files:
|
|
156
115
|
- test/parseable_test.rb
|
157
116
|
- test/parsers/basic_parsers_test.rb
|
158
117
|
- test/parsers/csv_parser_test.rb
|
159
|
-
- test/parsers/roo_parser_test.rb
|
160
118
|
- test/renderable_test.rb
|
161
119
|
- test/renderers/basic_renderers_test.rb
|
162
120
|
- test/renderers/csv_renderer_test.rb
|
163
121
|
- test/renderers/excel_renderer_test.rb
|
122
|
+
- test/results.json
|
164
123
|
- test/test_helper.rb
|
165
124
|
has_rdoc: true
|
166
125
|
homepage: https://github.com/bspaulding/Sheets
|
@@ -172,27 +131,23 @@ rdoc_options: []
|
|
172
131
|
require_paths:
|
173
132
|
- lib
|
174
133
|
required_ruby_version: !ruby/object:Gem::Requirement
|
175
|
-
none: false
|
176
134
|
requirements:
|
177
135
|
- - ">="
|
178
136
|
- !ruby/object:Gem::Version
|
179
|
-
hash: 3
|
180
137
|
segments:
|
181
138
|
- 0
|
182
139
|
version: "0"
|
183
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
184
|
-
none: false
|
185
141
|
requirements:
|
186
142
|
- - ">="
|
187
143
|
- !ruby/object:Gem::Version
|
188
|
-
hash: 3
|
189
144
|
segments:
|
190
145
|
- 0
|
191
146
|
version: "0"
|
192
147
|
requirements: []
|
193
148
|
|
194
149
|
rubyforge_project: sheets
|
195
|
-
rubygems_version: 1.
|
150
|
+
rubygems_version: 1.3.6
|
196
151
|
signing_key:
|
197
152
|
specification_version: 3
|
198
153
|
summary: Sheets provides a Facade for importing spreadsheets that gives the application control. Any Spreadsheet can be represented as either (1) a two dimensional array, or (2) an array of hashes. Sheets' goal is to convert any spreadsheet format to one of these native Ruby data structures.
|
@@ -207,9 +162,9 @@ test_files:
|
|
207
162
|
- test/parseable_test.rb
|
208
163
|
- test/parsers/basic_parsers_test.rb
|
209
164
|
- test/parsers/csv_parser_test.rb
|
210
|
-
- test/parsers/roo_parser_test.rb
|
211
165
|
- test/renderable_test.rb
|
212
166
|
- test/renderers/basic_renderers_test.rb
|
213
167
|
- test/renderers/csv_renderer_test.rb
|
214
168
|
- test/renderers/excel_renderer_test.rb
|
169
|
+
- test/results.json
|
215
170
|
- test/test_helper.rb
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'roo'
|
2
|
-
require File.join( File.expand_path(File.dirname(__FILE__)), 'roo_patches.rb' )
|
3
|
-
|
4
|
-
class Sheets::Parsers::RooParser < Sheets::Parsers::Base
|
5
|
-
parses :xls, :xlsx, :ods
|
6
|
-
|
7
|
-
ROO_CLASS = {
|
8
|
-
:xls => Excel,
|
9
|
-
:xlsx => Excelx,
|
10
|
-
:ods => Openoffice
|
11
|
-
}
|
12
|
-
|
13
|
-
def to_array
|
14
|
-
array = []
|
15
|
-
(spreadsheet.first_row..spreadsheet.last_row).each do |row_num|
|
16
|
-
row = []
|
17
|
-
(spreadsheet.first_column..spreadsheet.last_column).each do |column_num|
|
18
|
-
row << spreadsheet.cell(row_num, column_num).to_s
|
19
|
-
end
|
20
|
-
array << row
|
21
|
-
end
|
22
|
-
array
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
def spreadsheet
|
27
|
-
ROO_CLASS[@format.to_sym].new(@file_path)
|
28
|
-
end
|
29
|
-
end
|
@@ -1,116 +0,0 @@
|
|
1
|
-
# RubyForge Patch: 28885 - Fixes to Honor XLSX Base Date Format
|
2
|
-
# NOTE: This fix is *highly* brittle. If roo updates, this may break roo.
|
3
|
-
|
4
|
-
class Excelx
|
5
|
-
|
6
|
-
def initialize(filename, packed=nil, file_warning = :error) #, create = false)
|
7
|
-
super()
|
8
|
-
@file_warning = file_warning
|
9
|
-
@tmpdir = "oo_"+$$.to_s
|
10
|
-
@tmpdir = File.join(ENV['ROO_TMP'], @tmpdir) if ENV['ROO_TMP']
|
11
|
-
unless File.exists?(@tmpdir)
|
12
|
-
FileUtils::mkdir(@tmpdir)
|
13
|
-
end
|
14
|
-
filename = open_from_uri(filename) if filename[0,7] == "http://"
|
15
|
-
filename = unzip(filename) if packed and packed == :zip
|
16
|
-
begin
|
17
|
-
file_type_check(filename,'.xlsx','an Excel-xlsx')
|
18
|
-
@cells_read = Hash.new
|
19
|
-
@filename = filename
|
20
|
-
unless File.file?(@filename)
|
21
|
-
raise IOError, "file #{@filename} does not exist"
|
22
|
-
end
|
23
|
-
@@nr += 1
|
24
|
-
@file_nr = @@nr
|
25
|
-
extract_content(@filename)
|
26
|
-
file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_workbook.xml"))
|
27
|
-
# TODO: @workbook_doc = XML::Parser.io(file).parse
|
28
|
-
@workbook_doc = Nokogiri::XML(file)
|
29
|
-
|
30
|
-
# Set the base date, could be 1900 or 1904 depending on the system of origin.
|
31
|
-
date_base_element = @workbook_doc.search('workbookPr').attribute('date1904')
|
32
|
-
if date_base_element && date_base_element.value.to_i == 1
|
33
|
-
@base_date = Date.parse('1904-01-01')
|
34
|
-
else
|
35
|
-
@base_date = Date.parse('1900-01-01')
|
36
|
-
end
|
37
|
-
@base_datetime = DateTime.parse( @base_date.strftime("%Y-%m-%d") )
|
38
|
-
|
39
|
-
file.close
|
40
|
-
@shared_table = []
|
41
|
-
if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
|
42
|
-
file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
|
43
|
-
#TODO: @sharedstring_doc = XML::Parser.io(file).parse
|
44
|
-
@sharedstring_doc = Nokogiri::XML(file)
|
45
|
-
file.close
|
46
|
-
read_shared_strings(@sharedstring_doc)
|
47
|
-
end
|
48
|
-
@styles_table = []
|
49
|
-
@style_definitions = Array.new # TODO: ??? { |h,k| h[k] = {} }
|
50
|
-
if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
|
51
|
-
file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
|
52
|
-
#TODO: @styles_doc = XML::Parser.io(file).parse
|
53
|
-
@styles_doc = Nokogiri::XML(file)
|
54
|
-
file.close
|
55
|
-
read_styles(@styles_doc)
|
56
|
-
end
|
57
|
-
@sheet_doc = []
|
58
|
-
@sheet_files.each_with_index do |item, i|
|
59
|
-
file = File.new(item)
|
60
|
-
#TODO: @sheet_doc[i] = XML::Parser.io(file).parse
|
61
|
-
@sheet_doc[i] = Nokogiri::XML(file)
|
62
|
-
file.close
|
63
|
-
end
|
64
|
-
ensure
|
65
|
-
#if ENV["roo_local"] != "thomas-p"
|
66
|
-
FileUtils::rm_r(@tmpdir)
|
67
|
-
#end
|
68
|
-
end
|
69
|
-
@default_sheet = self.sheets.first
|
70
|
-
@cell = Hash.new
|
71
|
-
@cell_type = Hash.new
|
72
|
-
@formula = Hash.new
|
73
|
-
@first_row = Hash.new
|
74
|
-
@last_row = Hash.new
|
75
|
-
@first_column = Hash.new
|
76
|
-
@last_column = Hash.new
|
77
|
-
@header_line = 1
|
78
|
-
@excelx_type = Hash.new
|
79
|
-
@excelx_value = Hash.new
|
80
|
-
@s_attribute = Hash.new # TODO: ggf. wieder entfernen nur lokal benoetigt
|
81
|
-
end
|
82
|
-
|
83
|
-
def set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v,
|
84
|
-
excelx_type=nil,
|
85
|
-
excelx_value=nil,
|
86
|
-
s_attribute=nil)
|
87
|
-
key = [y,x+i]
|
88
|
-
@cell_type[sheet] = {} unless @cell_type[sheet]
|
89
|
-
@cell_type[sheet][key] = vt
|
90
|
-
@formula[sheet] = {} unless @formula[sheet]
|
91
|
-
@formula[sheet][key] = formula if formula
|
92
|
-
@cell[sheet] = {} unless @cell[sheet]
|
93
|
-
case @cell_type[sheet][key]
|
94
|
-
when :float
|
95
|
-
@cell[sheet][key] = v.to_f
|
96
|
-
when :string
|
97
|
-
@cell[sheet][key] = str_v
|
98
|
-
when :date
|
99
|
-
@cell[sheet][key] = (@base_date+v.to_i).strftime("%Y-%m-%d")
|
100
|
-
when :datetime
|
101
|
-
@cell[sheet][key] = (@base_datetime+v.to_f).strftime("%Y-%m-%d %H:%M:%S")
|
102
|
-
when :percentage
|
103
|
-
@cell[sheet][key] = v.to_f
|
104
|
-
when :time
|
105
|
-
@cell[sheet][key] = v.to_f*(24*60*60)
|
106
|
-
else
|
107
|
-
@cell[sheet][key] = v
|
108
|
-
end
|
109
|
-
@excelx_type[sheet] = {} unless @excelx_type[sheet]
|
110
|
-
@excelx_type[sheet][key] = excelx_type
|
111
|
-
@excelx_value[sheet] = {} unless @excelx_value[sheet]
|
112
|
-
@excelx_value[sheet][key] = excelx_value
|
113
|
-
@s_attribute[sheet] = {} unless @s_attribute[sheet]
|
114
|
-
@s_attribute[sheet][key] = s_attribute
|
115
|
-
end
|
116
|
-
end
|