excel_utils 1.1.2 → 1.2.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.
- 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
|