sheet2hash 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +62 -0
- data/Rakefile +1 -0
- data/lib/sheet2hash/errors.rb +4 -0
- data/lib/sheet2hash/options.rb +16 -0
- data/lib/sheet2hash/version.rb +7 -0
- data/lib/sheet2hash.rb +162 -0
- data/sheet2hash.gemspec +27 -0
- metadata +110 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2013 Wei-Ming Wu
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License"); you
|
4
|
+
may not use this file except in compliance with the License. You may
|
5
|
+
obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
12
|
+
implied. See the License for the specific language governing
|
13
|
+
permissions and limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Sheet2hash
|
2
|
+
|
3
|
+
Convert Excel or Spreadsheet to Ruby hash
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'sheet2hash'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install sheet2hash
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Basic:
|
22
|
+
|
23
|
+
wb = Sheet2hash.workbook.new 'path/to/your/excel_or_spreadsheet'
|
24
|
+
wb.to_a # convert default sheet to array of hash
|
25
|
+
# [{ field1 => data, field2 => data, ...}, { field1 => data, field2 => data, ...}, ...]
|
26
|
+
# each hash is a row of sheet
|
27
|
+
# the first row is used to be the keys of hash
|
28
|
+
wb.to_h # convert all sheets to hash
|
29
|
+
# the output will be { 'name_of_sheet' => [{ field => data, ... }, ...] }
|
30
|
+
|
31
|
+
Advanced:
|
32
|
+
|
33
|
+
# All sheets are count from 1, NOT 0
|
34
|
+
wb.sheets # list all sheets in the workbook
|
35
|
+
wb.sheet # show the name of current workbook
|
36
|
+
wb.turn_to(2) # make sheet 2 as current sheet
|
37
|
+
wb.turn_to('name_of_the_3rd_sheet') # make sheet 3 as current sheet
|
38
|
+
|
39
|
+
Options:
|
40
|
+
|
41
|
+
# All rows, columns are count from 1, NOT 0
|
42
|
+
wb = Sheet2hash.workbook.new 'path/to/your/excel_or_spreadsheet',
|
43
|
+
:header => 3, # use specific row as header
|
44
|
+
:header => ['col1', 'col2', ...], # use self-defined header
|
45
|
+
:start => 4, # start at row 4
|
46
|
+
:end => 20, # end at row 20
|
47
|
+
:keep_row => [4, 5], # only convert row 4 and 5
|
48
|
+
:skip_row => [6, 7], # skip row 6 and 7
|
49
|
+
:keep_col => [1], # only convert column 1
|
50
|
+
:skip_col => [2, 3] # skip column 2 and 3
|
51
|
+
|
52
|
+
wb.turn_to(2, :herder => 3, ...) # global options can be overrided by passing options to specfic sheet
|
53
|
+
# global options will still affect after turning to another sheet
|
54
|
+
|
55
|
+
|
56
|
+
## Contributing
|
57
|
+
|
58
|
+
1. Fork it
|
59
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
60
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
61
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
62
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Sheet2hash
|
2
|
+
module Options
|
3
|
+
def process_options(opts)
|
4
|
+
regulate_options opts
|
5
|
+
opts
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
def regulate_options(opts)
|
10
|
+
opts[:keep_row] = Array(opts[:keep_row]) if opts[:keep_row]
|
11
|
+
opts[:skip_row] = Array(opts[:skip_row]) if opts[:skip_row]
|
12
|
+
opts[:keep_col] = Array(opts[:keep_col]) if opts[:keep_col]
|
13
|
+
opts[:skip_col] = Array(opts[:skip_col]) if opts[:skip_col]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/sheet2hash.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'roo'
|
2
|
+
require 'sheet2hash/errors'
|
3
|
+
require 'sheet2hash/options'
|
4
|
+
|
5
|
+
module Sheet2hash
|
6
|
+
class Workbook
|
7
|
+
include Options
|
8
|
+
|
9
|
+
def initialize(path, opts = {})
|
10
|
+
@workbook = Roo::Spreadsheet.open path
|
11
|
+
@opts = process_options opts
|
12
|
+
@sheet_opts = {}
|
13
|
+
set_sheet_attributes
|
14
|
+
end
|
15
|
+
|
16
|
+
def turn_to(sheet, sheet_opts = {})
|
17
|
+
if sheet.kind_of?(Integer) && sheet <= sheets.size
|
18
|
+
@workbook.default_sheet = sheets[sheet - 1]
|
19
|
+
@sheet_opts = process_options sheet_opts
|
20
|
+
set_sheet_attributes
|
21
|
+
elsif sheet.kind_of?(String) && sheets.include?(sheet)
|
22
|
+
@workbook.default_sheet = sheet
|
23
|
+
@sheet_opts = process_options sheet_opts
|
24
|
+
set_sheet_attributes
|
25
|
+
else
|
26
|
+
raise SheetNotFoundError
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def sheets
|
31
|
+
@workbook.sheets
|
32
|
+
end
|
33
|
+
|
34
|
+
def sheet
|
35
|
+
@workbook.default_sheet
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_h
|
39
|
+
hash = {}
|
40
|
+
sheets.each do |sheet|
|
41
|
+
turn_to sheet
|
42
|
+
hash[sheet] = to_a
|
43
|
+
end
|
44
|
+
hash
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_a
|
48
|
+
ary = []
|
49
|
+
@rows.each do |row|
|
50
|
+
record = []
|
51
|
+
@columns.each { |col| record << trim_int_cell(@workbook.cell(row, col)) }
|
52
|
+
ary << Hash[ @header.zip record ]
|
53
|
+
end
|
54
|
+
ary
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def set_sheet_attributes
|
59
|
+
@header = header
|
60
|
+
@rows = rows
|
61
|
+
@columns = columns
|
62
|
+
end
|
63
|
+
|
64
|
+
def trim_int_cell(cell)
|
65
|
+
cell.kind_of?(Numeric) && cell % 1 == 0 ? cell.to_i : cell
|
66
|
+
end
|
67
|
+
|
68
|
+
def columns
|
69
|
+
columns = (@workbook.first_column..@workbook.last_column).to_a
|
70
|
+
if @sheet_opts[:skip_col] || @sheet_opts[:keep_col]
|
71
|
+
collect_columns columns, @sheet_opts
|
72
|
+
elsif @opts[:skip_col] || @opts[:keep_col]
|
73
|
+
collect_columns columns, @opts
|
74
|
+
else
|
75
|
+
columns
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def collect_columns(columns, opts)
|
80
|
+
columns.keep_if { |col| opts[:keep_col].include? col } if opts[:keep_col]
|
81
|
+
columns = columns - opts[:skip_col] if opts[:skip_col]
|
82
|
+
columns
|
83
|
+
end
|
84
|
+
|
85
|
+
def first_row
|
86
|
+
first_row = @sheet_opts[:start] || @opts[:start]
|
87
|
+
first_row || @workbook.first_row
|
88
|
+
end
|
89
|
+
|
90
|
+
def last_row
|
91
|
+
last_row = @sheet_opts[:end] || @opts[:end]
|
92
|
+
last_row || @workbook.last_row
|
93
|
+
end
|
94
|
+
|
95
|
+
def rows
|
96
|
+
rows = (first_row..last_row).to_a
|
97
|
+
if @sheet_opts[:keep_row] || @sheet_opts[:skip_row]
|
98
|
+
rows = collect_rows rows, @sheet_opts
|
99
|
+
rows - [@sheet_opts[:header]]
|
100
|
+
elsif @opts[:keep_row] || @opts[:skip_row]
|
101
|
+
rows = collect_rows rows, @opts
|
102
|
+
rows - [@opts[:header]]
|
103
|
+
else
|
104
|
+
rows - [@workbook.first_row]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def collect_rows(rows, opts)
|
109
|
+
rows.keep_if { |row| opts[:keep_row].include? row } if opts[:keep_row]
|
110
|
+
rows = rows - opts[:skip_row] if opts[:skip_row]
|
111
|
+
rows
|
112
|
+
end
|
113
|
+
|
114
|
+
def header
|
115
|
+
header = @sheet_opts[:header] || @opts[:header]
|
116
|
+
if header
|
117
|
+
header = process_header header
|
118
|
+
else
|
119
|
+
header = header_from_row @workbook.first_row
|
120
|
+
end
|
121
|
+
match_header_with_columns header
|
122
|
+
end
|
123
|
+
|
124
|
+
def match_header_with_columns(header)
|
125
|
+
header.each_with_index.select { |h, i| columns.include?(i + 1) }.map { |i| i.first }
|
126
|
+
end
|
127
|
+
|
128
|
+
def process_header(header)
|
129
|
+
if header.kind_of? Array
|
130
|
+
unique_header header
|
131
|
+
elsif header.kind_of? Integer
|
132
|
+
header_from_row header
|
133
|
+
else
|
134
|
+
raise InvalidHeaderError
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def header_from_row(row)
|
139
|
+
header = []
|
140
|
+
(@workbook.first_column..@workbook.last_column).each { |col| header << @workbook.cell(row, col) }
|
141
|
+
unique_header header
|
142
|
+
end
|
143
|
+
|
144
|
+
def unique_header(header)
|
145
|
+
header.reverse!
|
146
|
+
dup_header = header.dup
|
147
|
+
header = header.map do |field|
|
148
|
+
count = dup_header.count field
|
149
|
+
if count == 2
|
150
|
+
dup_header.delete_at dup_header.find_index(field)
|
151
|
+
"#{field}_dup"
|
152
|
+
elsif count > 1
|
153
|
+
dup_header.delete_at dup_header.find_index(field)
|
154
|
+
"#{field}_dup#{count - 1}"
|
155
|
+
else
|
156
|
+
field
|
157
|
+
end
|
158
|
+
end
|
159
|
+
header.reverse!
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
data/sheet2hash.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sheet2hash/version'
|
5
|
+
require 'date'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "sheet2hash"
|
9
|
+
spec.version = Sheet2hash::VERSION
|
10
|
+
spec.authors = ["Wei-Ming Wu"]
|
11
|
+
spec.email = ["wnameless@gmail.com"]
|
12
|
+
spec.description = %q{Convert Excel or Spreadsheet to Ruby hash}
|
13
|
+
spec.date = "#{Date.today.to_s}"
|
14
|
+
spec.summary = "sheet2hash-#{Sheet2hash::VERSION}"
|
15
|
+
spec.homepage = "http://github.com/wnameless/sheet2hash"
|
16
|
+
spec.license = "Apache License, Version 2.0"
|
17
|
+
|
18
|
+
spec.files = `git ls-files`.split($/)
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_dependency "roo"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sheet2hash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Wei-Ming Wu
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-30 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: roo
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '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'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.3'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.3'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
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: '0'
|
62
|
+
description: Convert Excel or Spreadsheet to Ruby hash
|
63
|
+
email:
|
64
|
+
- wnameless@gmail.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- Gemfile
|
71
|
+
- LICENSE.txt
|
72
|
+
- README.md
|
73
|
+
- Rakefile
|
74
|
+
- lib/sheet2hash.rb
|
75
|
+
- lib/sheet2hash/errors.rb
|
76
|
+
- lib/sheet2hash/options.rb
|
77
|
+
- lib/sheet2hash/version.rb
|
78
|
+
- sheet2hash.gemspec
|
79
|
+
homepage: http://github.com/wnameless/sheet2hash
|
80
|
+
licenses:
|
81
|
+
- Apache License, Version 2.0
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
hash: 1249836198874523190
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
hash: 1249836198874523190
|
104
|
+
requirements: []
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 1.8.25
|
107
|
+
signing_key:
|
108
|
+
specification_version: 3
|
109
|
+
summary: sheet2hash-0.1.0
|
110
|
+
test_files: []
|