simple_xlsx_reader 4.0.1 → 5.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5e0de15ab326f027127322eac9d88d752ffd2d55797df23ed525a7eea1d9833
4
- data.tar.gz: 415972aaf4f77e4bdb5e60b0095cf01f6d7e24a0cd28d493c8ad8d01fa50d66b
3
+ metadata.gz: f779f6e272fd4b79b2da180f31eb71b40e51b25d96f50fa72180908472c56750
4
+ data.tar.gz: 6bd6d85c61aaede6aebbe24f88b8fcc8a4018345581a3793e6e3a89a7bc285ab
5
5
  SHA512:
6
- metadata.gz: cfea3adb62767bedfe6470377b54078066b1bf07e13c065160a31c260261f65a658c34c37dc850c01dd27ba7038a4261f1a6ea9c6ff42771e8113dbabc51897b
7
- data.tar.gz: a4b996c3d15b2f54a61d8fc90366ba502d6bc108b1bfe5ed34b9d46f63fe7c52381f181421cc31eea46b7c73e6925d3aa3cfeb8e1b737021be93e4863ea9e703
6
+ metadata.gz: 63b52b5835fe344b7a8116c6217c6df2f1ec9e68b2876212dec1b08a22dc33549f81905079d7ccea8f2612455e70ab1719aad82229d4fbc00d6da92e4c1ca7a1
7
+ data.tar.gz: e9e615a600b5bd19c7510fc1b0cbd42e2a2a5494ca9da63be9de813b1bedff73045faa3d0b2f2c8c7b6a7eefecc1219fbbcf6a9f79971b30ba2f8e8c7417cdd8
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
@@ -22,10 +22,10 @@ jobs:
22
22
  runs-on: ubuntu-latest
23
23
  strategy:
24
24
  matrix:
25
- ruby-version: ['2.6', '2.7', '3.0', '3.1', '3.2']
25
+ ruby-version: ['2.6', '2.7', '3.0', '3.1', '3.2', '3.3']
26
26
 
27
27
  steps:
28
- - uses: actions/checkout@v3
28
+ - uses: actions/checkout@v4
29
29
  - name: Set up Ruby
30
30
  uses: ruby/setup-ruby@v1
31
31
  with:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ### 5.1.0
2
+
3
+ * Parse sheets containing namespaces and no 'r' att (@skipchris)
4
+ * Fix Zlib error when loading from string (@myabc)
5
+ * Prevent a SimpleXlsxReader::CellLoadError (no implicit conversion of Integer
6
+ into String) when the casted value (friendly name) is not a string (@tsdbrown)
7
+ * Accidental 25% perfarmance improvement while experimenting with namespace
8
+ support (see #53f5a9).
9
+
10
+ ### 5.0.0
11
+
12
+ * Change SimpleXlsxReader::Hyperlink to default to the visible cell value
13
+ instead of the hyperlink URL, which in the case of mailto hyperlinks is
14
+ surprising.
15
+ * Fix blank content when parsing docs from string (@codemole)
16
+
1
17
  ### 4.0.1
2
18
 
3
19
  * Fix nil error when handling some inline strings
data/README.md CHANGED
@@ -9,15 +9,17 @@ then forgotten. We just want to get the data, and get out!
9
9
 
10
10
  ## Summary (now with stream parsing):
11
11
 
12
- doc = SimpleXlsxReader.open('/path/to/workbook.xlsx')
13
- doc.sheets # => [<#SXR::Sheet>, ...]
14
- doc.sheets.first.name # 'Sheet1'
15
- doc.sheets.first.rows # <SXR::Document::RowsProxy>
16
- doc.sheets.first.rows.each # an <Enumerator> ready to chain or stream
17
- doc.sheets.first.rows.each {} # Streams the rows to your block
18
- doc.sheets.first.rows.each(headers: true) {} # Streams row-hashes
19
- doc.sheets.first.rows.each(headers: {id: /ID/}) {} # finds & maps headers, streams
20
- doc.sheets.first.rows.slurp # Slurps rows into memory as a 2D array
12
+ ```ruby
13
+ doc = SimpleXlsxReader.open('/path/to/workbook.xlsx')
14
+ doc.sheets # => [<#SXR::Sheet>, ...]
15
+ doc.sheets.first.name # 'Sheet1'
16
+ rows = doc.sheets.first.rows # <SXR::Document::RowsProxy>
17
+ rows.each # an <Enumerator> ready to chain or stream
18
+ rows.each {} # Streams the rows to your block
19
+ rows.each(headers: true) {} # Streams row-hashes
20
+ rows.each(headers: {id: /ID/}) {} # finds & maps headers, streams
21
+ rows.slurp # Slurps rows into memory as a 2D array
22
+ ```
21
23
 
22
24
  That's the gist of it!
23
25
 
@@ -29,7 +31,8 @@ See also the [Document](https://github.com/woahdae/simple_xlsx_reader/blob/2.0.0
29
31
 
30
32
  This project was started years ago, primarily because other Ruby xlsx parsers
31
33
  didn't import data with the correct types. Numbers as strings, dates as numbers,
32
- hyperlinks with inaccessible URLs, or - subtly buggy - simple dates as DateTime
34
+ [hyperlinks](https://github.com/woahdae/simple_xlsx_reader/blob/master/lib/simple_xlsx_reader/hyperlink.rb)
35
+ with inaccessible URLs, or - subtly buggy - simple dates as DateTime
33
36
  objects. If your app uses a timezone offset, depending on what timezone and
34
37
  what time of day you load the xlsx file, your dates might end up a day off!
35
38
  SimpleXlsxReader understands all these correctly.
@@ -39,12 +42,14 @@ SimpleXlsxReader understands all these correctly.
39
42
  Many Ruby xlsx parsers seem to be inspired more by Excel than Ruby, frankly.
40
43
  SimpleXlsxReader strives to be fairly idiomatic Ruby:
41
44
 
42
- # quick example having fun w/ ruby
43
- doc = SimpleXlsxReader.open(path_or_io)
44
- doc.sheets.first.rows.each(headers: {id: /ID/})
45
- .with_index.with_object({}) do |(row, index), acc|
46
- acc[row[:id]] = index
47
- end
45
+ ```ruby
46
+ # quick example having fun w/ ruby
47
+ doc = SimpleXlsxReader.open(file_path) # or SimpleXlsxReader.parse(string_or_io)
48
+ doc.sheets.first.rows.each(headers: {id: /ID/})
49
+ .with_index.with_object({}) do |(row, index), acc|
50
+ acc[row[:id]] = index
51
+ end
52
+ ```
48
53
 
49
54
  ### Now faster
50
55
 
@@ -77,15 +82,19 @@ If you had an excel sheet representing this data:
77
82
 
78
83
  Get a handle on the rows proxy:
79
84
 
80
- `rows = SimpleXlsxReader.open('suited_heroes.xlsx').sheets.first.rows`
85
+ ```ruby
86
+ rows = SimpleXlsxReader.open('suited_heroes.xlsx').sheets.first.rows
87
+ ```
81
88
 
82
89
  Simple streaming (kinda boring):
83
90
 
84
- `rows.each { |row| ... }`
91
+ ```ruby
92
+ rows.each { |row| ... }
93
+ ````
85
94
 
86
95
  Streaming with headers, and how about a little enumerable chaining:
87
96
 
88
- ```
97
+ ```ruby
89
98
  # Map of hero names by ID: { 117 => 'John Halo', ... }
90
99
 
91
100
  rows.each(headers: true).with_object({}) do |row, acc|
@@ -108,7 +117,7 @@ Sometimes though you have some junk at the top of your spreadsheet:
108
117
  For this, `headers` can be a hash whose keys replace headers and whose values
109
118
  help find the correct header row:
110
119
 
111
- ```
120
+ ```ruby
112
121
  # Same map of hero names by ID: { 117 => 'John Halo', ... }
113
122
 
114
123
  rows.each(headers: {id: /ID/, name: /Name/}).with_object({}) do |row, acc|
@@ -119,7 +128,7 @@ end
119
128
  If your header-to-attribute mapping is more complicated than key/value, you
120
129
  can do the mapping elsewhere, but use a block to find the header row:
121
130
 
122
- ```
131
+ ```ruby
123
132
  # Example roughly analogous to some production code mapping a single spreadsheet
124
133
  # across many objects. Might be a simpler way now that we have the headers-hash
125
134
  # feature.
@@ -168,9 +177,11 @@ can set `SimpleXlsxReader.configuration.catch_cell_load_errors =
168
177
  true`, and load errors will instead be inserted into Sheet#load_errors keyed
169
178
  by [rownum, colnum]:
170
179
 
171
- {
172
- [rownum, colnum] => '[error]'
173
- }
180
+ ```ruby
181
+ {
182
+ [rownum, colnum] => '[error]'
183
+ }
184
+ ```
174
185
 
175
186
  ### Performance
176
187
 
@@ -233,11 +244,9 @@ This project follows [semantic versioning 1.0](http://semver.org/spec/v1.0.0.htm
233
244
  Remember to write tests, think about edge cases, and run the existing
234
245
  suite.
235
246
 
236
- Note that as of commit 665cbafdde, the most extreme end of the
237
- linear-time performance test, which is 10,000 rows (12 columns), runs in
238
- ~4 seconds on Ruby 2.1 on a 2012 MBP. If the linear time assertion fails
239
- or you're way off that, there is probably a performance regression in
240
- your code.
247
+ The full suite contains a performance test that on an M1 MBP runs the final
248
+ large file in about five seconds. Check out that test before & after your
249
+ change to check for performance changes.
241
250
 
242
251
  Then, the standard stuff:
243
252
 
@@ -4,27 +4,26 @@ module SimpleXlsxReader
4
4
  # We support hyperlinks as a "type" even though they're technically
5
5
  # represented either as a function or an external reference in the xlsx spec.
6
6
  #
7
- # Since having hyperlink data in our sheet usually means we might want to do
8
- # something primarily with the URL (store it in the database, download it, etc),
9
- # we go through extra effort to parse the function or follow the reference
10
- # to represent the hyperlink primarily as a URL. However, maybe we do want
11
- # the hyperlink "friendly name" part (as MS calls it), so here we've subclassed
12
- # string to tack on the friendly name. This means 80% of us that just want
13
- # the URL value will have to do nothing extra, but the 20% that might want the
14
- # friendly name can access it.
7
+ # In practice, hyperlinks are usually a link or a mailto. In the case of a
8
+ # link, we probably want to follow it to download something, but in the case
9
+ # of an email, we probably just want the email and not the mailto. So we
10
+ # represent a hyperlink primarily as it is seen by the user, following the
11
+ # principle of least surprise, but the url is accessible via #url.
15
12
  #
16
- # Note, by default, the value we would get by just asking the cell would
17
- # be the "friendly name" and *not* the URL, which is tucked away in the
18
- # function definition or a separate "relationships" meta-document.
13
+ # Microsoft calls the visible part of a hyperlink cell the "friendly name,"
14
+ # so we expose that as a method too, in case you want to be explicit about
15
+ # how you're accessing it.
19
16
  #
20
17
  # See MS documentation on the HYPERLINK function for some background:
21
18
  # https://support.office.com/en-us/article/HYPERLINK-function-333c7ce6-c5ae-4164-9c47-7de9b76f577f
22
19
  class Hyperlink < String
23
20
  attr_reader :friendly_name
21
+ attr_reader :url
24
22
 
25
23
  def initialize(url, friendly_name = nil)
26
- @friendly_name = friendly_name
27
- super(url)
24
+ @url = url
25
+ @friendly_name = friendly_name&.to_s
26
+ super(@friendly_name || @url)
28
27
  end
29
28
  end
30
29
  end
@@ -31,9 +31,11 @@ module SimpleXlsxReader
31
31
  @url = nil # silence warnings
32
32
  @function = nil # silence warnings
33
33
  @capture = nil # silence warnings
34
+ @captured = nil # silence warnings
34
35
  @dimension = nil # silence warnings
36
+ @column_index = 0
35
37
 
36
- @file_io.rewind # in case we've already parsed this once
38
+ @file_io.rewind # if it's IO from IO.read, we need to rewind it
37
39
 
38
40
  # In this project this is only used for GUI-made hyperlinks (as opposed
39
41
  # to FUNCTION-based hyperlinks). Unfortunately the're needed to parse
@@ -41,10 +43,12 @@ module SimpleXlsxReader
41
43
  # to just stream-parse the file twice, first for the hyperlinks at the
42
44
  # bottom of the file, then for the file itself. In the future it would
43
45
  # be clever to use grep to extract the xml into its own smaller file.
44
- if xrels_file&.grep(/hyperlink/)&.any?
45
- xrels_file.rewind
46
- load_gui_hyperlinks # represented as hyperlinks_by_cell
47
- @file_io.rewind
46
+ if xrels_file
47
+ if xrels_file.grep(/hyperlink/).any?
48
+ xrels_file.rewind
49
+ load_gui_hyperlinks # represented as hyperlinks_by_cell
50
+ end
51
+ @file_io.rewind # we've already parsed this once
48
52
  end
49
53
 
50
54
  Nokogiri::XML::SAX::Parser.new(self).parse(@file_io)
@@ -53,17 +57,20 @@ module SimpleXlsxReader
53
57
  ###
54
58
  # SAX document hooks
55
59
 
56
- def start_element(name, attrs = [])
60
+ def start_element_namespace(name, attrs = [], _prefix, _uri, _ns)
57
61
  case name
58
- when 'dimension' then @dimension = attrs.last.last
62
+ when 'dimension'
63
+ @dimension = attrs.last.value
59
64
  when 'row'
60
- @current_row_num = attrs.find {|(k, v)| k == 'r'}&.last&.to_i
65
+ @current_row_num = attrs.find {|attr| attr.localname == 'r'}&.value&.to_i
61
66
  @current_row = Array.new(column_length)
67
+ @column_index = 0
62
68
  when 'c'
63
- attrs = attrs.inject({}) {|acc, (k, v)| acc[k] = v; acc}
64
- @cell_name = attrs['r']
69
+ attrs = attrs.inject({}) {|acc, attr| acc[attr.localname] = attr.value; acc}
70
+ @cell_name = attrs['r'] || column_number_to_letter(@column_index)
65
71
  @type = attrs['t']
66
72
  @style = attrs['s'] && style_types[attrs['s'].to_i]
73
+ @column_index += 1
67
74
  when 'f' then @function = true
68
75
  when 'v', 't' then @capture = true
69
76
  end
@@ -114,7 +121,7 @@ module SimpleXlsxReader
114
121
  @captured = @captured ? @captured + (captured || '') : captured
115
122
  end
116
123
 
117
- def end_element(name)
124
+ def end_element_namespace(name, _prefix, _uri)
118
125
  case name
119
126
  when 'row'
120
127
  if @headers == true # ya a little funky
@@ -208,10 +215,10 @@ module SimpleXlsxReader
208
215
  @hyperlinks_by_cell
209
216
  end
210
217
 
211
- def start_element(name, attrs)
218
+ def start_element_namespace(name, attrs, _prefix, _uri, _ns)
212
219
  case name
213
220
  when 'hyperlink'
214
- attrs = attrs.inject({}) {|acc, (k, v)| acc[k] = v; acc}
221
+ attrs = attrs.inject({}) {|acc, attr| acc[attr.localname] = attr.value; acc}
215
222
  id = attrs['id'] || attrs['r:id']
216
223
 
217
224
  @hyperlinks_by_cell[attrs['ref']] =
@@ -264,6 +271,16 @@ module SimpleXlsxReader
264
271
  end
265
272
  result
266
273
  end
274
+
275
+ def column_number_to_letter(n)
276
+ result = []
277
+ loop do
278
+ result.unshift((n % 26 + 65).chr)
279
+ n = (n / 26) - 1
280
+ break if n < 0
281
+ end
282
+ result.join
283
+ end
267
284
  end
268
285
  end
269
286
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleXlsxReader
4
- VERSION = '4.0.1'
4
+ VERSION = '5.1.0'
5
5
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'test_helper'
4
+
5
+ describe SimpleXlsxReader do
6
+ # Based on a real-world sheet possibly generated by PowerBI, where the xml
7
+ # has namespacing and rows are missing the 'r' attribute.
8
+ let(:sheet) do
9
+ <<~XML
10
+ <?xml version="1.0" encoding="utf-8"?>
11
+ <x:worksheet xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
12
+ <x:sheetData>
13
+ <x:row>
14
+ <x:c s="2" t="inlineStr">
15
+ <x:is>
16
+ <x:t>Salmon</x:t>
17
+ </x:is>
18
+ </x:c>
19
+ <x:c s="2" t="inlineStr">
20
+ <x:is>
21
+ <x:t>Trout</x:t>
22
+ </x:is>
23
+ </x:c>
24
+ </x:row>
25
+ <x:row>
26
+ <x:c s="2" t="inlineStr">
27
+ <x:is>
28
+ <x:t>Cat</x:t>
29
+ </x:is>
30
+ </x:c>
31
+ <x:c s="2" t="inlineStr">
32
+ <x:is>
33
+ <x:t>Dog</x:t>
34
+ </x:is>
35
+ </x:c>
36
+ </x:row>
37
+ </x:sheetData>
38
+ </x:worksheet>
39
+ XML
40
+ end
41
+
42
+ let(:styles) do
43
+ <<~XML
44
+ <?xml version="1.0" encoding="utf-8"?><x:styleSheet xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><x:numFmts><x:numFmt numFmtId="181" formatCode="0" /><x:numFmt numFmtId="182" formatCode="m/d/yyyy h:mm:ss AM/PM" /><x:numFmt numFmtId="183" formatCode="dd MMMM yyyy" /></x:numFmts><x:fonts><x:font /><x:font><x:b /></x:font></x:fonts><x:fills><x:fill><x:patternFill patternType="none" /></x:fill><x:fill><x:patternFill patternType="gray125" /></x:fill></x:fills><x:borders><x:border /><x:border><x:bottom style="thin" /></x:border><x:border><x:right style="thin" /></x:border></x:borders><x:cellXfs><x:xf /><x:xf fontId="1" /><x:xf borderId="1" /><x:xf fontId="1" borderId="1" /><x:xf borderId="2" /><x:xf fontId="1" borderId="2" /><x:xf><x:alignment vertical="top" /></x:xf><x:xf fontId="1"><x:alignment vertical="top" /></x:xf><x:xf numFmtId="181" /><x:xf numFmtId="182" /><x:xf numFmtId="183" /><x:xf numFmtId="182" fontId="1" /><x:xf numFmtId="181" fontId="1" /><x:xf numFmtId="183" fontId="1" /></x:cellXfs></x:styleSheet>
45
+ XML
46
+ end
47
+
48
+ let(:wonky_file) do
49
+ TestXlsxBuilder.new(
50
+ sheets: [sheet],
51
+ styles: styles
52
+ )
53
+ end
54
+
55
+ let(:subject) { SimpleXlsxReader::Document.new(wonky_file.archive.path) }
56
+
57
+ describe '#to_hash' do
58
+ it 'should extract values from namespaced cells missing "r" attributes' do
59
+ _(subject.sheets.first.rows.to_a[0]).must_include('Salmon')
60
+ _(subject.sheets.first.rows.to_a[1]).must_include('Dog')
61
+ end
62
+ end
63
+ end
@@ -70,7 +70,7 @@ describe 'SimpleXlsxReader Benchmark' do
70
70
  let(:styles) do
71
71
  # s='0' above refers to the value of numFmtId at cellXfs index 0,
72
72
  # which is in this case 'General' type
73
- styles =
73
+ _styles =
74
74
  <<-XML
75
75
  <styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
76
76
  <cellXfs count="1">
@@ -56,7 +56,7 @@ describe SimpleXlsxReader do
56
56
  end
57
57
 
58
58
  describe 'load from string' do
59
- let(:subject) { SimpleXlsxReader.parse(sesame_street_blog_io) }
59
+ let(:subject) { SimpleXlsxReader.parse(sesame_street_blog_string) }
60
60
 
61
61
  it 'reads an xlsx string into a hash of {[sheet name] => [data]}' do
62
62
  _(subject.to_hash).must_equal(expected_result)
@@ -92,7 +92,7 @@ describe SimpleXlsxReader do
92
92
  body: 'The Greatest',
93
93
  created_at: Time.parse('2002-01-01 11:00:00 UTC'),
94
94
  count: 1,
95
- "URL" => 'http://www.example.com/hyperlink-function'
95
+ "URL" => 'This uses the HYPERLINK() function'
96
96
  )
97
97
 
98
98
  _(rows.slurped?).must_equal false
@@ -611,6 +611,11 @@ describe SimpleXlsxReader do
611
611
  _(described_class.cast('2', 's', nil, shared_strings: %w[a b c], url: url))
612
612
  .must_equal SXR::Hyperlink.new(url, 'c')
613
613
  end
614
+
615
+ it 'creates a hyperlink with a fixnum friendly_name' do
616
+ _(described_class.cast('123', nil, :fixnum, url: url))
617
+ .must_equal SXR::Hyperlink.new(url, '123')
618
+ end
614
619
  end
615
620
  end
616
621
 
@@ -1031,6 +1036,52 @@ describe SimpleXlsxReader do
1031
1036
  end
1032
1037
  end
1033
1038
 
1039
+ describe 'parsing documents with non-hyperlinked rels' do
1040
+ let(:rels) do
1041
+ [
1042
+ Nokogiri::XML(
1043
+ <<-XML
1044
+ <?xml version="1.0" encoding="UTF-8"?>
1045
+ <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>
1046
+ XML
1047
+ ).remove_namespaces!
1048
+ ]
1049
+ end
1050
+
1051
+ describe 'when document is opened as path' do
1052
+ before do
1053
+ @row = SimpleXlsxReader.open(xlsx.archive.path).sheets[0].rows.to_a[0]
1054
+ end
1055
+
1056
+ it 'reads cell content' do
1057
+ _(@row[0]).must_equal 'Cell A'
1058
+ end
1059
+ end
1060
+
1061
+ describe 'when document is parsed as a String' do
1062
+ before do
1063
+ output = File.binread(xlsx.archive.path)
1064
+ @row = SimpleXlsxReader.parse(output).sheets[0].rows.to_a[0]
1065
+ end
1066
+
1067
+ it 'reads cell content' do
1068
+ _(@row[0]).must_equal 'Cell A'
1069
+ end
1070
+ end
1071
+
1072
+ describe 'when document is parsed as StringIO' do
1073
+ before do
1074
+ stream = StringIO.new(File.binread(xlsx.archive.path), 'rb')
1075
+ @row = SimpleXlsxReader.parse(stream).sheets[0].rows.to_a[0]
1076
+ stream.close
1077
+ end
1078
+
1079
+ it 'reads cell content' do
1080
+ _(@row[0]).must_equal 'Cell A'
1081
+ end
1082
+ end
1083
+ end
1084
+
1034
1085
  # https://support.microsoft.com/en-us/office/available-number-formats-in-excel-0afe8f52-97db-41f1-b972-4b46e9f1e8d2
1035
1086
  describe 'numeric fields styled as "General"' do
1036
1087
  let(:misc_numbers_path) do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_xlsx_reader
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Woody Peterson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-06 00:00:00.000000000 Z
11
+ date: 2025-04-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -87,6 +87,7 @@ executables: []
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
+ - ".github/dependabot.yml"
90
91
  - ".github/workflows/ruby.yml"
91
92
  - ".gitignore"
92
93
  - ".travis.yml"
@@ -115,6 +116,7 @@ files:
115
116
  - test/lower_case_sharedstrings.xlsx
116
117
  - test/lower_case_sharedstrings_test.rb
117
118
  - test/misc_numbers.xlsx
119
+ - test/namespaces_and_missing_atts_test.rb
118
120
  - test/percentages_n_currencies.xlsx
119
121
  - test/performance_test.rb
120
122
  - test/sesame_street_blog.xlsx
@@ -142,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
144
  - !ruby/object:Gem::Version
143
145
  version: '0'
144
146
  requirements: []
145
- rubygems_version: 3.3.7
147
+ rubygems_version: 3.5.22
146
148
  signing_key:
147
149
  specification_version: 4
148
150
  summary: Read xlsx data the Ruby way
@@ -157,6 +159,7 @@ test_files:
157
159
  - test/lower_case_sharedstrings.xlsx
158
160
  - test/lower_case_sharedstrings_test.rb
159
161
  - test/misc_numbers.xlsx
162
+ - test/namespaces_and_missing_atts_test.rb
160
163
  - test/percentages_n_currencies.xlsx
161
164
  - test/performance_test.rb
162
165
  - test/sesame_street_blog.xlsx