xsv 0.2.1 → 0.2.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: ace53a58655a50f4de2f10c4a2d68819774e3e74625595353290502299630b30
4
- data.tar.gz: 8278ea7b26ac261781ae71328762104db9d14de0cbc05be1b0551a3cb876ea35
3
+ metadata.gz: 2b097ec44b4cee4a7f6331a3a94f15e24f33c88258d375923f965dafe88ee13e
4
+ data.tar.gz: c2da68b26d04cb6bd28496d810f7721e327a655c1c96b695d9b091e569767d21
5
5
  SHA512:
6
- metadata.gz: 31ccd6261073893e0a0873997d7befa39fc0f8088f5f4d9d1ec3f97b7d90f48d1153714cff4f124a4be853976ce714326a6ec8634e646f15ecf6cf428c245a39
7
- data.tar.gz: eed43d77052870dc45bc009719b130096a05a6add11576a349ca027ff93b428bfe64813dd83a8ea58a1a7da94aa8b490b4394efa65bbb175ae09dd74c77ee20a
6
+ metadata.gz: b0a7b30c258e16d391990881f4574577eeee6ec3424524cdc360901ffa62033102c518b005d3b181d0b6e7887f52afa7dfc9415cb2cd762f3f0779d9801aaf5a
7
+ data.tar.gz: 32ab543df470d94eb4a81e2b271a18ba9295c0d7d9fd63cf918a18baa02b6c01e6bcfb35e6d6e42021d36f773affce5ace52fb07dd7d2ea4110b4a0cbe22fc9c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- xsv (0.2.0)
4
+ xsv (0.2.1)
5
5
  nokogiri (~> 1.10)
6
6
  rubyzip (~> 2.2)
7
7
 
data/lib/xsv/helpers.rb CHANGED
@@ -32,14 +32,14 @@ module Xsv
32
32
  47 => "mm:ss.0",
33
33
  48 => "##0.0E+0",
34
34
  49 => "@",
35
- }
35
+ }.freeze
36
36
 
37
- MINUTE = 60
38
- HOUR = 3600
37
+ MINUTE = 60.freeze
38
+ HOUR = 3600.freeze
39
39
 
40
40
  # Return the index number for the given Excel column name
41
41
  def column_index(col)
42
- col = col.scan(/^[A-Z]+/).first
42
+ col = col[/^[A-Z]+/]
43
43
 
44
44
  val = 0
45
45
  while col.length > 0
data/lib/xsv/sheet.rb CHANGED
@@ -14,24 +14,14 @@ module Xsv
14
14
  @mode = :array
15
15
  @row_skip = 0
16
16
 
17
- dimension = xml.css("dimension").first
17
+ @has_cells = !xml.at_css("sheetData c").nil?
18
18
 
19
- if dimension
20
- _firstCell, lastCell = dimension["ref"].split(":")
21
- end
22
-
23
- if lastCell
24
- # Assume the dimension reflects the content
25
- @column_count = column_index(lastCell) + 1
19
+ if @has_cells
20
+ @column_count, @last_row = get_sheet_dimensions
26
21
  else
27
- # Find the last cell in every row that has a value
28
- rightmost_cells = @xml.xpath("//xmlns:row/xmlns:c[*[local-name() = 'v']][last()]").map { |c| column_index(c["r"]) }
29
- @column_count = rightmost_cells.max + 1
30
-
22
+ @column_count = 0
23
+ @last_row = 0
31
24
  end
32
-
33
- # Find the last row that contains actual values
34
- @last_row = @xml.xpath("//xmlns:row[*[xmlns:v]][last()]").first["r"].to_i
35
25
  end
36
26
 
37
27
  def inspect
@@ -69,7 +59,7 @@ module Xsv
69
59
 
70
60
  # Get row by number, starting at 0
71
61
  def [](number)
72
- row_xml = xml.css("sheetData row[r=#{number + @row_skip + 1}]").first
62
+ row_xml = xml.at_css("sheetData row[r=#{number + @row_skip + 1}]")
73
63
 
74
64
  if row_xml
75
65
  parse_row(row_xml)
@@ -81,18 +71,24 @@ module Xsv
81
71
  # Load headers in the top row of the worksheet. After parsing of headers
82
72
  # all methods return hashes instead of arrays
83
73
  def parse_headers!
84
- @mode = :array
85
74
  @headers = parse_headers
86
-
87
75
  @mode = :hash
88
76
 
89
77
  true
90
78
  end
91
79
 
80
+ def headers
81
+ if @headers.any?
82
+ @headers
83
+ else
84
+ parse_headers
85
+ end
86
+ end
87
+
92
88
  private
93
89
 
94
90
  def parse_headers
95
- parse_row(@xml.css("sheetData row")[@row_skip])
91
+ parse_row(@xml.css("sheetData row")[@row_skip], :array)
96
92
  end
97
93
 
98
94
  def empty_row
@@ -104,7 +100,8 @@ module Xsv
104
100
  end
105
101
  end
106
102
 
107
- def parse_row(xml)
103
+ def parse_row(xml, mode = nil)
104
+ mode ||= @mode
108
105
  row = empty_row
109
106
 
110
107
  xml.css("c").first(@column_count).each do |c_xml|
@@ -116,7 +113,7 @@ module Xsv
116
113
  when "e" # N/A
117
114
  nil
118
115
  when nil
119
- v = c_xml.css("v").first
116
+ v = c_xml.at_css("v")
120
117
 
121
118
  if v.nil?
122
119
  nil
@@ -147,7 +144,7 @@ module Xsv
147
144
  # Determine column position and pad row with nil values
148
145
  col_index = column_index(c_xml["r"])
149
146
 
150
- case @mode
147
+ case mode
151
148
  when :array
152
149
  row[col_index] = value
153
150
  when :hash
@@ -157,5 +154,28 @@ module Xsv
157
154
 
158
155
  row
159
156
  end
157
+
158
+ # Read or estimate outer bounds of sheet
159
+ def get_sheet_dimensions
160
+ dimension = xml.at_css("dimension")
161
+
162
+ if dimension
163
+ _firstCell, lastCell = dimension["ref"].split(":")
164
+ end
165
+
166
+ if lastCell
167
+ # Assume the dimension reflects the content
168
+ column_count = column_index(lastCell) + 1
169
+ else
170
+ # Find the last cell in every row that has a value
171
+ rightmost_cells = @xml.xpath("//xmlns:row/xmlns:c[*[local-name() = 'v']][last()]").map { |c| column_index(c["r"]) }
172
+ column_count = rightmost_cells.max + 1
173
+ end
174
+
175
+ # Find the last row that contains actual values
176
+ last_row = @xml.at_xpath("//xmlns:row[*[xmlns:v]][last()]")["r"].to_i
177
+
178
+ return [column_count, last_row]
179
+ end
160
180
  end
161
181
  end
data/lib/xsv/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Xsv
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
data/lib/xsv/workbook.rb CHANGED
@@ -17,7 +17,7 @@ module Xsv
17
17
 
18
18
  @sheets = []
19
19
  @xfs = []
20
- @numFmts = Xsv::Helpers::BUILT_IN_NUMBER_FORMATS
20
+ @numFmts = Xsv::Helpers::BUILT_IN_NUMBER_FORMATS.dup
21
21
 
22
22
  fetch_shared_strings
23
23
  fetch_styles
@@ -33,11 +33,11 @@ module Xsv
33
33
  def fetch_shared_strings
34
34
  stream = @zip.glob("xl/sharedStrings.xml").first.get_input_stream
35
35
  xml = Nokogiri::XML(stream)
36
- expected_count = xml.css("sst").first["uniqueCount"].to_i
37
- @shared_strings = xml.css("sst si t").map(&:inner_text)
36
+ expected_count = xml.at_css("sst")["uniqueCount"].to_i
37
+ @shared_strings = xml.css("sst si").map { |si| si.css("t").map(&:inner_text).join }
38
38
 
39
39
  if @shared_strings.count != expected_count
40
- raise Xsv::Error, "Mismatch in shared strings count! #{expected_count} <> #{@shared_strings.count}"
40
+ raise Xsv::AssertionFailed, "Mismatch in shared strings count! #{expected_count} <> #{@shared_strings.count}"
41
41
  end
42
42
 
43
43
  stream.close
@@ -58,7 +58,7 @@ module Xsv
58
58
 
59
59
  def fetch_sheets
60
60
  @zip.glob("xl/worksheets/sheet*.xml").sort do |a, b|
61
- a.name.scan(/\d+/).first.to_i <=> b.name.scan(/\d+/).first.to_i
61
+ a.name[/\d+/].to_i <=> b.name[/\d+/].to_i
62
62
  end.each do |entry|
63
63
  @sheets << Xsv::Sheet.new(self, Nokogiri::XML(entry.get_input_stream))
64
64
  end
data/lib/xsv.rb CHANGED
@@ -7,4 +7,7 @@ require "xsv/workbook"
7
7
 
8
8
  module Xsv
9
9
  class Error < StandardError; end
10
+ # An AssertionFailed error indicates an unexpected condition, meaning a bug
11
+ # or misinterpreted .xlsx document
12
+ class AssertionFailed < StandardError; end
10
13
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xsv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martijn Storck