simple-excel 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.travis.yml +1 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +87 -0
- data/Rakefile +8 -0
- data/lib/simple-excel.rb +113 -0
- data/lib/simple-excel/ext_string_io.rb +9 -0
- data/lib/simple-excel/version.rb +3 -0
- data/lib/simple-excel/worksheet.rb +68 -0
- data/simple-excel.gemspec +31 -0
- data/spec/simple-excel/ext_string_io_spec.rb +22 -0
- data/spec/simple-excel/worksheet_spec.rb +88 -0
- data/spec/simple-excel_spec.rb +123 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/correct.xls +0 -0
- data/spec/support/empty.xls +0 -0
- data/spec/support/no_data.xls +0 -0
- data/spec/support/not_supported_format.ods +0 -0
- data/spec/support/two_sheets.xls +0 -0
- metadata +197 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
language: ruby
|
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Mikhail Grachev
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# SimpleExcel
|
2
|
+
|
3
|
+
A simple to work with Excel files. Supported formats: xls
|
4
|
+
|
5
|
+
[![Build Status](https://travis-ci.org/mgrachev/simple-excel.png?branch=master)](https://travis-ci.org/mgrachev/simple-excel)
|
6
|
+
[![Coverage Status](https://coveralls.io/repos/mgrachev/simple-excel/badge.png?branch=master)](https://coveralls.io/r/mgrachev/simple-excel?branch=master)
|
7
|
+
[![Dependency Status](https://gemnasium.com/mgrachev/simple-excel.png)](https://gemnasium.com/mgrachev/simple-excel)
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'simple-excel'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install simple-excel
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
Create instance of SimpleExcel:
|
26
|
+
|
27
|
+
excel = SimpleExcel.new('path/to/file', ['ID', 'Value'])
|
28
|
+
|
29
|
+
The second argument passed to the array with the headers that will be used to check the headers contained in the file.
|
30
|
+
|
31
|
+
The first argument can also provide a link to the file:
|
32
|
+
|
33
|
+
excel = SimpleExcel.new('http://link_to_file.com', ['ID', 'Value'])
|
34
|
+
|
35
|
+
To obtain data sufficient to call method `each`:
|
36
|
+
|
37
|
+
excel.each do |row|
|
38
|
+
puts row
|
39
|
+
end
|
40
|
+
|
41
|
+
The variable `row` contains a hash containing the headers and values:
|
42
|
+
|
43
|
+
{
|
44
|
+
'ID' => 1,
|
45
|
+
'Value' => 'Test',
|
46
|
+
'index' => 1 # The row number
|
47
|
+
}
|
48
|
+
|
49
|
+
By default, `each` method compares the titles passed when creating an instance SimpleExcel with headers that are present in the file. If the headers do not match, an exception is thrown. This action can be undone, passed as the first argument to `false`:
|
50
|
+
|
51
|
+
excel.each(false) do |row|
|
52
|
+
puts row
|
53
|
+
end
|
54
|
+
|
55
|
+
Also by default, the `each` method checks filling the fields and if at least one field is not filled in, an exception is thrown. To undo this action, pass `false` as the second argument:
|
56
|
+
|
57
|
+
excel.each(false, false) do |row|
|
58
|
+
puts row
|
59
|
+
end
|
60
|
+
|
61
|
+
If you want to check out not all fields, the third argument can be passed to the array with the headers that should be excluded from the check:
|
62
|
+
|
63
|
+
excel.each(true, true, ['ID']) do |row|
|
64
|
+
puts row
|
65
|
+
end
|
66
|
+
|
67
|
+
To changing the existing data or write new data, may be used such a construction:
|
68
|
+
|
69
|
+
excel.each(true, true, ['ID']) do |row|
|
70
|
+
# excel.worksheet.sheet.row(row['index'])[column number] = something
|
71
|
+
# For example:
|
72
|
+
excel.worksheet.sheet.row(row['index'])[0] = 7 # ID
|
73
|
+
excel.worksheet.sheet.row(row['index'])[1] = 'Angel' # Value
|
74
|
+
end
|
75
|
+
|
76
|
+
To save a file, you must call the method `save_to_output`, which will save the file as a stream:
|
77
|
+
|
78
|
+
io = excel.save_to_output('path/to/file')
|
79
|
+
io.read # Print the contents of the file
|
80
|
+
|
81
|
+
## Contributing
|
82
|
+
|
83
|
+
1. Fork it
|
84
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
85
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
86
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
87
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/simple-excel.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'spreadsheet'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
|
4
|
+
require 'simple-excel/worksheet'
|
5
|
+
require 'simple-excel/ext_string_io'
|
6
|
+
require 'simple-excel/version'
|
7
|
+
|
8
|
+
class SimpleExcel
|
9
|
+
class FileNotFound < StandardError; end
|
10
|
+
class InvalidUrl < StandardError; end
|
11
|
+
class UnsupportedExcelFile < StandardError; end
|
12
|
+
class HeadersMustBeAnArray < StandardError; end
|
13
|
+
class RequiredHeaders < StandardError; end
|
14
|
+
class ExcludeMustBeAnArray < StandardError; end
|
15
|
+
class NotFilledField < StandardError; end
|
16
|
+
|
17
|
+
EXTENSIONS_AVAILABLE = %w(xls)
|
18
|
+
|
19
|
+
# @attr_reader [Object] excel Instance of Spreadsheet::Excel::Workbook
|
20
|
+
# @attr_reader [Array] headers Headers excel file
|
21
|
+
# @attr_reader [Object] worksheet Instance of SimpleExcel::Worksheet
|
22
|
+
attr_reader :excel, :headers, :worksheet
|
23
|
+
|
24
|
+
# Create new instance of SimpleExcel::Core
|
25
|
+
#
|
26
|
+
# @todo Check the supported extensions
|
27
|
+
# Before opening the file to check the supported extension
|
28
|
+
# Use SimpleExcel::Core::EXTENSIONS_AVAILABLE
|
29
|
+
#
|
30
|
+
# @param [String] path_to_file_or_url The path or link to excel file
|
31
|
+
# @param [Array] headers Headers excel file
|
32
|
+
#
|
33
|
+
# @return [Object] Instance of SimpleExcel::Core
|
34
|
+
def initialize(path_to_file_or_url, headers)
|
35
|
+
raise ArgumentError, 'Path to file or url a blank' if path_to_file_or_url.blank?
|
36
|
+
|
37
|
+
# Open URL or file
|
38
|
+
file = if /^http/ =~ path_to_file_or_url
|
39
|
+
begin
|
40
|
+
open(path_to_file_or_url)
|
41
|
+
rescue
|
42
|
+
raise InvalidUrl, "Invalid URL: #{path_to_file_or_url}"
|
43
|
+
end
|
44
|
+
else
|
45
|
+
begin
|
46
|
+
File.open(path_to_file_or_url)
|
47
|
+
rescue Errno::ENOENT
|
48
|
+
raise FileNotFound, "File '#{path_to_file_or_url}' not found"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
begin
|
53
|
+
@excel = Spreadsheet.open(file)
|
54
|
+
rescue
|
55
|
+
raise UnsupportedExcelFile, "File '#{path_to_file_or_url}' not supported"
|
56
|
+
end
|
57
|
+
|
58
|
+
raise RequiredHeaders, 'Headers is required' if headers.blank?
|
59
|
+
raise HeadersMustBeAnArray, 'Headers are not an array' unless headers.instance_of? Array
|
60
|
+
@headers = headers
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [String] Class name
|
64
|
+
def to_s
|
65
|
+
self.class
|
66
|
+
end
|
67
|
+
|
68
|
+
# Pass all rows excel file
|
69
|
+
#
|
70
|
+
# @param [Boolean] check_headers Check headers
|
71
|
+
# @param [Boolean] check_fields Check filled fields
|
72
|
+
# @param [Array] exclude Exclude checking headers
|
73
|
+
#
|
74
|
+
# @yield [row] Row excel file
|
75
|
+
# @yieldparam [Hash] Hash of values with headers
|
76
|
+
def each(check_headers = true, check_fields = true, exclude = [])
|
77
|
+
@worksheet = SimpleExcel::Worksheet.new(@excel, @headers, check_headers)
|
78
|
+
|
79
|
+
@worksheet.each do |row|
|
80
|
+
checking_fill_fields(row, exclude) if check_fields
|
81
|
+
yield row
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Save the excel file to the output
|
86
|
+
#
|
87
|
+
# @param [String] path Path to file
|
88
|
+
# @return [Object] Instance of SimpleExcel::ExtStringIO
|
89
|
+
def save_to_output(path)
|
90
|
+
output = SimpleExcel::ExtStringIO.new
|
91
|
+
@excel.write(output)
|
92
|
+
output.filepath = path
|
93
|
+
return output
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
# Checking fill fields excluding some fields
|
99
|
+
#
|
100
|
+
# @param [Hash] row Row excel file
|
101
|
+
# @param [Array] exclude Exclude checking headers
|
102
|
+
def checking_fill_fields(row, exclude = [])
|
103
|
+
check_headers = @headers.clone
|
104
|
+
if exclude.present?
|
105
|
+
raise ExcludeMustBeAnArray, 'Headers are not an array' unless exclude.instance_of? Array
|
106
|
+
exclude.each{ |column| check_headers.delete(column) }
|
107
|
+
end
|
108
|
+
|
109
|
+
check_headers.each do |name|
|
110
|
+
raise NotFilledField, "Field '#{name}' is not filled" if row[name].blank?
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class SimpleExcel::Worksheet
|
2
|
+
class HeadersDoNotMatch < StandardError; end
|
3
|
+
class FileWithoutData < StandardError; end
|
4
|
+
|
5
|
+
# @attr_reader [Object] excel Instance of Spreadsheet::Excel::Workbook
|
6
|
+
# @attr_reader [Array] headers Headers excel file
|
7
|
+
# @attr_reader [Object] sheet Instance of Spreadsheet::Excel::Worksheet
|
8
|
+
attr_reader :excel, :headers, :sheet
|
9
|
+
|
10
|
+
# Create new instance of SimpleExcel::Worksheet
|
11
|
+
#
|
12
|
+
# @param [Object] excel Instance of Spreadsheet
|
13
|
+
# @param [Array] headers Headers excel file
|
14
|
+
# @param [Boolean] check_headers Check headers
|
15
|
+
#
|
16
|
+
# @return [Object] Instance of SimpleExcel::Worksheet
|
17
|
+
def initialize(excel, headers, check_headers = true)
|
18
|
+
@excel, @headers = excel, headers
|
19
|
+
|
20
|
+
if check_headers
|
21
|
+
@excel.worksheets.each_with_index do |sheet, index|
|
22
|
+
@sheet = @excel.worksheet(index)
|
23
|
+
return @sheet if @headers == sheet.row(0)
|
24
|
+
end
|
25
|
+
raise HeadersDoNotMatch, "File headers do not coincide with #{@headers}"
|
26
|
+
else
|
27
|
+
@sheet = @excel.worksheet(0)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [String] Class name
|
32
|
+
def to_s
|
33
|
+
self.class
|
34
|
+
end
|
35
|
+
|
36
|
+
# Pass all rows excel file
|
37
|
+
#
|
38
|
+
# @yield [row] Row excel file
|
39
|
+
# @yieldparam [Hash] Hash of values with headers
|
40
|
+
def each
|
41
|
+
raise FileWithoutData, 'File contains no data' if no_data?
|
42
|
+
(1..@sheet.last_row_index).each do |i|
|
43
|
+
row = get_values(i)
|
44
|
+
yield row
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# Check data without headers
|
51
|
+
#
|
52
|
+
# @return [Boolean] True if no data or false
|
53
|
+
def no_data?
|
54
|
+
@sheet.last_row_index == 0
|
55
|
+
end
|
56
|
+
|
57
|
+
# Get data from the row
|
58
|
+
#
|
59
|
+
# @param [Fixnum] index Index of row
|
60
|
+
# @return [Hash] Hash of values with headers
|
61
|
+
def get_values(index)
|
62
|
+
active_row = @sheet.row(index)
|
63
|
+
headers_with_values = []
|
64
|
+
@headers.each_with_index { |header, index| headers_with_values << [header, active_row[index]] }
|
65
|
+
headers_with_values << ['index', index]
|
66
|
+
Hash[*headers_with_values.flatten]
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'simple-excel/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'simple-excel'
|
8
|
+
spec.platform = Gem::Platform::RUBY
|
9
|
+
spec.version = SimpleExcel::VERSION
|
10
|
+
spec.authors = ['Mikhail Grachev']
|
11
|
+
spec.email = ['i@mgrachev.com']
|
12
|
+
spec.description = %q{A simple to work with Excel files}
|
13
|
+
spec.summary = %q{A simple to work with Excel files}
|
14
|
+
spec.homepage = 'https://github.com/mgrachev/simple-excel'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files`.split($/)
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_dependency 'spreadsheet', '~> 0.9.0'
|
23
|
+
spec.add_dependency 'activesupport', '~> 3.2.14'
|
24
|
+
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
26
|
+
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 2.14.1'
|
28
|
+
|
29
|
+
spec.add_development_dependency 'yard', '~> 0.8.7.2'
|
30
|
+
spec.add_development_dependency 'redcarpet', '~> 3.0.0' # Markdown implementation (for yard)
|
31
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleExcel::ExtStringIO do
|
4
|
+
let(:file) { File.join('spec', 'support', 'correct.xls') }
|
5
|
+
|
6
|
+
context '#filepath' do
|
7
|
+
it 'set and return the file path' do
|
8
|
+
io = SimpleExcel::ExtStringIO.new
|
9
|
+
io.filepath.should be_nil
|
10
|
+
io.filepath = file
|
11
|
+
io.filepath.should == file
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context '#original_filename' do
|
16
|
+
it 'returns the file name' do
|
17
|
+
io = SimpleExcel::ExtStringIO.new
|
18
|
+
io.filepath = file
|
19
|
+
io.original_filename.should eq File.basename(file)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleExcel::Worksheet do
|
4
|
+
let(:headers) { ['ID', 'Value'] }
|
5
|
+
let(:file) { File.join('spec', 'support', 'correct.xls') }
|
6
|
+
let(:no_data_file) { File.join('spec', 'support', 'no_data.xls') }
|
7
|
+
let(:two_sheets) { File.join('spec', 'support', 'two_sheets.xls') }
|
8
|
+
let(:simple_excel) { SimpleExcel.new(file, headers) }
|
9
|
+
let(:worksheet) { SimpleExcel::Worksheet.new(simple_excel.excel, headers) }
|
10
|
+
|
11
|
+
context '.initialize' do
|
12
|
+
it 'raise an exception if headers do not match' do
|
13
|
+
simple_excel = SimpleExcel.new(no_data_file, ['ID', 'Test'])
|
14
|
+
expect{ SimpleExcel::Worksheet.new(simple_excel.excel, simple_excel.headers) }.to raise_error(
|
15
|
+
SimpleExcel::Worksheet::HeadersDoNotMatch, "File headers do not coincide with #{['ID', 'Test']}"
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'check headers and return sheet' do
|
20
|
+
simple_excel = SimpleExcel.new(two_sheets, headers)
|
21
|
+
worksheet = SimpleExcel::Worksheet.new(simple_excel.excel, simple_excel.headers)
|
22
|
+
|
23
|
+
sheet_index = 0
|
24
|
+
simple_excel.excel.worksheets.each_with_index do |sheet, index|
|
25
|
+
if simple_excel.excel.worksheet(index).row(0) == headers
|
26
|
+
sheet_index = index
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
worksheet.sheet.should_not == simple_excel.excel.worksheet(0)
|
31
|
+
worksheet.sheet.should == simple_excel.excel.worksheet(sheet_index)
|
32
|
+
worksheet.sheet.should be_an_instance_of Spreadsheet::Excel::Worksheet
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns first sheet if check_headers argument set to false' do
|
36
|
+
worksheet = SimpleExcel::Worksheet.new(simple_excel.excel, simple_excel.headers, false)
|
37
|
+
worksheet.sheet.should be_an_instance_of Spreadsheet::Excel::Worksheet
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns instance of SimpleExcel::Worksheet' do
|
41
|
+
worksheet.should be_an_instance_of SimpleExcel::Worksheet
|
42
|
+
worksheet.excel.should be_an_instance_of Spreadsheet::Excel::Workbook
|
43
|
+
worksheet.headers.should be_an_instance_of Array
|
44
|
+
worksheet.sheet.should be_an_instance_of Spreadsheet::Excel::Worksheet
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context '#to_s' do
|
49
|
+
it 'returns name of class' do
|
50
|
+
worksheet.to_s.should eq worksheet.class
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context '#each' do
|
55
|
+
it 'raise an exception if excel file contains no data' do
|
56
|
+
excel = SimpleExcel.new(no_data_file, headers)
|
57
|
+
worksheet = SimpleExcel::Worksheet.new(excel.excel, excel.headers)
|
58
|
+
expect{ worksheet.each }.to raise_error(
|
59
|
+
SimpleExcel::Worksheet::FileWithoutData, 'File contains no data'
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'returns row' do
|
64
|
+
row = worksheet.send(:get_values, 1)
|
65
|
+
expect { |block| worksheet.each(&block) }.to yield_successive_args(row)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context '#no_data?' do
|
70
|
+
it 'return true if excel file contains no data' do
|
71
|
+
excel = SimpleExcel.new(no_data_file, headers)
|
72
|
+
worksheet = SimpleExcel::Worksheet.new(excel.excel, excel.headers)
|
73
|
+
worksheet.send(:no_data?).should be_true
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'return false if excel file with data' do
|
77
|
+
worksheet.send(:no_data?).should be_false
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context '#get_values' do
|
82
|
+
it 'return hash of values with headers' do
|
83
|
+
row = worksheet.send(:get_values, 1)
|
84
|
+
row.should be_an_instance_of Hash
|
85
|
+
row.should include('ID' => 1, 'Value' => 'Test', 'index' => 1)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleExcel do
|
4
|
+
let(:headers) { ['ID', 'Value'] }
|
5
|
+
let(:invalid_url) { 'http://invalid.url' }
|
6
|
+
|
7
|
+
let(:correct_file) { File.join('spec', 'support', 'correct.xls') }
|
8
|
+
let(:no_data_file) { File.join('spec', 'support', 'no_data.xls') }
|
9
|
+
let(:not_found_file) { File.join('spec', 'support', 'not_found') }
|
10
|
+
let(:not_supported_format_file) { File.join('spec', 'support', 'not_supported_format.ods') }
|
11
|
+
|
12
|
+
let(:simple_excel) { SimpleExcel.new(correct_file, headers) }
|
13
|
+
|
14
|
+
context '::EXTENSIONS_AVAILABLE' do
|
15
|
+
it 'returns array of available extensions' do
|
16
|
+
SimpleExcel::EXTENSIONS_AVAILABLE.should be_an_instance_of Array
|
17
|
+
SimpleExcel::EXTENSIONS_AVAILABLE.should == ['xls']
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context '.initialize' do
|
22
|
+
it 'raise an exception if calling method without arguments' do
|
23
|
+
expect{ SimpleExcel.new }.to raise_error(
|
24
|
+
ArgumentError, 'wrong number of arguments (0 for 2)'
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'raise an exception if first argument is blank' do
|
29
|
+
expect{ SimpleExcel.new('', '') }.to raise_error(
|
30
|
+
ArgumentError, 'Path to file or url a blank'
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'raise an exception if url is invalid' do
|
35
|
+
expect{ SimpleExcel.new(invalid_url, '') }.to raise_error(
|
36
|
+
SimpleExcel::InvalidUrl, "Invalid URL: #{invalid_url}"
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'raise an exception if file not found' do
|
41
|
+
expect{ SimpleExcel.new(not_found_file, '') }.to raise_error(
|
42
|
+
SimpleExcel::FileNotFound, "File '#{not_found_file}' not found"
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'raise an exception if file does not open' do
|
47
|
+
expect{ SimpleExcel.new(not_supported_format_file, '') }.to raise_error(
|
48
|
+
SimpleExcel::UnsupportedExcelFile, "File '#{not_supported_format_file}' not supported"
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'raise an exception if headers is blank' do
|
53
|
+
expect{ SimpleExcel.new(correct_file, '') }.to raise_error(
|
54
|
+
SimpleExcel::RequiredHeaders, 'Headers is required'
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'raise and exception if second argument exists, but is not an Array' do
|
59
|
+
expect{ SimpleExcel.new(correct_file, 'ID, VALUE') }.to raise_error(
|
60
|
+
SimpleExcel::HeadersMustBeAnArray, 'Headers are not an array'
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should set @excel' do
|
65
|
+
simple_excel.excel.should be_an_instance_of Spreadsheet::Excel::Workbook
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should set @headers' do
|
69
|
+
simple_excel.headers.should be_an_instance_of(Array)
|
70
|
+
simple_excel.headers.should eq headers
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'open excel file and return instance of SimpleExcel' do
|
74
|
+
simple_excel.should be_an_instance_of SimpleExcel
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context '#to_s' do
|
79
|
+
it 'returns name of class' do
|
80
|
+
simple_excel.to_s.should eq simple_excel.class
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context '#each' do
|
85
|
+
it 'raise an exception if excel file contains no data' do
|
86
|
+
simple_excel = SimpleExcel.new(no_data_file, headers)
|
87
|
+
expect{ simple_excel.each }.to raise_error(
|
88
|
+
SimpleExcel::Worksheet::FileWithoutData, 'File contains no data'
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'returns row' do
|
93
|
+
worksheet = SimpleExcel::Worksheet.new(simple_excel.excel, simple_excel.headers)
|
94
|
+
row = worksheet.send(:get_values, 1)
|
95
|
+
expect { |block| simple_excel.each(&block) }.to yield_successive_args(row)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context '#checking_fill_fields' do
|
100
|
+
it 'raise an exception if exclude argument is not Array' do
|
101
|
+
worksheet = SimpleExcel::Worksheet.new(simple_excel.excel, simple_excel.headers)
|
102
|
+
row = worksheet.send(:get_values, 1)
|
103
|
+
expect{ simple_excel.send(:checking_fill_fields, row, 'test') }.to raise_error(
|
104
|
+
SimpleExcel::ExcludeMustBeAnArray, 'Headers are not an array'
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'raise an exception if field is not filled' do
|
109
|
+
simple_excel = SimpleExcel.new(no_data_file, headers)
|
110
|
+
worksheet = SimpleExcel::Worksheet.new(simple_excel.excel, simple_excel.headers)
|
111
|
+
row = worksheet.send(:get_values, 1)
|
112
|
+
expect{ simple_excel.send(:checking_fill_fields, row) }.to raise_error(
|
113
|
+
SimpleExcel::NotFilledField, "Field '#{headers.first}' is not filled"
|
114
|
+
)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context '#save_to_output' do
|
119
|
+
it 'returns instance of SimpleExcel::ExtStringIO' do
|
120
|
+
simple_excel.save_to_output(correct_file).should be_an_instance_of SimpleExcel::ExtStringIO
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'coveralls'
|
2
|
+
Coveralls.wear!
|
3
|
+
|
4
|
+
require 'simple-excel'
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
8
|
+
config.run_all_when_everything_filtered = true
|
9
|
+
config.filter_run :focus
|
10
|
+
|
11
|
+
config.fail_fast = true
|
12
|
+
config.color_enabled = true
|
13
|
+
|
14
|
+
config.order = 'random'
|
15
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple-excel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mikhail Grachev
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-10-08 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: spreadsheet
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.9.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.9.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: activesupport
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 3.2.14
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 3.2.14
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bundler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.3'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 2.14.1
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 2.14.1
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: yard
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 0.8.7.2
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.8.7.2
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: redcarpet
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 3.0.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 3.0.0
|
126
|
+
description: A simple to work with Excel files
|
127
|
+
email:
|
128
|
+
- i@mgrachev.com
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- .gitignore
|
134
|
+
- .rspec
|
135
|
+
- .travis.yml
|
136
|
+
- .yardopts
|
137
|
+
- CHANGELOG.md
|
138
|
+
- Gemfile
|
139
|
+
- LICENSE.txt
|
140
|
+
- README.md
|
141
|
+
- Rakefile
|
142
|
+
- lib/simple-excel.rb
|
143
|
+
- lib/simple-excel/ext_string_io.rb
|
144
|
+
- lib/simple-excel/version.rb
|
145
|
+
- lib/simple-excel/worksheet.rb
|
146
|
+
- simple-excel.gemspec
|
147
|
+
- spec/simple-excel/ext_string_io_spec.rb
|
148
|
+
- spec/simple-excel/worksheet_spec.rb
|
149
|
+
- spec/simple-excel_spec.rb
|
150
|
+
- spec/spec_helper.rb
|
151
|
+
- spec/support/correct.xls
|
152
|
+
- spec/support/empty.xls
|
153
|
+
- spec/support/no_data.xls
|
154
|
+
- spec/support/not_supported_format.ods
|
155
|
+
- spec/support/two_sheets.xls
|
156
|
+
homepage: https://github.com/mgrachev/simple-excel
|
157
|
+
licenses:
|
158
|
+
- MIT
|
159
|
+
post_install_message:
|
160
|
+
rdoc_options: []
|
161
|
+
require_paths:
|
162
|
+
- lib
|
163
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
164
|
+
none: false
|
165
|
+
requirements:
|
166
|
+
- - ! '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
segments:
|
170
|
+
- 0
|
171
|
+
hash: -890326845897824257
|
172
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
|
+
none: false
|
174
|
+
requirements:
|
175
|
+
- - ! '>='
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
version: '0'
|
178
|
+
segments:
|
179
|
+
- 0
|
180
|
+
hash: -890326845897824257
|
181
|
+
requirements: []
|
182
|
+
rubyforge_project:
|
183
|
+
rubygems_version: 1.8.23
|
184
|
+
signing_key:
|
185
|
+
specification_version: 3
|
186
|
+
summary: A simple to work with Excel files
|
187
|
+
test_files:
|
188
|
+
- spec/simple-excel/ext_string_io_spec.rb
|
189
|
+
- spec/simple-excel/worksheet_spec.rb
|
190
|
+
- spec/simple-excel_spec.rb
|
191
|
+
- spec/spec_helper.rb
|
192
|
+
- spec/support/correct.xls
|
193
|
+
- spec/support/empty.xls
|
194
|
+
- spec/support/no_data.xls
|
195
|
+
- spec/support/not_supported_format.ods
|
196
|
+
- spec/support/two_sheets.xls
|
197
|
+
has_rdoc:
|