xsv 0.2.1 → 0.2.2
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/Gemfile.lock +1 -1
- data/lib/xsv/helpers.rb +4 -4
- data/lib/xsv/sheet.rb +42 -22
- data/lib/xsv/version.rb +1 -1
- data/lib/xsv/workbook.rb +5 -5
- data/lib/xsv.rb +3 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2b097ec44b4cee4a7f6331a3a94f15e24f33c88258d375923f965dafe88ee13e
|
|
4
|
+
data.tar.gz: c2da68b26d04cb6bd28496d810f7721e327a655c1c96b695d9b091e569767d21
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b0a7b30c258e16d391990881f4574577eeee6ec3424524cdc360901ffa62033102c518b005d3b181d0b6e7887f52afa7dfc9415cb2cd762f3f0779d9801aaf5a
|
|
7
|
+
data.tar.gz: 32ab543df470d94eb4a81e2b271a18ba9295c0d7d9fd63cf918a18baa02b6c01e6bcfb35e6d6e42021d36f773affce5ace52fb07dd7d2ea4110b4a0cbe22fc9c
|
data/Gemfile.lock
CHANGED
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
|
|
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
|
-
|
|
17
|
+
@has_cells = !xml.at_css("sheetData c").nil?
|
|
18
18
|
|
|
19
|
-
if
|
|
20
|
-
|
|
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
|
-
|
|
28
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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
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.
|
|
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::
|
|
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
|
|
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