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 +4 -4
- data/excel_utils.gemspec +3 -2
- data/lib/excel_utils.rb +14 -4
- data/lib/excel_utils/sheets/base.rb +41 -0
- data/lib/excel_utils/sheets/csv.rb +28 -0
- data/lib/excel_utils/sheets/excel.rb +35 -0
- data/lib/excel_utils/sheets/excel_stream.rb +35 -0
- data/lib/excel_utils/version.rb +1 -1
- data/lib/excel_utils/workbooks/csv.rb +36 -0
- data/lib/excel_utils/workbooks/excel.rb +41 -0
- data/spec/minitest_helper.rb +11 -1
- data/spec/read_spec.rb +111 -70
- data/spec/resources/basic.csv +5 -0
- data/spec/resources/basic.ods +0 -0
- data/spec/{sample.xls → resources/basic.xls} +0 -0
- data/spec/resources/basic.xlsm +0 -0
- data/spec/resources/basic.xlsx +0 -0
- data/spec/resources/custom_extension.tmp +0 -0
- data/spec/resources/empty.csv +0 -0
- data/spec/resources/multiple.xlsx +0 -0
- data/spec/resources/only_headers.csv +1 -0
- data/spec/write_spec.rb +1 -1
- metadata +44 -14
- data/lib/excel_utils/sheet.rb +0 -54
- data/lib/excel_utils/workbook.rb +0 -33
- data/spec/sample.tmp +0 -0
- data/spec/sample.xlsx +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83f4fd8fec5396120145aefdaa76246f93310b40a6a80d9d799223546e8de9d2
|
4
|
+
data.tar.gz: 45cce54a288cd0e462f60341d0fc4f8884eea4c640db9f92850a50f35e1f32bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20d1dfdf88228997f8c999348541dd269ef2bd9510bb5480663a3aa9c1cef9528ffe1287c198355b55347299d0d89ba6e6946e4950bf11b9b398d66f59ecebdc
|
7
|
+
data.tar.gz: 7e0d52d3569e343780230ba2efff28c69f449502de5dab3931d1caa426e3748c4131d72cabe003b28d4eac70602ed5be1c031470028069dcc8d0c6ddffe11544
|
data/excel_utils.gemspec
CHANGED
@@ -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.
|
23
|
-
spec.add_runtime_dependency 'roo-xls', '~> 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'
|
data/lib/excel_utils.rb
CHANGED
@@ -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/
|
10
|
-
require_relative 'excel_utils/
|
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
|
-
|
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
|
data/lib/excel_utils/version.rb
CHANGED
@@ -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
|
data/spec/minitest_helper.rb
CHANGED
@@ -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
|
data/spec/read_spec.rb
CHANGED
@@ -2,110 +2,151 @@ require 'minitest_helper'
|
|
2
2
|
|
3
3
|
describe ExcelUtils, 'Read' do
|
4
4
|
|
5
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
23
|
+
let(:expected_columns) { [column_a, column_b] }
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
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
|
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
|
-
|
60
|
+
describe 'Sheet' do
|
50
61
|
|
51
|
-
|
62
|
+
it 'name' do
|
63
|
+
sheet.name.must_equal expected_sheet_name
|
64
|
+
end
|
52
65
|
|
53
|
-
|
66
|
+
it 'normalize_column_names' do
|
67
|
+
sheet.normalize_column_names.must_equal workbook.normalize_column_names
|
68
|
+
end
|
54
69
|
|
55
|
-
|
56
|
-
|
57
|
-
|
70
|
+
it 'column_names' do
|
71
|
+
sheet.column_names.must_equal expected_columns
|
72
|
+
end
|
58
73
|
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
86
|
+
end
|
70
87
|
|
71
|
-
|
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
|
-
|
90
|
+
it 'empty.csv' do
|
91
|
+
workbook = ExcelUtils.read resource_path('empty.csv')
|
82
92
|
|
83
|
-
|
93
|
+
workbook.sheets.map(&:name).must_equal ['default']
|
84
94
|
|
85
|
-
|
95
|
+
workbook['default'].column_names.must_equal []
|
96
|
+
workbook['default'].to_a.must_equal []
|
86
97
|
|
87
|
-
|
88
|
-
|
89
|
-
end
|
98
|
+
workbook.to_h.must_equal 'default' => []
|
99
|
+
end
|
90
100
|
|
91
|
-
|
92
|
-
|
93
|
-
end
|
101
|
+
it 'only_headers.csv' do
|
102
|
+
workbook = ExcelUtils.read resource_path('only_headers.csv')
|
94
103
|
|
95
|
-
|
104
|
+
workbook.sheets.map(&:name).must_equal ['default']
|
96
105
|
|
97
|
-
|
106
|
+
workbook['default'].column_names.must_equal ['ID', 'Value']
|
107
|
+
workbook['default'].to_a.must_equal []
|
98
108
|
|
99
|
-
|
109
|
+
workbook.to_h.must_equal 'default' => []
|
110
|
+
end
|
100
111
|
|
101
|
-
|
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 '
|
106
|
-
|
107
|
-
|
108
|
-
workbook.sheets.
|
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
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
File without changes
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
ID,Value
|
data/spec/write_spec.rb
CHANGED
@@ -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.
|
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-
|
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.
|
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.
|
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.
|
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.
|
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/
|
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/
|
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/
|
199
|
-
- spec/
|
200
|
-
- spec/
|
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/
|
230
|
-
- spec/
|
231
|
-
- spec/
|
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
|
data/lib/excel_utils/sheet.rb
DELETED
@@ -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
|
data/lib/excel_utils/workbook.rb
DELETED
@@ -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
|
data/spec/sample.tmp
DELETED
Binary file
|
data/spec/sample.xlsx
DELETED
Binary file
|