sheets 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .DS_Store
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
6
+ doc/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in sheets.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2011 Bradley J. Spaulding
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,92 @@
1
+ Sheets
2
+ ==========
3
+
4
+ Sheets is a Facade on top of many spreadsheet formats, presenting them as simple, unified, native ruby arrays. It is intended to allow applications to easily import data from a wide variety of spreadsheet formats.
5
+
6
+ With Sheets, all cell values are strings representing the final, evaluated value of the cell.
7
+
8
+ This does mean that, in some cases, you will be casting data back into its native format.
9
+
10
+ However, this eliminates the need to deal with multiple spreadsheet formats and normalize data types in your application logic.
11
+
12
+ Your application only needs to care about the layout of the spreadsheet, and the format *you* want the data in.
13
+
14
+ Usage
15
+ ----------
16
+
17
+ To retrieve a list of parseable spreadsheet formats at runtime:
18
+
19
+ Sheets::Base.parseable_formats # => ["csv", "xls", "xlsx", "ods"]
20
+
21
+ To open a spreadsheet, pass initialize Sheets::Base.new either a file path:
22
+
23
+ Sheets::Base.new( '/path/to/a/spreadsheet.(format)' )
24
+
25
+ or a file handle:
26
+
27
+ Sheets::Base.new( File.open('/path/to/a/spreadsheet.(format)') )
28
+
29
+ By default, Sheets will use the basename of the file to detect the spreadsheet type. You can override this by passing in the :format option:
30
+
31
+ *This is necessary if you pass Sheets an IO object, like StringIO, that doesn't have metadata like a filename/path.*
32
+
33
+ Sheets::Base.new( an_io_object_with_spreadsheet_data, :format => :xls )
34
+
35
+ Once you have imported a sheet, you can either grab the array:
36
+
37
+ sheet = Sheets::Base.new( # ... )
38
+ sheet.to_array
39
+
40
+ or utilize any of the Enumerable functions on the sheet:
41
+
42
+ sheet = Sheets::Base.new( # ... )
43
+ sheet.collect {|row| puts row }
44
+
45
+ Additionally, you may output the sheet in any of the renderable formats:
46
+
47
+ Sheets::Base.renderable_formats # => ['csv', 'xls']
48
+ sheet = Sheets::Base.new( file )
49
+ sheet.to_csv
50
+ sheet.to_xls
51
+
52
+ Sheets::Base will skip the parsing phase if initialized with an array, allowing you to render arrays to a native spreadsheet format:
53
+
54
+ my_awesome_data = [ ["Date", "Spent", "Earned"], ["2011-04-11", "$0.00", "$5,000.00"] ]
55
+ sheet = Sheets::Base.new( my_awesome_data )
56
+ sheet.to_csv
57
+ sheet.to_xls
58
+
59
+ Adding Parsers
60
+ ------------
61
+
62
+ Parsers subclass Sheets::Parsers::Base, live in the Sheets::Parsers namespace and should respond to two methods:
63
+
64
+ * formats: returns an array of string format names (file extensions) that this parser class supports
65
+ * to_array: returns a simple array representation of the spreadsheet.
66
+
67
+ Parsers have access to @data and @format in order to do their parsing. See lib/sheets/parsers/* for examples.
68
+
69
+ Adding Renderers
70
+ ------------
71
+
72
+ Renderers subclass Sheets::Renderers::Base, live in the Sheets::Renderers namespace and should respond to:
73
+
74
+ * formats: returns an array of string format names that this parser class supports
75
+ * to\_#{format}: For each format that a renderer supports, it should respond to "to\_#{format}", returning the file data of that format.
76
+
77
+ Renderers are given access to the results of Sheets::Base#to_array as @data. See lib/sheets/renderers/* for examples.
78
+
79
+ License
80
+ ----------
81
+
82
+ Sheets is licensed under the [MIT License](http://www.opensource.org/licenses/mit-license.php).
83
+
84
+ Please note that Sheets is dependent upon the Spreadsheet gem, which is licensed under the [GPLv3](http://www.opensource.org/licenses/gpl-3.0.html).
85
+
86
+ Credits
87
+ ----------
88
+
89
+ Sheets takes full advantage of the great work done in these gems:
90
+
91
+ * [Spreadsheet](http://spreadsheet.rubyforge.org/) - mhatakeyama@ywesee.com, zdavatz@ywesee.com
92
+ * [Roo](http://roo.rubyforge.org/) - [Thomas Preymesser](mailto:thopre@gmail.com)
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ task :test do
5
+ require File.join(File.expand_path(File.dirname(__FILE__)), 'test', 'test_helper.rb')
6
+ Dir[ File.join(File.expand_path(File.dirname(__FILE__)), 'test', '**', '*_test.rb') ].each {|file| require file }
7
+ end
data/lib/sheets.rb ADDED
@@ -0,0 +1,21 @@
1
+ module Sheets
2
+ module Parsers; end
3
+ module Renderers; end
4
+
5
+ class UnsupportedSpreadsheetFormatError < StandardError; end
6
+ end
7
+
8
+ lib_path = File.expand_path(File.dirname(__FILE__))
9
+
10
+ # Load Parsers
11
+ require File.join lib_path, 'sheets', 'parseable.rb'
12
+ require File.join lib_path, 'sheets', 'parsers', 'base.rb'
13
+ Dir[ File.join lib_path, 'sheets', 'parsers', '*_parser.rb' ].each {|file| require file }
14
+
15
+ # Load Renderers
16
+ require File.join lib_path, 'sheets', 'renderable.rb'
17
+ require File.join lib_path, 'sheets', 'renderers', 'base.rb'
18
+ Dir[ File.join lib_path, 'sheets', 'renderers', '*_renderer.rb' ].each {|file| require file }
19
+
20
+ # Load Sheets::Base
21
+ require File.join lib_path, 'sheets', 'base.rb'
@@ -0,0 +1,28 @@
1
+ module Sheets
2
+ class Base
3
+ include Parseable
4
+ include Renderable
5
+
6
+ def initialize(file, options = {})
7
+ if file.is_a?(Array)
8
+ @data = file
9
+ @extension = options[:format].to_s
10
+ return
11
+ end
12
+
13
+ file = File.open(file.to_s) unless file.respond_to? :read
14
+ options[:format] ||= File.basename(file.path || "").split('.')[-1]
15
+
16
+ @data = file.read
17
+ @extension = options[:format].to_s
18
+ @file_path = File.expand_path(file.path || "")
19
+
20
+ raise UnsupportedSpreadsheetFormatError, "Couldn't find a parser for the '#{@extension}' format." if parser.nil?
21
+ end
22
+
23
+ alias_method :default_to_array, :to_array
24
+ def to_array
25
+ @data.is_a?(Array) ? @data : default_to_array
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ module Sheets
2
+ module Parseable
3
+ include Enumerable
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def parseable_formats
11
+ Sheets::Parsers.constants.collect {|constant_name| Sheets::Parsers.const_get(constant_name) }.map(&:formats).flatten.uniq
12
+ end
13
+ end
14
+
15
+ def each
16
+ to_array.each {|row| yield row }
17
+ end
18
+
19
+ def to_array
20
+ parser.send(:to_array)
21
+ end
22
+
23
+ private
24
+ def parser_class
25
+ classes = Sheets::Parsers.constants.map do |constant_name|
26
+ constant = Sheets::Parsers.const_get(constant_name)
27
+ constant if constant && constant.respond_to?(:formats) && constant.formats.map(&:to_s).include?(@extension)
28
+ end
29
+
30
+ classes.delete(nil)
31
+
32
+ classes.first
33
+ end
34
+
35
+ def parser
36
+ @parser ||= parser_class.new(@data, @extension, @file_path) unless parser_class.nil?
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,23 @@
1
+ class Sheets::Parsers::Base
2
+ def initialize(data, format, file_path)
3
+ @data = data
4
+ @format = format
5
+ @file_path = file_path
6
+ end
7
+
8
+ def io
9
+ StringIO.new(@data)
10
+ end
11
+
12
+ def self.parses(*args)
13
+ self.formats = args.map(&:to_s)
14
+ end
15
+
16
+ def self.formats
17
+ @formats ||= []
18
+ end
19
+
20
+ def self.formats=(new_formats)
21
+ @formats = new_formats
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ require 'csv'
2
+
3
+ class Sheets::Parsers::CSVParser < Sheets::Parsers::Base
4
+ parses :csv
5
+
6
+ def to_array
7
+ CSV.parse( @data )
8
+ end
9
+ end
@@ -0,0 +1,28 @@
1
+ require 'roo'
2
+
3
+ class Sheets::Parsers::RooParser < Sheets::Parsers::Base
4
+ parses :xls, :xlsx, :ods
5
+
6
+ ROO_CLASS = {
7
+ :xls => Excel,
8
+ :xlsx => Excelx,
9
+ :ods => Openoffice
10
+ }
11
+
12
+ def to_array
13
+ array = []
14
+ (spreadsheet.first_row..spreadsheet.last_row).each do |row_num|
15
+ row = []
16
+ (spreadsheet.first_column..spreadsheet.last_column).each do |column_num|
17
+ row << spreadsheet.cell(row_num, column_num).to_s
18
+ end
19
+ array << row
20
+ end
21
+ array
22
+ end
23
+
24
+ private
25
+ def spreadsheet
26
+ ROO_CLASS[@format.to_sym].new(@file_path)
27
+ end
28
+ end
@@ -0,0 +1,36 @@
1
+ module Sheets
2
+ module Renderable
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def renderable_formats
9
+ Sheets::Renderers.constants.collect {|constant_name| Sheets::Renderers.const_get(constant_name) }.map(&:formats).flatten.uniq
10
+ end
11
+ end
12
+
13
+ def method_missing(method_name, *args, &block)
14
+ match = method_name.to_s.match(/\Ato_(.*)/i)
15
+ format = match[1] unless match.nil?
16
+
17
+ format.nil? || !self.class.renderable_formats.include?(format) ? super(method_name, args, block) : renderer(format).send(method_name)
18
+ end
19
+
20
+ private
21
+ def renderer_class(format)
22
+ classes = Sheets::Renderers.constants.map do |constant_name|
23
+ constant = Sheets::Renderers.const_get(constant_name)
24
+ constant if constant && constant.respond_to?(:formats) && constant.formats.map(&:to_s).include?(format)
25
+ end
26
+
27
+ classes.delete(nil)
28
+
29
+ classes.first
30
+ end
31
+
32
+ def renderer(format = @extension)
33
+ @renderer ||= renderer_class(format).new(to_array, format) unless renderer_class(format).nil?
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ class Sheets::Renderers::Base
2
+ def initialize(data, format)
3
+ @data = data
4
+ @format = format
5
+ end
6
+
7
+ def self.renders(*args)
8
+ self.formats = args.map(&:to_s)
9
+ end
10
+
11
+ def self.formats
12
+ @formats ||= []
13
+ end
14
+
15
+ def self.formats=(new_formats)
16
+ @formats = new_formats
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ class Sheets::Renderers::CSVRenderer < Sheets::Renderers::Base
2
+ renders :csv
3
+
4
+ def to_csv
5
+ @data.collect {|row| row.join(',') }.join("\n")
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ class Sheets::Renderers::ExcelRenderer < Sheets::Renderers::Base
2
+ renders :xls
3
+
4
+ def to_xls
5
+ workbook = Spreadsheet::Excel::Workbook.new
6
+ worksheet = Spreadsheet::Excel::Worksheet.new
7
+ workbook.add_worksheet(worksheet)
8
+
9
+ @data.each_with_index do |row, row_index|
10
+ row.each_with_index do |cell, col_index|
11
+ worksheet[row_index, col_index] = cell
12
+ end
13
+ end
14
+
15
+ # Tried to use StringIO here, but ran into encoding issues with Ruby 1.8.7.
16
+ file_path = "tmp_excel_render_#{Time.now.to_i}"
17
+ File.open(file_path, 'w+') {|file| workbook.write(file) }
18
+ File.read(file_path)
19
+ ensure
20
+ File.delete( file_path ) if File.exists?( file_path )
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module Sheets
2
+ VERSION = "0.9.0"
3
+ end
data/sheets.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "sheets/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "sheets"
7
+ s.version = Sheets::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Bradley J. Spaulding"]
10
+ s.email = ["brad.spaulding@gmail.com"]
11
+ s.homepage = "https://github.com/bspaulding/Sheets"
12
+ s.summary = %q{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.}
13
+ s.description = %q{Work with spreadsheets easily in a native ruby format.}
14
+
15
+ s.rubyforge_project = "sheets"
16
+
17
+ s.add_dependency('roo', '>= 1.9.3')
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+ end
data/test/base_test.rb ADDED
@@ -0,0 +1,19 @@
1
+ class TestBase < Test::Unit::TestCase
2
+ EXAMPLE_DATA = [
3
+ ["Date", "Impressions", "Clicks", "Actions"],
4
+ ["2011-01-01", "10", "10", "10"],
5
+ ["2011-01-02", "10", "10", "10"],
6
+ ["2011-01-03", "10", "10", "10"],
7
+ ["2011-01-04", "10", "10", "10"],
8
+ ["2011-01-05", "10", "10", "10"],
9
+ ["2011-01-06", "10", "10", "10"],
10
+ ["2011-01-07", "10", "10", "10"],
11
+ ["2011-01-08", "10", "10", "10"],
12
+ ["2011-01-09", "10", "10", "10"],
13
+ ["2011-01-10", "10", "10", "10"]
14
+ ]
15
+
16
+ def test_initialize_with_array
17
+ assert_equal EXAMPLE_DATA, Sheets::Base.new( EXAMPLE_DATA ).to_array
18
+ end
19
+ end
@@ -0,0 +1,11 @@
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
Binary file
Binary file
Binary file
@@ -0,0 +1,7 @@
1
+ def test_classes_for_collection(collection, &block)
2
+ collection.each do |object|
3
+ test_class = Class.new(Test::Unit::TestCase)
4
+ Object.const_set("Test#{object.to_s.split(':')[-1]}Interface", test_class)
5
+ test_class.instance_exec(object, &block)
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ class TestParseable < Test::Unit::TestCase
2
+ Sheets::Base.parseable_formats.each do |format|
3
+ define_method "test_sheet_parses_#{format}" do
4
+ assert_nothing_raised do
5
+ Sheets::Base.new( File.join('test', 'data', "simple.#{format}") ).to_array
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ parser_classes = (Sheets::Parsers.constants - ["Base"]).map {|constant_name| Sheets::Parsers.const_get(constant_name) }
2
+
3
+ test_classes_for_collection parser_classes do |parser_class|
4
+ define_method :test_provides_formats do
5
+ assert parser_class.respond_to? :formats, "#{parser_class} doesn't respond_to formats."
6
+ end
7
+
8
+ define_method :test_formats_not_empty do
9
+ assert !parser_class.formats.empty?, "#{parser_class} doesn't render any formats."
10
+ end
11
+
12
+ parser_class.formats.each do |format|
13
+ define_method "test_#{format}_to_array" do
14
+ parser = parser_class.new([], format, nil)
15
+ assert parser.respond_to?("to_array"), "#{parser.inspect} doesn't respond to to_array"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,37 @@
1
+ class TestCSVParser < Test::Unit::TestCase
2
+
3
+ def test_to_array
4
+ file_path = generate_test_spreadsheet
5
+ assert_equal Sheets::Base.new( file_path ).to_array, example_spreadsheet_data
6
+ ensure
7
+ File.delete( file_path ) if File.exists?( file_path )
8
+ end
9
+
10
+ private
11
+ def example_spreadsheet_data
12
+ [
13
+ ["Date", "Impressions", "Clicks", "Actions"],
14
+ ["2011-01-01", "10", "10", "10"],
15
+ ["2011-01-02", "10", "10", "10"],
16
+ ["2011-01-03", "10", "10", "10"],
17
+ ["2011-01-04", "10", "10", "10"],
18
+ ["2011-01-05", "10", "10", "10"],
19
+ ["2011-01-06", "10", "10", "10"],
20
+ ["2011-01-07", "10", "10", "10"],
21
+ ["2011-01-08", "10", "10", "10"],
22
+ ["2011-01-09", "10", "10", "10"],
23
+ ["2011-01-10", "10", "10", "10"]
24
+ ]
25
+ end
26
+
27
+ def generate_test_spreadsheet
28
+ filename = "test_simple_#{Time.new.to_i}.csv"
29
+ file_path = File.join('.', filename)
30
+
31
+ File.open( file_path, 'w+' ) do |file|
32
+ file.write( example_spreadsheet_data.collect {|row| row.join(',') }.join("\n") )
33
+ end
34
+
35
+ file_path
36
+ end
37
+ end
@@ -0,0 +1,8 @@
1
+ class TestRenderable < Test::Unit::TestCase
2
+ Sheets::Base.renderable_formats.each do |renderable_format|
3
+ define_method "test_sheet_responds_to_#{renderable_format}" do
4
+ sheet = Sheets::Base.new( File.join('test', 'data', 'simple.csv') )
5
+ assert_nothing_raised { sheet.send("to_#{renderable_format}") }
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,18 @@
1
+ renderer_classes = (Sheets::Renderers.constants - ["Base"]).map {|constant_name| Sheets::Renderers.const_get(constant_name) }
2
+
3
+ test_classes_for_collection renderer_classes do |renderer_class|
4
+ define_method :test_provides_formats do
5
+ assert renderer_class.respond_to? :formats, "#{renderer_class} doesn't respond_to formats."
6
+ end
7
+
8
+ define_method :test_formats_not_empty do
9
+ assert !renderer_class.formats.empty?, "#{renderer_class} doesn't render any formats."
10
+ end
11
+
12
+ renderer_class.formats.each do |format|
13
+ define_method "test_to_#{format}" do
14
+ renderer = renderer_class.new([], format)
15
+ assert renderer.respond_to?("to_#{format}"), "#{renderer.inspect} doesn't respond to to_#{format}"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ class TestCSVRenderer < Test::Unit::TestCase
2
+
3
+ def test_to_csv
4
+ renderer = Sheets::Renderers::CSVRenderer.new(example_spreadsheet_data, :csv)
5
+
6
+ assert_equal renderer.to_csv, example_spreadsheet_data.collect {|row| row.join(',') }.join("\n")
7
+ end
8
+
9
+ private
10
+ def example_spreadsheet_data
11
+ [
12
+ ["Date", "Impressions", "Clicks", "Actions"],
13
+ ["2011-01-01", "10", "10", "10"],
14
+ ["2011-01-02", "10", "10", "10"],
15
+ ["2011-01-03", "10", "10", "10"],
16
+ ["2011-01-04", "10", "10", "10"],
17
+ ["2011-01-05", "10", "10", "10"],
18
+ ["2011-01-06", "10", "10", "10"],
19
+ ["2011-01-07", "10", "10", "10"],
20
+ ["2011-01-08", "10", "10", "10"],
21
+ ["2011-01-09", "10", "10", "10"],
22
+ ["2011-01-10", "10", "10", "10"]
23
+ ]
24
+ end
25
+ end
@@ -0,0 +1,42 @@
1
+ class TestExcelRenderer < Test::Unit::TestCase
2
+
3
+ EXAMPLE_DATA = [
4
+ ["Date", "Impressions", "Clicks", "Actions"],
5
+ ["2011-01-01", "10", "10", "10"],
6
+ ["2011-01-02", "10", "10", "10"],
7
+ ["2011-01-03", "10", "10", "10"],
8
+ ["2011-01-04", "10", "10", "10"],
9
+ ["2011-01-05", "10", "10", "10"],
10
+ ["2011-01-06", "10", "10", "10"],
11
+ ["2011-01-07", "10", "10", "10"],
12
+ ["2011-01-08", "10", "10", "10"],
13
+ ["2011-01-09", "10", "10", "10"],
14
+ ["2011-01-10", "10", "10", "10"]
15
+ ]
16
+
17
+ def test_to_xls
18
+ renderer = Sheets::Renderers::ExcelRenderer.new(EXAMPLE_DATA, :xls)
19
+
20
+ file_path = File.expand_path( File.join('test', 'data', "excel_render_test_#{Time.now.to_i}.xls") )
21
+ File.open(file_path, 'w+') {|file| file.write(renderer.to_xls) }
22
+
23
+ assert_equal EXAMPLE_DATA, Sheets::Base.new( file_path ).to_array
24
+ ensure
25
+ File.delete( file_path ) if File.exists?( file_path )
26
+ end
27
+
28
+ Sheets::Base.parseable_formats.each do |parseable_format|
29
+ define_method "test_#{parseable_format}_to_xls" do
30
+ begin
31
+ sheet = Sheets::Base.new( File.join('test', 'data', "simple.#{parseable_format}") )
32
+
33
+ file_path = File.expand_path( File.join('test', 'data', "excel_render_test_#{Time.now.to_i}.xls") )
34
+ File.open(file_path, 'w+') {|file| file.write(sheet.to_xls) }
35
+
36
+ assert_equal sheet.to_array, Sheets::Base.new( file_path ).to_array
37
+ ensure
38
+ File.delete( file_path ) if File.exists?( file_path )
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,6 @@
1
+ require 'test/unit'
2
+
3
+ puts 'Loading Test Generators'
4
+ Dir[ File.join(File.expand_path(File.dirname(__FILE__)), 'generators', '*.rb') ].each {|file| puts "- #{file}"; require file }
5
+
6
+ require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib', 'sheets.rb')
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sheets
3
+ version: !ruby/object:Gem::Version
4
+ hash: 59
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 9
9
+ - 0
10
+ version: 0.9.0
11
+ platform: ruby
12
+ authors:
13
+ - Bradley J. Spaulding
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-04-11 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: roo
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 53
30
+ segments:
31
+ - 1
32
+ - 9
33
+ - 3
34
+ version: 1.9.3
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: Work with spreadsheets easily in a native ruby format.
38
+ email:
39
+ - brad.spaulding@gmail.com
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - Gemfile
49
+ - LICENSE.txt
50
+ - README.md
51
+ - Rakefile
52
+ - lib/sheets.rb
53
+ - lib/sheets/base.rb
54
+ - lib/sheets/parseable.rb
55
+ - lib/sheets/parsers/base.rb
56
+ - lib/sheets/parsers/csv_parser.rb
57
+ - lib/sheets/parsers/roo_parser.rb
58
+ - lib/sheets/renderable.rb
59
+ - lib/sheets/renderers/base.rb
60
+ - lib/sheets/renderers/csv_renderer.rb
61
+ - lib/sheets/renderers/excel_renderer.rb
62
+ - lib/sheets/version.rb
63
+ - sheets.gemspec
64
+ - test/base_test.rb
65
+ - test/data/simple.csv
66
+ - test/data/simple.ods
67
+ - test/data/simple.xls
68
+ - test/data/simple.xlsx
69
+ - test/generators/test_classes.rb
70
+ - test/parseable_test.rb
71
+ - test/parsers/basic_parsers_test.rb
72
+ - test/parsers/csv_parser_test.rb
73
+ - test/renderable_test.rb
74
+ - test/renderers/basic_renderers_test.rb
75
+ - test/renderers/csv_renderer_test.rb
76
+ - test/renderers/excel_renderer_test.rb
77
+ - test/test_helper.rb
78
+ has_rdoc: true
79
+ homepage: https://github.com/bspaulding/Sheets
80
+ licenses: []
81
+
82
+ post_install_message:
83
+ rdoc_options: []
84
+
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ requirements: []
106
+
107
+ rubyforge_project: sheets
108
+ rubygems_version: 1.5.0
109
+ signing_key:
110
+ specification_version: 3
111
+ 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.
112
+ test_files:
113
+ - test/base_test.rb
114
+ - test/data/simple.csv
115
+ - test/data/simple.ods
116
+ - test/data/simple.xls
117
+ - test/data/simple.xlsx
118
+ - test/generators/test_classes.rb
119
+ - test/parseable_test.rb
120
+ - test/parsers/basic_parsers_test.rb
121
+ - test/parsers/csv_parser_test.rb
122
+ - test/renderable_test.rb
123
+ - test/renderers/basic_renderers_test.rb
124
+ - test/renderers/csv_renderer_test.rb
125
+ - test/renderers/excel_renderer_test.rb
126
+ - test/test_helper.rb