creek 2.5.3 → 2.6.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: 0d90975898b7d260d37f6543755f8c2f4d5931d6e387a56c343bce23eee7e3b1
4
- data.tar.gz: 0c381e483070a0e883f128e1a03147a5acf60c4a1095b42ef0d3106af7889f8b
3
+ metadata.gz: d6c8bd9467a3772e8b09ecfce4dbef12d530cc094e44a0a9de3806d92930a46f
4
+ data.tar.gz: de59455bb37db21574fb55f269dd12faa3c4aeecbb52139ce5fdb6b0a7bb740a
5
5
  SHA512:
6
- metadata.gz: 1f23c318b54b45c2d1732c874e3f6519e7d528175a395b888e3352f302fb1f0b8625cdde965f16540081163282751dd410a712281651b9b3d3b91c9e89bec800
7
- data.tar.gz: e601060be6ba35b3bc3ded42865bce8b46fc3ca92feec1439dc2e719f132bb2359d06129f1110dc6676d07f7707364fead716f8f584a5851388a1d183c6e6825
6
+ metadata.gz: c0d5f95b17cd1e3cd7f0fb1286aa6a3a57875949b8a1c55c7eb34e0afe6f9bb34c373126273e5b20f77553c4e350fa8089c0398dfe23c55757a9c43a5ebd141c
7
+ data.tar.gz: ff1771e65a5add043080fa4ebb63c5b90a4e91d40ee7566996ae9e33a83dc0f6b54d327ee825a5759ee874a7219c4bcd2097b2e78e27374e5c7fc6d69fcccebd
@@ -0,0 +1,35 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ "*" ]
13
+ pull_request:
14
+ branches: [ "*" ]
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ test:
21
+
22
+ runs-on: ubuntu-latest
23
+ strategy:
24
+ matrix:
25
+ ruby-version: ['2.6', '2.7', '3.0', '3.1']
26
+
27
+ steps:
28
+ - uses: actions/checkout@v3
29
+ - name: Set up Ruby
30
+ uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: ${{ matrix.ruby-version }}
33
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
34
+ - name: Run tests
35
+ run: bundle exec rake
data/creek.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.required_ruby_version = '>= 2.0.0'
22
22
 
23
- spec.add_development_dependency "bundler", "~> 2.1.2"
23
+ spec.add_development_dependency "bundler"
24
24
  spec.add_development_dependency "rake"
25
25
  spec.add_development_dependency 'rspec', '~> 3.6.0'
26
26
  spec.add_development_dependency 'pry-byebug'
data/lib/creek/drawing.rb CHANGED
@@ -66,7 +66,7 @@ module Creek
66
66
  # Drawing xml contains relationships ID's and coordinates (row, col).
67
67
  # Drawing relationships xml contains images' locations.
68
68
  def load_drawings_and_rels
69
- @drawings = parse_xml(@drawing_filepath).css('xdr|twoCellAnchor')
69
+ @drawings = parse_xml(@drawing_filepath).css('xdr|twoCellAnchor', 'xdr|oneCellAnchor' )
70
70
  drawing_rels_filepath = expand_to_rels_path(@drawing_filepath)
71
71
  @drawings_rels = parse_xml(drawing_rels_filepath).css('Relationships')
72
72
  end
@@ -82,7 +82,7 @@ module Creek
82
82
  col_from_selector = 'xdr:from/xdr:col'.freeze
83
83
  col_to_selector = 'xdr:to/xdr:col'.freeze
84
84
 
85
- @drawings.xpath('//xdr:twoCellAnchor').each do |drawing|
85
+ @drawings.xpath('//xdr:twoCellAnchor', '//xdr:oneCellAnchor').each do |drawing|
86
86
  # embed = drawing.xpath(image_selector).first.attributes['embed']
87
87
  temp = drawing.xpath(image_selector).first
88
88
  embed = temp.attributes['embed'] if temp
@@ -93,12 +93,17 @@ module Creek
93
93
 
94
94
  row_from = drawing.xpath(row_from_selector).text.to_i
95
95
  col_from = drawing.xpath(col_from_selector).text.to_i
96
- row_to = drawing.xpath(row_to_selector).text.to_i
97
- col_to = drawing.xpath(col_to_selector).text.to_i
98
96
 
99
- (col_from..col_to).each do |col|
100
- (row_from..row_to).each do |row|
101
- @images_pathnames[[row, col]].push(path)
97
+ if drawing.name == 'oneCellAnchor'
98
+ @images_pathnames[[row_from , col_from ]].push(path)
99
+ else
100
+ row_to = drawing.xpath(row_to_selector).text.to_i
101
+ col_to = drawing.xpath(col_to_selector).text.to_i
102
+
103
+ (col_from..col_to).each do |col|
104
+ (row_from..row_to).each do |row|
105
+ @images_pathnames[[row, col]].push(path)
106
+ end
102
107
  end
103
108
  end
104
109
  end
@@ -5,6 +5,8 @@ module Creek
5
5
 
6
6
  class Creek::SharedStrings
7
7
 
8
+ SPREADSHEETML_URI = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'
9
+
8
10
  attr_reader :book, :dictionary
9
11
 
10
12
  def initialize book
@@ -27,9 +29,17 @@ module Creek
27
29
 
28
30
  def self.parse_shared_string_from_document(xml)
29
31
  dictionary = Hash.new
30
-
31
- xml.css('si').each_with_index do |si, idx|
32
- text_nodes = si.css('>t, r t')
32
+ namespace = xml.namespaces.detect{|_key, uri| uri == SPREADSHEETML_URI }
33
+ prefix = if namespace && namespace[0].start_with?('xmlns:')
34
+ namespace[0].delete_prefix('xmlns:') + '|'
35
+ else
36
+ ''
37
+ end
38
+ node_selector = "#{prefix}si"
39
+ text_selector = ">#{prefix}t, #{prefix}r #{prefix}t"
40
+
41
+ xml.css(node_selector).each_with_index do |si, idx|
42
+ text_nodes = si.css(text_selector)
33
43
  if text_nodes.count == 1 # plain text node
34
44
  dictionary[idx] = Creek::Styles::Converter.unescape_string(text_nodes.first.content)
35
45
  else # rich text nodes with text fragments
data/lib/creek/sheet.rb CHANGED
@@ -8,6 +8,7 @@ module Creek
8
8
  include Creek::Utils
9
9
 
10
10
  HEADERS_ROW_NUMBER = '1'
11
+ SPREADSHEETML_URI = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'
11
12
 
12
13
  attr_accessor :with_headers
13
14
  attr_reader :book,
@@ -97,13 +98,22 @@ module Creek
97
98
  cell_type = nil
98
99
  cell_style_idx = nil
99
100
  @book.files.file.open(path) do |xml|
101
+ prefix = ''
100
102
  Nokogiri::XML::Reader.from_io(xml).each do |node|
101
- if node.name == 'row' && node.node_type == opener
103
+ if prefix.empty? && node.namespaces.any?
104
+ namespace = node.namespaces.detect{|_key, uri| uri == SPREADSHEETML_URI }
105
+ prefix = if namespace && namespace[0].start_with?('xmlns:')
106
+ namespace[0].delete_prefix('xmlns:') + ':'
107
+ else
108
+ ''
109
+ end
110
+ end
111
+ if node.name == "#{prefix}row" && node.node_type == opener
102
112
  row = node.attributes
103
113
  row['cells'] = {}
104
114
  cells = {}
105
115
  y << (include_meta_data ? row : cells) if node.self_closing?
106
- elsif node.name == 'row' && node.node_type == closer
116
+ elsif node.name == "#{prefix}row" && node.node_type == closer
107
117
  processed_cells = fill_in_empty_cells(cells, row['r'], cell, use_simple_rows_format)
108
118
  @headers = processed_cells if with_headers && row['r'] == HEADERS_ROW_NUMBER
109
119
 
@@ -117,11 +127,11 @@ module Creek
117
127
 
118
128
  row['cells'] = processed_cells
119
129
  y << (include_meta_data ? row : processed_cells)
120
- elsif node.name == 'c' && node.node_type == opener
130
+ elsif node.name == "#{prefix}c" && node.node_type == opener
121
131
  cell_type = node.attributes['t']
122
132
  cell_style_idx = node.attributes['s']
123
133
  cell = node.attributes['r']
124
- elsif %w[v t].include?(node.name) && node.node_type == opener
134
+ elsif ["#{prefix}v", "#{prefix}t"].include?(node.name) && node.node_type == opener
125
135
  unless cell.nil?
126
136
  node.read
127
137
  cells[cell] = convert(node.value, cell_type, cell_style_idx)
data/lib/creek/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Creek
2
- VERSION = "2.5.3"
2
+ VERSION = "2.6.2"
3
3
  end
data/spec/drawing_spec.rb CHANGED
@@ -3,9 +3,11 @@ require './spec/spec_helper'
3
3
  describe 'drawing' do
4
4
  let(:book) { Creek::Book.new('spec/fixtures/sample-with-images.xlsx') }
5
5
  let(:book_no_images) { Creek::Book.new('spec/fixtures/sample.xlsx') }
6
+ let(:book_with_one_cell_anchored_images) { Creek::Book.new('spec/fixtures/sample-with-one-cell-anchored-images.xlsx') }
6
7
  let(:drawingfile) { 'xl/drawings/drawing1.xml' }
7
8
  let(:drawing) { Creek::Drawing.new(book, drawingfile) }
8
9
  let(:drawing_without_images) { Creek::Drawing.new(book_no_images, drawingfile) }
10
+ let(:drawing_with_one_cell_anchored_images) { Creek::Drawing.new(book_with_one_cell_anchored_images, drawingfile) }
9
11
 
10
12
  describe '#has_images?' do
11
13
  it 'has' do
@@ -48,5 +50,21 @@ describe 'drawing' do
48
50
  expect(image1).to eq(image2)
49
51
  end
50
52
  end
53
+
54
+ context 'when one cell anchored images in cell' do
55
+ it 'returns image for anchored cell' do
56
+ image = drawing_with_one_cell_anchored_images.images_at('A2')[0]
57
+ expect(image.class).to eq(Pathname)
58
+ expect(image.exist?).to eq(true)
59
+ end
60
+
61
+ it 'returns nil for non-anchored cell' do
62
+ image = drawing_with_one_cell_anchored_images.images_at('A3')[0]
63
+ # Image can be seen present on cell A4 in `sample-with-one-cell-anchored-images.xlsx`
64
+ image_at_non_anchored_cell = drawing_with_one_cell_anchored_images.images_at('A4')
65
+ expect(image.class).to eq(Pathname)
66
+ expect(image_at_non_anchored_cell).to eq(nil)
67
+ end
68
+ end
51
69
  end
52
70
  end
@@ -0,0 +1,91 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
+ <sst xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="6" uniqueCount="5">
3
+ <x:si>
4
+ <x:t>Cell A1</x:t>
5
+ </x:si>
6
+ <x:si>
7
+ <x:t>Cell B1</x:t>
8
+ </x:si>
9
+ <x:si>
10
+ <x:t>My Cell</x:t>
11
+ </x:si>
12
+ <x:si>
13
+ <x:r>
14
+ <x:rPr>
15
+ <x:sz val="11"/>
16
+ <x:color rgb="FFFF0000"/>
17
+ <x:rFont val="Calibri"/>
18
+ <x:family val="2"/>
19
+ <x:scheme val="minor"/>
20
+ </x:rPr>
21
+ <x:t>Cell</x:t>
22
+ </x:r>
23
+ <x:r>
24
+ <x:rPr>
25
+ <x:sz val="11"/>
26
+ <x:color theme="1"/>
27
+ <x:rFont val="Calibri"/>
28
+ <x:family val="2"/>
29
+ <x:scheme val="minor"/>
30
+ </x:rPr>
31
+ <x:t xml:space="preserve"> </x:t>
32
+ </x:r>
33
+ <x:r>
34
+ <x:rPr>
35
+ <x:b/>
36
+ <x:sz val="11"/>
37
+ <x:color theme="1"/>
38
+ <x:rFont val="Calibri"/>
39
+ <x:family val="2"/>
40
+ <x:scheme val="minor"/>
41
+ </x:rPr>
42
+ <x:t>A2</x:t>
43
+ </x:r>
44
+ </x:si>
45
+ <x:si>
46
+ <x:r>
47
+ <x:rPr>
48
+ <x:sz val="11"/>
49
+ <x:color rgb="FF00B0F0"/>
50
+ <x:rFont val="Calibri"/>
51
+ <x:family val="2"/>
52
+ <x:scheme val="minor"/>
53
+ </x:rPr>
54
+ <x:t>Cell</x:t>
55
+ </x:r>
56
+ <x:r>
57
+ <x:rPr>
58
+ <x:sz val="11"/>
59
+ <x:color theme="1"/>
60
+ <x:rFont val="Calibri"/>
61
+ <x:family val="2"/>
62
+ <x:scheme val="minor"/>
63
+ </x:rPr>
64
+ <x:t xml:space="preserve"> </x:t>
65
+ </x:r>
66
+ <x:r>
67
+ <x:rPr>
68
+ <x:i/>
69
+ <x:sz val="11"/>
70
+ <x:color theme="1"/>
71
+ <x:rFont val="Calibri"/>
72
+ <x:family val="2"/>
73
+ <x:scheme val="minor"/>
74
+ </x:rPr>
75
+ <x:t>B2</x:t>
76
+ </x:r>
77
+ </x:si>
78
+ <x:si>
79
+ <x:t>Cell with_x000D_escaped_x000D_characters</x:t>
80
+ </x:si>
81
+ <x:si>
82
+ <x:t>吉田兼好</x:t>
83
+ <x:rPh sb="0" eb="2">
84
+ <x:t xml:space="preserve">ヨシダ </x:t>
85
+ </x:rPh>
86
+ <x:rPh sb="2" eb="4">
87
+ <x:t xml:space="preserve">ケンコウ </x:t>
88
+ </x:rPh>
89
+ <x:phoneticPr fontId="1"/>
90
+ </x:si>
91
+ </x:sst>
@@ -17,4 +17,21 @@ describe 'shared strings' do
17
17
  expect(dictionary[6]).to eq('吉田兼好')
18
18
  end
19
19
 
20
- end
20
+ context 'when the nodes are namespaced' do
21
+ it 'parses the dictionary correctly' do
22
+ shared_strings_xml_file = File.open('spec/fixtures/sst_namespaced.xml')
23
+ doc = Nokogiri::XML(shared_strings_xml_file)
24
+ dictionary = Creek::SharedStrings.parse_shared_string_from_document(doc)
25
+
26
+ expect(dictionary.keys.size).to eq(7)
27
+ expect(dictionary[0]).to eq('Cell A1')
28
+ expect(dictionary[1]).to eq('Cell B1')
29
+ expect(dictionary[2]).to eq('My Cell')
30
+ expect(dictionary[3]).to eq('Cell A2')
31
+ expect(dictionary[4]).to eq('Cell B2')
32
+ expect(dictionary[5]).to eq("Cell with\rescaped\rcharacters")
33
+ expect(dictionary[6]).to eq('吉田兼好')
34
+ end
35
+
36
+ end
37
+ end
data/spec/sheet_spec.rb CHANGED
@@ -65,6 +65,20 @@ describe 'sheet' do
65
65
  end
66
66
  end
67
67
 
68
+ context 'when one cell anchored images in cell' do
69
+ let(:book_with_one_cell_anchored_images) { Creek::Book.new('spec/fixtures/sample-with-one-cell-anchored-images.xlsx') }
70
+ let(:sheet_with_one_cell_anchored_images) { Creek::Sheet.new(book_with_one_cell_anchored_images, 'Sheet 1', 1, '', '', '1', sheetfile) }
71
+ let(:rows) { sheet_with_one_cell_anchored_images.with_images.rows.map { |r| r } }
72
+
73
+ it 'returns image for anchored cell' do
74
+ expect(load_cell(rows, 'A2').size).to eq(1)
75
+ end
76
+
77
+ it 'returns nil for non-anchored cell' do
78
+ expect(load_cell(rows, 'A4')).to eq(nil)
79
+ end
80
+ end
81
+
68
82
  context 'with excel without images' do
69
83
  let(:book_no_images) { Creek::Book.new('spec/fixtures/sample.xlsx') }
70
84
  let(:sheet_no_images) { Creek::Sheet.new(book_no_images, 'Sheet 1', 1, '', '', '1', sheetfile) }
@@ -74,6 +88,16 @@ describe 'sheet' do
74
88
  expect(load_cell(rows, 'A10')).to eq(0.15)
75
89
  end
76
90
  end
91
+
92
+ context 'when nodes are namespaced' do
93
+ let(:namespaced_book) { Creek::Book.new('spec/fixtures/sample_namespaced.xlsx') }
94
+ let(:namespaced_sheet) { Creek::Sheet.new(namespaced_book, 'Sheet 1', 1, '', '', '1', sheetfile) }
95
+
96
+ it 'parses rows correctly' do
97
+ rows = namespaced_sheet.rows.map { |r| r }
98
+ expect(load_cell(rows, 'A10')).to eq(0.15)
99
+ end
100
+ end
77
101
  end
78
102
 
79
103
  describe '#images_at' do
@@ -130,5 +154,37 @@ describe 'sheet' do
130
154
  expect(row['HeaderC']).to eq 'value3'
131
155
  end
132
156
  end
157
+
158
+ context 'when nodes are namespaced' do
159
+ let(:namespaced_book) { Creek::Book.new('spec/fixtures/sample-with-headers_namespaced.xlsx') }
160
+ let(:sheet) { Creek::Sheet.new(namespaced_book, 'Sheet 1', 1, '', '', '1', sheetfile) }
161
+
162
+ it 'returns values by letters' do
163
+ expect(subject['A']).to eq 'value1'
164
+ expect(subject['B']).to eq 'value2'
165
+ end
166
+
167
+ context 'when enable with_headers property' do
168
+ before { sheet.with_headers = true }
169
+
170
+ it 'returns values by headers name' do
171
+ expect(subject['HeaderA']).to eq 'value1'
172
+ expect(subject['HeaderB']).to eq 'value2'
173
+ expect(subject['HeaderC']).to eq 'value3'
174
+ end
175
+
176
+ it 'returns headers correctly when called multiple times' do
177
+ row = sheet.simple_rows.to_a[1]
178
+ expect(row['HeaderA']).to eq 'value1'
179
+ expect(row['HeaderB']).to eq 'value2'
180
+ expect(row['HeaderC']).to eq 'value3'
181
+
182
+ row = sheet.simple_rows.to_a[1]
183
+ expect(row['HeaderA']).to eq 'value1'
184
+ expect(row['HeaderB']).to eq 'value2'
185
+ expect(row['HeaderC']).to eq 'value3'
186
+ end
187
+ end
188
+ end
133
189
  end
134
190
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: creek
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.3
4
+ version: 2.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - pythonicrubyist
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-12 00:00:00.000000000 Z
11
+ date: 2022-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 2.1.2
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 2.1.2
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -103,6 +103,7 @@ extensions: []
103
103
  extra_rdoc_files: []
104
104
  files:
105
105
  - ".DS_Store"
106
+ - ".github/workflows/test.yml"
106
107
  - ".gitignore"
107
108
  - Gemfile
108
109
  - LICENSE.txt
@@ -128,13 +129,17 @@ files:
128
129
  - spec/fixtures/large_numbers.xlsx
129
130
  - spec/fixtures/sample-as-zip.zip
130
131
  - spec/fixtures/sample-with-headers.xlsx
132
+ - spec/fixtures/sample-with-headers_namespaced.xlsx
131
133
  - spec/fixtures/sample-with-images.xlsx
134
+ - spec/fixtures/sample-with-one-cell-anchored-images.xlsx
132
135
  - spec/fixtures/sample.xlsx
133
136
  - spec/fixtures/sample_dates.xlsx
137
+ - spec/fixtures/sample_namespaced.xlsx
134
138
  - spec/fixtures/sheets/sample_dates.xlsx
135
139
  - spec/fixtures/sheets/sheet1.xml
136
140
  - spec/fixtures/sheets/single_data_programme.xlsx
137
141
  - spec/fixtures/sst.xml
142
+ - spec/fixtures/sst_namespaced.xml
138
143
  - spec/fixtures/styles/first.xml
139
144
  - spec/fixtures/temp_string_io_file_path_with_no_extension
140
145
  - spec/shared_string_spec.rb
@@ -162,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
162
167
  - !ruby/object:Gem::Version
163
168
  version: '0'
164
169
  requirements: []
165
- rubygems_version: 3.0.3
170
+ rubygems_version: 3.0.3.1
166
171
  signing_key:
167
172
  specification_version: 4
168
173
  summary: A Ruby gem for parsing large Excel(xlsx and xlsm) files.
@@ -175,13 +180,17 @@ test_files:
175
180
  - spec/fixtures/large_numbers.xlsx
176
181
  - spec/fixtures/sample-as-zip.zip
177
182
  - spec/fixtures/sample-with-headers.xlsx
183
+ - spec/fixtures/sample-with-headers_namespaced.xlsx
178
184
  - spec/fixtures/sample-with-images.xlsx
185
+ - spec/fixtures/sample-with-one-cell-anchored-images.xlsx
179
186
  - spec/fixtures/sample.xlsx
180
187
  - spec/fixtures/sample_dates.xlsx
188
+ - spec/fixtures/sample_namespaced.xlsx
181
189
  - spec/fixtures/sheets/sample_dates.xlsx
182
190
  - spec/fixtures/sheets/sheet1.xml
183
191
  - spec/fixtures/sheets/single_data_programme.xlsx
184
192
  - spec/fixtures/sst.xml
193
+ - spec/fixtures/sst_namespaced.xml
185
194
  - spec/fixtures/styles/first.xml
186
195
  - spec/fixtures/temp_string_io_file_path_with_no_extension
187
196
  - spec/shared_string_spec.rb