creek 2.5.1 → 2.5.2

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: 39ef59b96aa1733768b24a21c8b393247fbdec6d2f9919da92e1329f352524da
4
- data.tar.gz: 9b460a1530f18ceaf6d1884b0ac2040f33a88887895fbbe7fea39fa855d8b01c
3
+ metadata.gz: 1b9680127cd771d8b0840567db333a2a32369952bbeb09eee7364a9dbcdd2284
4
+ data.tar.gz: e39694d00b142e542457cc585d9b0e027386a8a3fcdb39b0cfe670f6e8d57b81
5
5
  SHA512:
6
- metadata.gz: 01561d9355ea7f82d1523c887b8e0556f031bf579c36f0ada04b2a9ada5b5c19e10378098764604ae5bf7b18c371d58b787704f1ad84ccafbb93a9905b1e20ec
7
- data.tar.gz: 5b9315c34588b2dea639252f188158bcbe6fef1519fd73f6337f7d995be7ac28ba62d35e7cf9ea64ba941c2d6e6b0b3091ca69cded65f06cd943f156998bf8c2
6
+ metadata.gz: ffa323e9d0f5a9c7976750d4c802a10ca39517b7f2ed388c801c5109aa331a109128dfdfcc5a039e919a2f3e28b9099b9839face7594b1667ccf76cb0bef1bca
7
+ data.tar.gz: 6c5d6dc7b921d504490502b9e2c37def7112d23bb4a8f6d4a3a7e28d68bc6f297b0ff2864725c2186f302106c40543f4369a54c6884d3a3d908aaf0355539c6f
data/.gitignore CHANGED
@@ -15,3 +15,6 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+
19
+ # Mac finder artifacts
20
+ .DS_Store
data/README.md CHANGED
@@ -100,6 +100,14 @@ remote_url = 'http://dev-builds.libreoffice.org/tmp/test.xlsx'
100
100
  Creek::Book.new remote_url, remote: true
101
101
  ```
102
102
 
103
+ ## Mapping cells with header names
104
+ By default, Creek will map cell names with letter and number(A1, B3 and etc). To be able to get cell values by header column name use ***with_headers*** (can be used only with ***#simple_rows*** method!!!) during creation *(Note: header column is first string of sheet)*
105
+
106
+ ```ruby
107
+ creek = Creek::Book.new file.path, with_headers: true
108
+ ```
109
+
110
+
103
111
  ## Contributing
104
112
 
105
113
  Contributions are welcomed. You can fork a repository, add your code changes to the forked branch, ensure all existing unit tests pass, create new unit tests which cover your new changes and finally create a pull request.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'creek/version'
2
4
  require 'creek/book'
3
5
  require 'creek/styles/constants'
@@ -4,12 +4,11 @@ require 'date'
4
4
  require 'open-uri'
5
5
 
6
6
  module Creek
7
-
8
7
  class Creek::Book
9
-
10
8
  attr_reader :files,
11
9
  :sheets,
12
- :shared_strings
10
+ :shared_strings,
11
+ :with_headers
13
12
 
14
13
  DATE_1900 = Date.new(1899, 12, 30).freeze
15
14
  DATE_1904 = Date.new(1904, 1, 1).freeze
@@ -23,6 +22,7 @@ module Creek
23
22
  path = download_file(path) if options[:remote]
24
23
  @files = Zip::File.open(path)
25
24
  @shared_strings = SharedStrings.new(self)
25
+ @with_headers = options.fetch(:with_headers, false)
26
26
  end
27
27
 
28
28
  def sheets
@@ -41,7 +41,17 @@ module Creek
41
41
  rels = Nokogiri::XML::Document.parse(rels_doc).css("Relationship")
42
42
  @sheets = xml.css(cssPrefix+'sheet').map do |sheet|
43
43
  sheetfile = rels.find { |el| sheet.attr("r:id") == el.attr("Id") }.attr("Target")
44
- Sheet.new(self, sheet.attr("name"), sheet.attr("sheetid"), sheet.attr("state"), sheet.attr("visible"), sheet.attr("r:id"), sheetfile)
44
+ sheet = Sheet.new(
45
+ self,
46
+ sheet.attr("name"),
47
+ sheet.attr("sheetid"),
48
+ sheet.attr("state"),
49
+ sheet.attr("visible"),
50
+ sheet.attr("r:id"),
51
+ sheetfile
52
+ )
53
+ sheet.with_headers = with_headers
54
+ sheet
45
55
  end
46
56
  end
47
57
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'zip/filesystem'
2
4
  require 'nokogiri'
3
5
 
@@ -5,16 +7,19 @@ module Creek
5
7
  class Creek::Sheet
6
8
  include Creek::Utils
7
9
 
10
+ HEADERS_ROW_NUMBER = '1'
11
+
12
+ attr_accessor :with_headers
8
13
  attr_reader :book,
9
14
  :name,
10
15
  :sheetid,
11
16
  :state,
12
17
  :visible,
13
18
  :rid,
14
- :index
15
-
19
+ :index,
20
+ :headers
16
21
 
17
- def initialize book, name, sheetid, state, visible, rid, sheetfile
22
+ def initialize(book, name, sheetid, state, visible, rid, sheetfile)
18
23
  @book = book
19
24
  @name = name
20
25
  @sheetid = sheetid
@@ -46,7 +51,6 @@ module Creek
46
51
  @drawing.images_at(cell) if @images_present
47
52
  end
48
53
 
49
-
50
54
  ##
51
55
  # Provides an Enumerator that returns a hash representing each row.
52
56
  # The key of the hash is the column ID and the value is the value of the cell.
@@ -89,35 +93,37 @@ module Creek
89
93
  closer = Nokogiri::XML::Reader::TYPE_END_ELEMENT
90
94
  Enumerator.new do |y|
91
95
  row, cells, cell = nil, {}, nil
92
- cell_type = nil
96
+ cell_type = nil
93
97
  cell_style_idx = nil
94
98
  @book.files.file.open(path) do |xml|
95
99
  Nokogiri::XML::Reader.from_io(xml).each do |node|
96
- if (node.name.eql? 'row') and (node.node_type.eql? opener)
100
+ if node.name == 'row' && node.node_type == opener
97
101
  row = node.attributes
98
- row['cells'] = Hash.new
99
- cells = Hash.new
102
+ row['cells'] = {}
103
+ cells = {}
100
104
  y << (include_meta_data ? row : cells) if node.self_closing?
101
- elsif (node.name.eql? 'row') and (node.node_type.eql? closer)
105
+ elsif node.name == 'row' && node.node_type == closer
102
106
  processed_cells = fill_in_empty_cells(cells, row['r'], cell, use_simple_rows_format)
107
+ @headers = processed_cells if row['r'] == HEADERS_ROW_NUMBER
103
108
 
104
109
  if @images_present
105
110
  processed_cells.each do |cell_name, cell_value|
106
111
  next unless cell_value.nil?
112
+
107
113
  processed_cells[cell_name] = images_at(cell_name)
108
114
  end
109
115
  end
110
116
 
111
117
  row['cells'] = processed_cells
112
118
  y << (include_meta_data ? row : processed_cells)
113
- elsif (node.name.eql? 'c') and (node.node_type.eql? opener)
119
+ elsif node.name == 'c' && node.node_type == opener
114
120
  cell_type = node.attributes['t']
115
121
  cell_style_idx = node.attributes['s']
116
122
  cell = node.attributes['r']
117
- elsif (['v', 't'].include? node.name) and (node.node_type.eql? opener)
123
+ elsif %w[v t].include?(node.name) && node.node_type == opener
118
124
  unless cell.nil?
119
125
  node.read
120
- cells[(use_simple_rows_format ? cell.tr("0-9", "") : cell)] = convert(node.value, cell_type, cell_style_idx)
126
+ cells[cell] = convert(node.value, cell_type, cell_style_idx)
121
127
  end
122
128
  end
123
129
  end
@@ -142,15 +148,13 @@ module Creek
142
148
  # The unzipped XML file does not contain any node for empty cells.
143
149
  # Empty cells are being padded in using this function
144
150
  def fill_in_empty_cells(cells, row_number, last_col, use_simple_rows_format)
145
- new_cells = Hash.new
151
+ new_cells = {}
152
+ return new_cells if cells.empty?
146
153
 
147
- unless cells.empty?
148
- last_col = last_col.gsub(row_number, '')
149
-
150
- ("A"..last_col).to_a.each do |column|
151
- id = use_simple_rows_format ? "#{column}" : "#{column}#{row_number}"
152
- new_cells[id] = cells[id]
153
- end
154
+ last_col = last_col.gsub(row_number, '')
155
+ ('A'..last_col).to_a.each do |column|
156
+ id = cell_id(column, use_simple_rows_format, row_number)
157
+ new_cells[id] = cells["#{column}#{row_number}"]
154
158
  end
155
159
 
156
160
  new_cells
@@ -172,5 +176,11 @@ module Creek
172
176
  sheet_rels_filepath = expand_to_rels_path(sheet_filepath)
173
177
  parse_xml(sheet_rels_filepath).css("Relationship[@Id='#{drawing_rid}']").first.attributes['Target'].value
174
178
  end
179
+
180
+ def cell_id(column, use_simple_rows_format, row_number = '')
181
+ return "#{column}#{row_number}" unless use_simple_rows_format
182
+
183
+ with_headers && headers ? headers[column] : column
184
+ end
175
185
  end
176
186
  end
@@ -1,3 +1,3 @@
1
1
  module Creek
2
- VERSION = "2.5.1"
2
+ VERSION = "2.5.2"
3
3
  end
@@ -1,26 +1,26 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require './spec/spec_helper'
2
4
 
3
5
  describe 'sheet' do
4
6
  let(:book_with_images) { Creek::Book.new('spec/fixtures/sample-with-images.xlsx') }
5
- let(:book_no_images) { Creek::Book.new('spec/fixtures/sample.xlsx') }
6
7
  let(:sheetfile) { 'worksheets/sheet1.xml' }
7
8
  let(:sheet_with_images) { Creek::Sheet.new(book_with_images, 'Sheet 1', 1, '', '', '1', sheetfile) }
8
- let(:sheet_no_images) { Creek::Sheet.new(book_no_images, 'Sheet 1', 1, '', '', '1', sheetfile) }
9
9
 
10
10
  def load_cell(rows, cell_name)
11
- cell = rows.find { |row| !row[cell_name].nil? }
11
+ cell = rows.find { |row| row[cell_name] }
12
12
  cell[cell_name] if cell
13
13
  end
14
14
 
15
15
  context 'escaped ampersand' do
16
16
  let(:book_escaped) { Creek::Book.new('spec/fixtures/escaped.xlsx') }
17
17
  it 'does NOT escape ampersand' do
18
- expect(book_escaped.sheets[0].rows.to_enum.map(&:values)).to eq([["abc", "def"], ["ghi", "j&k"]])
18
+ expect(book_escaped.sheets[0].rows.to_enum.map(&:values)).to eq([%w[abc def], %w[ghi j&k]])
19
19
  end
20
20
 
21
21
  let(:book_escaped2) { Creek::Book.new('spec/fixtures/escaped2.xlsx') }
22
22
  it 'does escape ampersand' do
23
- expect(book_escaped2.sheets[0].rows.to_enum.map(&:values)).to eq([["abc", "def"], ["ghi", "j&k"]])
23
+ expect(book_escaped2.sheets[0].rows.to_enum.map(&:values)).to eq([%w[abc def], %w[ghi j&k]])
24
24
  end
25
25
  end
26
26
 
@@ -66,6 +66,9 @@ describe 'sheet' do
66
66
  end
67
67
 
68
68
  context 'with excel without images' do
69
+ let(:book_no_images) { Creek::Book.new('spec/fixtures/sample.xlsx') }
70
+ let(:sheet_no_images) { Creek::Sheet.new(book_no_images, 'Sheet 1', 1, '', '', '1', sheetfile) }
71
+
69
72
  it 'does not break on with_images' do
70
73
  rows = sheet_no_images.with_images.rows.map { |r| r }
71
74
  expect(load_cell(rows, 'A10')).to eq(0.15)
@@ -94,4 +97,28 @@ describe 'sheet' do
94
97
  expect(image).to eq(nil)
95
98
  end
96
99
  end
100
+
101
+ describe '#simple_rows' do
102
+ let(:book_with_headers) { Creek::Book.new('spec/fixtures/sample-with-headers.xlsx') }
103
+ let(:sheet) { Creek::Sheet.new(book_with_headers, 'Sheet 1', 1, '', '', '1', sheetfile) }
104
+
105
+ subject { sheet.simple_rows.to_a[1] }
106
+
107
+ it 'returns values by letters' do
108
+ expect(subject['A']).to eq 'value1'
109
+ expect(subject['B']).to eq 'value2'
110
+ end
111
+
112
+ context 'when enable with_headers property' do
113
+ before { sheet.with_headers = true }
114
+
115
+ subject { sheet.simple_rows.to_a[1] }
116
+
117
+ it 'returns values by headers name' do
118
+ expect(subject['HeaderA']).to eq 'value1'
119
+ expect(subject['HeaderB']).to eq 'value2'
120
+ expect(subject['HeaderC']).to eq 'value3'
121
+ end
122
+ end
123
+ end
97
124
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: creek
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.1
4
+ version: 2.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - pythonicrubyist
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-08 00:00:00.000000000 Z
11
+ date: 2020-04-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -127,6 +127,7 @@ files:
127
127
  - spec/fixtures/invalid.xls
128
128
  - spec/fixtures/large_numbers.xlsx
129
129
  - spec/fixtures/sample-as-zip.zip
130
+ - spec/fixtures/sample-with-headers.xlsx
130
131
  - spec/fixtures/sample-with-images.xlsx
131
132
  - spec/fixtures/sample.xlsx
132
133
  - spec/fixtures/sample_dates.xlsx
@@ -161,7 +162,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
162
  - !ruby/object:Gem::Version
162
163
  version: '0'
163
164
  requirements: []
164
- rubygems_version: 3.0.3
165
+ rubygems_version: 3.0.8
165
166
  signing_key:
166
167
  specification_version: 4
167
168
  summary: A Ruby gem for parsing large Excel(xlsx and xlsm) files.
@@ -173,6 +174,7 @@ test_files:
173
174
  - spec/fixtures/invalid.xls
174
175
  - spec/fixtures/large_numbers.xlsx
175
176
  - spec/fixtures/sample-as-zip.zip
177
+ - spec/fixtures/sample-with-headers.xlsx
176
178
  - spec/fixtures/sample-with-images.xlsx
177
179
  - spec/fixtures/sample.xlsx
178
180
  - spec/fixtures/sample_dates.xlsx