excel_utils 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea8c9b8aeb5945a6d01f5ea29578bf34c48d28f8a572cb6d5f3857757fb48ae9
4
- data.tar.gz: f1fc9f86e3a3fe784184cd942739e3ea961f018ea313006222568785988b6f34
3
+ metadata.gz: 83f4fd8fec5396120145aefdaa76246f93310b40a6a80d9d799223546e8de9d2
4
+ data.tar.gz: 45cce54a288cd0e462f60341d0fc4f8884eea4c640db9f92850a50f35e1f32bf
5
5
  SHA512:
6
- metadata.gz: 0d7ef606b270f1af8ae88e91e12b44c657e693c7653c3df2d5b951d71758339749be6d78ee95a2c04f1e6895544cb653d8f84bae8ba619757bfc2b1bbb945dbe
7
- data.tar.gz: 6eea2444670d88df36d2d4fdcca88ba4ced1ac9bfbc8890b8e2ab6b4c6b90d42a0413725599ea99e5bfc93f480bbd931cdc8516e725b04ed2c0a3c355ca00815
6
+ metadata.gz: 20d1dfdf88228997f8c999348541dd269ef2bd9510bb5480663a3aa9c1cef9528ffe1287c198355b55347299d0d89ba6e6946e4950bf11b9b398d66f59ecebdc
7
+ data.tar.gz: 7e0d52d3569e343780230ba2efff28c69f449502de5dab3931d1caa426e3748c4131d72cabe003b28d4eac70602ed5be1c031470028069dcc8d0c6ddffe11544
@@ -19,9 +19,10 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_runtime_dependency 'inflecto', '~> 0.0'
22
- spec.add_runtime_dependency 'roo', '~> 2.7'
23
- spec.add_runtime_dependency 'roo-xls', '~> 1.1'
22
+ spec.add_runtime_dependency 'roo', '~> 2.8'
23
+ spec.add_runtime_dependency 'roo-xls', '~> 1.2'
24
24
  spec.add_runtime_dependency 'write_xlsx', '~> 0.85'
25
+ spec.add_runtime_dependency 'nesquikcsv', '~> 0.1'
25
26
 
26
27
  spec.add_development_dependency 'rake', '~> 12.0'
27
28
  spec.add_development_dependency 'minitest', '~> 5.0', '< 5.11'
@@ -4,16 +4,26 @@ require 'roo'
4
4
  require 'roo-xls'
5
5
  require 'write_xlsx'
6
6
  require 'inflecto'
7
+ require 'nesquikcsv'
7
8
 
8
9
  require_relative 'excel_utils/version'
9
- require_relative 'excel_utils/workbook'
10
- require_relative 'excel_utils/sheet'
10
+ require_relative 'excel_utils/workbooks/csv'
11
+ require_relative 'excel_utils/workbooks/excel'
12
+ require_relative 'excel_utils/sheets/base'
13
+ require_relative 'excel_utils/sheets/csv'
14
+ require_relative 'excel_utils/sheets/excel'
15
+ require_relative 'excel_utils/sheets/excel_stream'
11
16
  require_relative 'excel_utils/writer'
12
17
 
13
18
  module ExcelUtils
14
-
19
+
15
20
  def self.read(filename, **options)
16
- Workbook.new filename, **options
21
+ extension = options.fetch(:extension, File.extname(filename)[1..-1])
22
+ if extension == 'csv'
23
+ Workbooks::CSV.new(filename, **options)
24
+ else
25
+ Workbooks::Excel.new(filename, **options)
26
+ end
17
27
  end
18
28
 
19
29
  def self.write(filename, data)
@@ -0,0 +1,41 @@
1
+ module ExcelUtils
2
+ module Sheets
3
+ class Base
4
+
5
+ include Enumerable
6
+
7
+ attr_reader :name, :normalize_column_names
8
+
9
+ def initialize(name:, normalize_column_names: false)
10
+ @name = name
11
+ @normalize_column_names = normalize_column_names
12
+ end
13
+
14
+ def column_names
15
+ @column_names ||= normalize_column_names ? normalize_columns(first_row) : first_row
16
+ end
17
+
18
+ def each
19
+ if column_names.any?
20
+ each_row do |row|
21
+ break if empty_row? row
22
+ yield Hash[column_names.zip(row)]
23
+ end
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def normalize_columns(names)
30
+ names.map do |name|
31
+ Inflecto.underscore(name.strip.gsub(' ', '_')).to_sym
32
+ end
33
+ end
34
+
35
+ def empty_row?(row)
36
+ row.all? { |cell| cell.to_s.strip.empty? }
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,28 @@
1
+ module ExcelUtils
2
+ module Sheets
3
+ class CSV < Base
4
+
5
+ def initialize(filename:, **options)
6
+ super(**options)
7
+ @filename = filename
8
+ end
9
+
10
+ private
11
+
12
+ attr_reader :filename
13
+
14
+ def first_row
15
+ NesquikCSV.open(filename) { |csv| csv.readline } || []
16
+ end
17
+
18
+ def each_row
19
+ first = true
20
+ NesquikCSV.foreach(filename) do |row|
21
+ yield row unless first
22
+ first = false
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,35 @@
1
+ module ExcelUtils
2
+ module Sheets
3
+ class Excel < Base
4
+
5
+ def initialize(spreadsheet:, **options)
6
+ super(**options)
7
+ @spreadsheet = spreadsheet
8
+ end
9
+
10
+ private
11
+
12
+ attr_reader :spreadsheet
13
+
14
+ def first_row
15
+ with_sheet do |sheet|
16
+ sheet.first_row ? sheet.row(sheet.first_row) : []
17
+ end
18
+ end
19
+
20
+ def each_row
21
+ with_sheet do |sheet|
22
+ (sheet.first_row + 1).upto(sheet.last_row) do |i|
23
+ yield sheet.row(i)
24
+ end
25
+ end
26
+ end
27
+
28
+ def with_sheet
29
+ yield spreadsheet.sheet(name)
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ module ExcelUtils
2
+ module Sheets
3
+ class ExcelStream < Base
4
+
5
+ def initialize(spreadsheet:, **options)
6
+ super(**options)
7
+ @spreadsheet = spreadsheet
8
+ end
9
+
10
+ private
11
+
12
+ attr_reader :spreadsheet
13
+
14
+ def first_row
15
+ row = sheet.each_row_streaming(pad_cells: true, max_rows: 0).first || []
16
+ normalize_row row
17
+ end
18
+
19
+ def each_row
20
+ sheet.each_row_streaming(pad_cells: true, offset: 1) do |row|
21
+ yield normalize_row(row)
22
+ end
23
+ end
24
+
25
+ def normalize_row(row)
26
+ row.map { |cell| cell ? cell.value : cell }
27
+ end
28
+
29
+ def sheet
30
+ spreadsheet.sheet name
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -1,3 +1,3 @@
1
1
  module ExcelUtils
2
- VERSION = '1.1.2'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -0,0 +1,36 @@
1
+ module ExcelUtils
2
+ module Workbooks
3
+ class CSV
4
+
5
+ SHEET_NAME = 'default'.freeze
6
+
7
+ attr_reader :filename, :normalize_column_names
8
+
9
+ def initialize(filename, normalize_column_names: false)
10
+ @filename = filename
11
+ @normalize_column_names = normalize_column_names
12
+
13
+ @sheet = Sheets::CSV.new name: SHEET_NAME,
14
+ normalize_column_names: normalize_column_names,
15
+ filename: filename
16
+ end
17
+
18
+ def sheets
19
+ [sheet]
20
+ end
21
+
22
+ def [](sheet_name)
23
+ sheet_name == SHEET_NAME ? sheet : nil
24
+ end
25
+
26
+ def to_h
27
+ {SHEET_NAME => sheet.to_a}
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :sheet
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,41 @@
1
+ module ExcelUtils
2
+ module Workbooks
3
+ class Excel
4
+
5
+ attr_reader :filename, :normalize_column_names
6
+
7
+ def initialize(filename, normalize_column_names: false, extension: nil)
8
+ @filename = filename
9
+ @normalize_column_names = normalize_column_names
10
+ @spreadsheet = Roo::Spreadsheet.open filename, extension: extension
11
+ end
12
+
13
+ def sheets
14
+ @sheets ||= spreadsheet.sheets.map do |name|
15
+ sheet_class.new name: name,
16
+ normalize_column_names: normalize_column_names,
17
+ spreadsheet: spreadsheet
18
+ end
19
+ end
20
+
21
+ def [](sheet_name)
22
+ sheets.detect { |sheet| sheet.name == sheet_name }
23
+ end
24
+
25
+ def to_h
26
+ sheets.each_with_object({}) do |sheet, hash|
27
+ hash[sheet.name] = sheet.to_a
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :spreadsheet
34
+
35
+ def sheet_class
36
+ @sheet_class ||= spreadsheet.respond_to?(:each_row_streaming) ? Sheets::ExcelStream : Sheets::Excel
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -3,4 +3,14 @@ require 'minitest/autorun'
3
3
  require 'minitest/colorin'
4
4
  require 'pry-nav'
5
5
 
6
- require 'excel_utils'
6
+ require 'excel_utils'
7
+
8
+ RESOURCES_PATH = File.expand_path '../resources', __FILE__
9
+
10
+ class Minitest::Test
11
+
12
+ def resource_path(relative_path)
13
+ File.join RESOURCES_PATH, relative_path
14
+ end
15
+
16
+ end
@@ -2,110 +2,151 @@ require 'minitest_helper'
2
2
 
3
3
  describe ExcelUtils, 'Read' do
4
4
 
5
- def expected_rows(sheet)
6
- rows_by_sheet[sheet.name].map { |r| Hash[columns_by_sheet[sheet.name].zip(r)] }
7
- end
5
+ Dir.glob(File.join(RESOURCES_PATH, 'basic.*')).each do |filename|
8
6
 
9
- let :rows_by_sheet do
10
- {
11
- 'Sheet1' => [
12
- [1.0, 'some text'],
13
- [2.0, 1.35],
14
- [3.0, Date.parse('2019-08-17')],
15
- [4.0, nil]
16
- ],
17
- 'Sheet2' => [
18
- [123.0, 'Text 1'],
19
- [456.0, 'Text 2']
20
- ],
21
- 'Sheet3' => []
22
- }
23
- end
7
+ [true, false].each do |normalize_column_names|
8
+
9
+ describe File.basename(filename), "Workbook (normalize_column_names: #{normalize_column_names})" do
10
+
11
+ let(:workbook) { ExcelUtils.read filename, normalize_column_names: normalize_column_names }
12
+
13
+ let(:sheet) { workbook.sheets.first }
14
+
15
+ let(:csv?) { File.extname(filename) == '.csv' }
16
+
17
+ let(:expected_sheet_name) { csv? ? 'default' : 'Sheet1' }
18
+
19
+ let(:column_a) { normalize_column_names ? :column_a : 'Column A' }
20
+
21
+ let(:column_b) { normalize_column_names ? :column_b : 'Column B' }
24
22
 
25
- ['xls', 'xlsx'].each do |extension|
23
+ let(:expected_columns) { [column_a, column_b] }
26
24
 
27
- describe extension do
28
-
29
- let(:filename) { File.expand_path "../sample.#{extension}", __FILE__ }
25
+ let :expected_rows do
26
+ if csv?
27
+ [
28
+ {column_a => '1', column_b => 'some text'},
29
+ {column_a => '2', column_b => '1,35'},
30
+ {column_a => '3', column_b => '17/08/2019'},
31
+ {column_a => '4', column_b => nil}
32
+ ]
33
+ else
34
+ [
35
+ {column_a => 1, column_b => 'some text'},
36
+ {column_a => 2, column_b => 1.35},
37
+ {column_a => 3, column_b => Date.parse('2019-08-17')},
38
+ {column_a => 4, column_b => nil}
39
+ ]
40
+ end
41
+ end
30
42
 
31
- describe 'Original column names' do
43
+ it 'filename' do
44
+ workbook.filename.must_equal filename
45
+ end
46
+
47
+ it 'normalize_column_names' do
48
+ workbook.normalize_column_names.must_equal normalize_column_names
49
+ end
32
50
 
33
- let(:workbook) { ExcelUtils.read filename }
34
-
35
- let :columns_by_sheet do
36
- {
37
- 'Sheet1' => ['Column A', 'Column B'],
38
- 'Sheet2' => ['ID', 'Value'],
39
- 'Sheet3' => []
40
- }
51
+ it 'sheets' do
52
+ workbook.sheets.count.must_equal 1
53
+ workbook[workbook.sheets.first.name].must_equal sheet
41
54
  end
42
55
 
43
56
  it 'to_h' do
44
- workbook.to_h.must_equal 'Sheet1' => expected_rows(workbook['Sheet1']),
45
- 'Sheet2' => expected_rows(workbook['Sheet2']),
46
- 'Sheet3' => []
57
+ workbook.to_h.must_equal workbook.sheets.first.name => sheet.to_a
47
58
  end
48
59
 
49
- ['Sheet1', 'Sheet2', 'Sheet3'].each do |sheet_name|
60
+ describe 'Sheet' do
50
61
 
51
- describe sheet_name do
62
+ it 'name' do
63
+ sheet.name.must_equal expected_sheet_name
64
+ end
52
65
 
53
- let(:sheet) { workbook[sheet_name] }
66
+ it 'normalize_column_names' do
67
+ sheet.normalize_column_names.must_equal workbook.normalize_column_names
68
+ end
54
69
 
55
- it 'Column names' do
56
- sheet.column_names.must_equal columns_by_sheet[sheet_name]
57
- end
70
+ it 'column_names' do
71
+ sheet.column_names.must_equal expected_columns
72
+ end
58
73
 
59
- it 'Rows' do
60
- sheet.to_a.must_equal expected_rows(sheet)
61
- end
74
+ it 'count' do
75
+ sheet.count.must_equal 4
76
+ end
62
77
 
78
+ it 'to_a' do
79
+ sheet.to_a.must_equal expected_rows
63
80
  end
64
81
 
65
82
  end
66
83
 
67
84
  end
68
85
 
69
- describe 'Normalized column names' do
86
+ end
70
87
 
71
- let(:workbook) { ExcelUtils.read filename, normalize_column_names: true }
72
-
73
- let :columns_by_sheet do
74
- {
75
- 'Sheet1' => [:column_a, :column_b],
76
- 'Sheet2' => [:id, :value],
77
- 'Sheet3' => []
78
- }
79
- end
88
+ end
80
89
 
81
- ['Sheet1', 'Sheet2', 'Sheet3'].each do |sheet_name|
90
+ it 'empty.csv' do
91
+ workbook = ExcelUtils.read resource_path('empty.csv')
82
92
 
83
- describe sheet_name do
93
+ workbook.sheets.map(&:name).must_equal ['default']
84
94
 
85
- let(:sheet) { workbook[sheet_name] }
95
+ workbook['default'].column_names.must_equal []
96
+ workbook['default'].to_a.must_equal []
86
97
 
87
- it 'Column names' do
88
- sheet.column_names.must_equal columns_by_sheet[sheet_name]
89
- end
98
+ workbook.to_h.must_equal 'default' => []
99
+ end
90
100
 
91
- it 'Rows' do
92
- sheet.to_a.must_equal expected_rows(sheet)
93
- end
101
+ it 'only_headers.csv' do
102
+ workbook = ExcelUtils.read resource_path('only_headers.csv')
94
103
 
95
- end
104
+ workbook.sheets.map(&:name).must_equal ['default']
96
105
 
97
- end
106
+ workbook['default'].column_names.must_equal ['ID', 'Value']
107
+ workbook['default'].to_a.must_equal []
98
108
 
99
- end
109
+ workbook.to_h.must_equal 'default' => []
110
+ end
100
111
 
101
- end
112
+ it 'custom_extension.tmp' do
113
+ workbook = ExcelUtils.read resource_path('custom_extension.tmp'), extension: 'xlsx'
102
114
 
115
+ expected_rows = [
116
+ {'ID' => 1, 'Value' => 'Text 1'},
117
+ {'ID' => 2, 'Value' => 'Text 2'}
118
+ ]
119
+
120
+ workbook.sheets.map(&:name).must_equal ['Sheet1']
121
+
122
+ workbook['Sheet1'].column_names.must_equal ['ID', 'Value']
123
+ workbook['Sheet1'].to_a.must_equal expected_rows
124
+
125
+ workbook.to_h.must_equal 'Sheet1' => expected_rows
103
126
  end
104
127
 
105
- it 'Force extension' do
106
- filename = File.expand_path "../sample.tmp", __FILE__
107
- workbook = ExcelUtils.read filename, extension: 'xlsx'
108
- workbook.sheets.count.must_equal 3
128
+ it 'multiple.xlsx' do
129
+ workbook = ExcelUtils.read resource_path('multiple.xlsx'), normalize_column_names: true
130
+
131
+ workbook.sheets.map(&:name).must_equal ['Sheet1', 'Sheet2', 'Sheet3']
132
+
133
+ expected_rows_sheet_1 = [
134
+ {id: 1, value: 'Text 1'},
135
+ {id: 2, value: 'Text 2'}
136
+ ]
137
+
138
+ workbook['Sheet1'].column_names.must_equal [:id, :value]
139
+ workbook['Sheet1'].to_a.must_equal expected_rows_sheet_1
140
+
141
+ workbook['Sheet2'].column_names.must_equal [:id, :value]
142
+ workbook['Sheet2'].to_a.must_equal []
143
+
144
+ workbook['Sheet3'].column_names.must_equal []
145
+ workbook['Sheet3'].to_a.must_equal []
146
+
147
+ workbook.to_h.must_equal 'Sheet1' => expected_rows_sheet_1,
148
+ 'Sheet2' => [],
149
+ 'Sheet3' => []
109
150
  end
110
151
 
111
152
  end
@@ -0,0 +1,5 @@
1
+ Column A,Column B
2
+ 1,some text
3
+ 2,"1,35"
4
+ 3,17/08/2019
5
+ 4,
Binary file
Binary file
Binary file
File without changes
@@ -0,0 +1 @@
1
+ ID,Value
@@ -34,7 +34,7 @@ describe ExcelUtils do
34
34
  sheet.each_with_index do |row, i|
35
35
  columns = row.keys | data[sheet.name][i].keys
36
36
  columns.each do |column|
37
- row[column].must_equal data[sheet.name][i][column]
37
+ row[column].must_equal data[sheet.name][i][column]
38
38
  end
39
39
  end
40
40
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: excel_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriel Naiman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-25 00:00:00.000000000 Z
11
+ date: 2020-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inflecto
@@ -30,28 +30,28 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.7'
33
+ version: '2.8'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.7'
40
+ version: '2.8'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: roo-xls
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.1'
47
+ version: '1.2'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.1'
54
+ version: '1.2'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: write_xlsx
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.85'
69
+ - !ruby/object:Gem::Dependency
70
+ name: nesquikcsv
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.1'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.1'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rake
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -188,16 +202,26 @@ files:
188
202
  - Rakefile
189
203
  - excel_utils.gemspec
190
204
  - lib/excel_utils.rb
191
- - lib/excel_utils/sheet.rb
205
+ - lib/excel_utils/sheets/base.rb
206
+ - lib/excel_utils/sheets/csv.rb
207
+ - lib/excel_utils/sheets/excel.rb
208
+ - lib/excel_utils/sheets/excel_stream.rb
192
209
  - lib/excel_utils/version.rb
193
- - lib/excel_utils/workbook.rb
210
+ - lib/excel_utils/workbooks/csv.rb
211
+ - lib/excel_utils/workbooks/excel.rb
194
212
  - lib/excel_utils/writer.rb
195
213
  - spec/coverage_helper.rb
196
214
  - spec/minitest_helper.rb
197
215
  - spec/read_spec.rb
198
- - spec/sample.tmp
199
- - spec/sample.xls
200
- - spec/sample.xlsx
216
+ - spec/resources/basic.csv
217
+ - spec/resources/basic.ods
218
+ - spec/resources/basic.xls
219
+ - spec/resources/basic.xlsm
220
+ - spec/resources/basic.xlsx
221
+ - spec/resources/custom_extension.tmp
222
+ - spec/resources/empty.csv
223
+ - spec/resources/multiple.xlsx
224
+ - spec/resources/only_headers.csv
201
225
  - spec/write_spec.rb
202
226
  homepage: https://github.com/gabynaiman/excel_utils
203
227
  licenses:
@@ -226,7 +250,13 @@ test_files:
226
250
  - spec/coverage_helper.rb
227
251
  - spec/minitest_helper.rb
228
252
  - spec/read_spec.rb
229
- - spec/sample.tmp
230
- - spec/sample.xls
231
- - spec/sample.xlsx
253
+ - spec/resources/basic.csv
254
+ - spec/resources/basic.ods
255
+ - spec/resources/basic.xls
256
+ - spec/resources/basic.xlsm
257
+ - spec/resources/basic.xlsx
258
+ - spec/resources/custom_extension.tmp
259
+ - spec/resources/empty.csv
260
+ - spec/resources/multiple.xlsx
261
+ - spec/resources/only_headers.csv
232
262
  - spec/write_spec.rb
@@ -1,54 +0,0 @@
1
- module ExcelUtils
2
- class Sheet
3
-
4
- include Enumerable
5
-
6
- attr_reader :name, :normalize_column_names
7
-
8
- def initialize(name, spreadsheet, normalize_column_names: false)
9
- @name = name
10
- @spreadsheet = spreadsheet
11
- @normalize_column_names = normalize_column_names
12
- end
13
-
14
- def column_names
15
- @column_names ||= begin
16
- if sheet.first_row
17
- first_row = sheet.row sheet.first_row
18
- normalize_column_names ? first_row.map { |name| normalize_column name } : first_row
19
- else
20
- []
21
- end
22
- end
23
- end
24
-
25
- def each(&block)
26
- rows.each(&block)
27
- end
28
-
29
- private
30
-
31
- attr_reader :spreadsheet
32
-
33
- def sheet
34
- spreadsheet.sheet name
35
- end
36
-
37
- def rows
38
- @rows ||= begin
39
- if sheet.first_row
40
- sheet.to_a[1..-1].map do |row|
41
- Hash[column_names.zip(row)]
42
- end
43
- else
44
- []
45
- end
46
- end
47
- end
48
-
49
- def normalize_column(name)
50
- Inflecto.underscore(name.strip.gsub(' ', '_')).to_sym
51
- end
52
-
53
- end
54
- end
@@ -1,33 +0,0 @@
1
- module ExcelUtils
2
- class Workbook
3
-
4
- attr_reader :filename, :normalize_column_names
5
-
6
- def initialize(filename, normalize_column_names: false, extension: nil)
7
- @filename = filename
8
- @normalize_column_names = normalize_column_names
9
- @spreadsheet = Roo::Spreadsheet.open filename, extension: extension
10
- end
11
-
12
- def sheets
13
- @sheets ||= spreadsheet.sheets.map do |name|
14
- Sheet.new name, spreadsheet, normalize_column_names: normalize_column_names
15
- end
16
- end
17
-
18
- def [](sheet_name)
19
- sheets.detect { |sheet| sheet.name == sheet_name }
20
- end
21
-
22
- def to_h
23
- sheets.each_with_object({}) do |sheet, hash|
24
- hash[sheet.name] = sheet.to_a
25
- end
26
- end
27
-
28
- private
29
-
30
- attr_reader :spreadsheet
31
-
32
- end
33
- end
Binary file
Binary file