roo 2.7.1 → 2.8.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 +5 -5
- data/.github/issue_template.md +16 -0
- data/.github/pull_request_template.md +14 -0
- data/.rubocop.yml +186 -0
- data/.travis.yml +12 -7
- data/CHANGELOG.md +31 -2
- data/LICENSE +2 -0
- data/README.md +25 -12
- data/lib/roo.rb +4 -1
- data/lib/roo/base.rb +65 -56
- data/lib/roo/constants.rb +5 -3
- data/lib/roo/csv.rb +20 -12
- data/lib/roo/excelx.rb +42 -16
- data/lib/roo/excelx/cell.rb +10 -6
- data/lib/roo/excelx/cell/base.rb +26 -12
- data/lib/roo/excelx/cell/boolean.rb +9 -6
- data/lib/roo/excelx/cell/date.rb +7 -7
- data/lib/roo/excelx/cell/datetime.rb +14 -18
- data/lib/roo/excelx/cell/empty.rb +3 -2
- data/lib/roo/excelx/cell/number.rb +35 -34
- data/lib/roo/excelx/cell/string.rb +3 -3
- data/lib/roo/excelx/cell/time.rb +4 -3
- data/lib/roo/excelx/comments.rb +3 -3
- data/lib/roo/excelx/coordinate.rb +11 -4
- data/lib/roo/excelx/extractor.rb +21 -3
- data/lib/roo/excelx/format.rb +38 -31
- data/lib/roo/excelx/images.rb +26 -0
- data/lib/roo/excelx/relationships.rb +3 -3
- data/lib/roo/excelx/shared.rb +10 -3
- data/lib/roo/excelx/shared_strings.rb +9 -15
- data/lib/roo/excelx/sheet.rb +49 -10
- data/lib/roo/excelx/sheet_doc.rb +86 -48
- data/lib/roo/excelx/styles.rb +3 -3
- data/lib/roo/excelx/workbook.rb +7 -3
- data/lib/roo/helpers/default_attr_reader.rb +20 -0
- data/lib/roo/helpers/weak_instance_cache.rb +41 -0
- data/lib/roo/open_office.rb +8 -6
- data/lib/roo/spreadsheet.rb +1 -1
- data/lib/roo/utils.rb +48 -19
- data/lib/roo/version.rb +1 -1
- data/roo.gemspec +13 -11
- data/spec/lib/roo/base_spec.rb +45 -3
- data/spec/lib/roo/excelx_spec.rb +125 -31
- data/spec/lib/roo/strict_spec.rb +43 -0
- data/spec/lib/roo/utils_spec.rb +12 -3
- data/spec/lib/roo/weak_instance_cache_spec.rb +92 -0
- data/spec/lib/roo_spec.rb +0 -0
- data/test/excelx/cell/test_attr_reader_default.rb +72 -0
- data/test/excelx/cell/test_base.rb +5 -0
- data/test/excelx/cell/test_datetime.rb +6 -6
- data/test/excelx/cell/test_empty.rb +11 -0
- data/test/excelx/cell/test_number.rb +9 -0
- data/test/excelx/cell/test_string.rb +20 -0
- data/test/excelx/cell/test_time.rb +4 -4
- data/test/excelx/test_coordinate.rb +51 -0
- data/test/formatters/test_csv.rb +17 -0
- data/test/formatters/test_xml.rb +4 -4
- data/test/roo/test_base.rb +2 -2
- data/test/roo/test_csv.rb +28 -0
- data/test/test_helper.rb +13 -0
- data/test/test_roo.rb +7 -7
- metadata +21 -11
- data/.github/ISSUE_TEMPLATE +0 -10
- data/Gemfile_ruby2 +0 -30
data/lib/roo/excelx/sheet.rb
CHANGED
@@ -4,11 +4,15 @@ module Roo
|
|
4
4
|
class Sheet
|
5
5
|
extend Forwardable
|
6
6
|
|
7
|
-
delegate [:styles, :workbook, :shared_strings, :rels_files, :sheet_files, :comments_files] => :@shared
|
7
|
+
delegate [:styles, :workbook, :shared_strings, :rels_files, :sheet_files, :comments_files, :image_rels] => :@shared
|
8
|
+
|
9
|
+
attr_reader :images
|
8
10
|
|
9
11
|
def initialize(name, shared, sheet_index, options = {})
|
10
12
|
@name = name
|
11
13
|
@shared = shared
|
14
|
+
@sheet_index = sheet_index
|
15
|
+
@images = Images.new(image_rels[sheet_index]).list
|
12
16
|
@rels = Relationships.new(rels_files[sheet_index])
|
13
17
|
@comments = Comments.new(comments_files[sheet_index])
|
14
18
|
@sheet = SheetDoc.new(sheet_files[sheet_index], @rels, shared, options)
|
@@ -19,7 +23,14 @@ module Roo
|
|
19
23
|
end
|
20
24
|
|
21
25
|
def present_cells
|
22
|
-
@present_cells ||=
|
26
|
+
@present_cells ||= begin
|
27
|
+
warn %{
|
28
|
+
[DEPRECATION] present_cells is deprecated. Alternate:
|
29
|
+
with activesupport => cells[key].presence
|
30
|
+
without activesupport => cells[key]&.presence
|
31
|
+
}
|
32
|
+
cells.select { |_, cell| cell&.presence }
|
33
|
+
end
|
23
34
|
end
|
24
35
|
|
25
36
|
# Yield each row as array of Excelx::Cell objects
|
@@ -39,33 +50,33 @@ module Roo
|
|
39
50
|
|
40
51
|
def row(row_number)
|
41
52
|
first_column.upto(last_column).map do |col|
|
42
|
-
cells[[row_number, col]]
|
43
|
-
end
|
53
|
+
cells[[row_number, col]]&.value
|
54
|
+
end
|
44
55
|
end
|
45
56
|
|
46
57
|
def column(col_number)
|
47
58
|
first_row.upto(last_row).map do |row|
|
48
|
-
cells[[row, col_number]]
|
49
|
-
end
|
59
|
+
cells[[row, col_number]]&.value
|
60
|
+
end
|
50
61
|
end
|
51
62
|
|
52
63
|
# returns the number of the first non-empty row
|
53
64
|
def first_row
|
54
|
-
@first_row ||=
|
65
|
+
@first_row ||= first_last_row_col[:first_row]
|
55
66
|
end
|
56
67
|
|
57
68
|
def last_row
|
58
|
-
@last_row ||=
|
69
|
+
@last_row ||= first_last_row_col[:last_row]
|
59
70
|
end
|
60
71
|
|
61
72
|
# returns the number of the first non-empty column
|
62
73
|
def first_column
|
63
|
-
@first_column ||=
|
74
|
+
@first_column ||= first_last_row_col[:first_column]
|
64
75
|
end
|
65
76
|
|
66
77
|
# returns the number of the last non-empty column
|
67
78
|
def last_column
|
68
|
-
@last_column ||=
|
79
|
+
@last_column ||= first_last_row_col[:last_column]
|
69
80
|
end
|
70
81
|
|
71
82
|
def excelx_format(key)
|
@@ -107,6 +118,34 @@ module Roo
|
|
107
118
|
(cell.coordinate.column - 1 - last_column).times { pad << nil }
|
108
119
|
pad
|
109
120
|
end
|
121
|
+
|
122
|
+
def first_last_row_col
|
123
|
+
@first_last_row_col ||= begin
|
124
|
+
first_row = last_row = first_col = last_col = nil
|
125
|
+
|
126
|
+
cells.each do |(row, col), cell|
|
127
|
+
next unless cell&.presence
|
128
|
+
first_row ||= row
|
129
|
+
last_row ||= row
|
130
|
+
first_col ||= col
|
131
|
+
last_col ||= col
|
132
|
+
|
133
|
+
if row > last_row
|
134
|
+
last_row = row
|
135
|
+
elsif row < first_row
|
136
|
+
first_row = row
|
137
|
+
end
|
138
|
+
|
139
|
+
if col > last_col
|
140
|
+
last_col = col
|
141
|
+
elsif col < first_col
|
142
|
+
first_col = col
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
{first_row: first_row, last_row: last_row, first_column: first_col, last_column: last_col}
|
147
|
+
end
|
148
|
+
end
|
110
149
|
end
|
111
150
|
end
|
112
151
|
end
|
data/lib/roo/excelx/sheet_doc.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'forwardable'
|
2
4
|
require 'roo/excelx/extractor'
|
3
5
|
|
@@ -5,7 +7,7 @@ module Roo
|
|
5
7
|
class Excelx
|
6
8
|
class SheetDoc < Excelx::Extractor
|
7
9
|
extend Forwardable
|
8
|
-
delegate [:
|
10
|
+
delegate [:workbook] => :@shared
|
9
11
|
|
10
12
|
def initialize(path, relationships, shared, options = {})
|
11
13
|
super(path)
|
@@ -19,7 +21,12 @@ module Roo
|
|
19
21
|
end
|
20
22
|
|
21
23
|
def hyperlinks(relationships)
|
22
|
-
|
24
|
+
# If you're sure you're not going to need this hyperlinks you can discard it
|
25
|
+
@hyperlinks ||= if @options[:no_hyperlinks]
|
26
|
+
{}
|
27
|
+
else
|
28
|
+
extract_hyperlinks(relationships)
|
29
|
+
end
|
23
30
|
end
|
24
31
|
|
25
32
|
# Get the dimensions for the sheet.
|
@@ -39,13 +46,10 @@ module Roo
|
|
39
46
|
def each_cell(row_xml)
|
40
47
|
return [] unless row_xml
|
41
48
|
row_xml.children.each do |cell_element|
|
42
|
-
|
43
|
-
hyperlinks =
|
44
|
-
key = ::Roo::Utils.ref_to_key(cell_element['r'])
|
45
|
-
hyperlinks(@relationships)[key]
|
46
|
-
end
|
49
|
+
coordinate = ::Roo::Utils.extract_coordinate(cell_element["r"])
|
50
|
+
hyperlinks = hyperlinks(@relationships)[coordinate]
|
47
51
|
|
48
|
-
yield cell_from_xml(cell_element, hyperlinks)
|
52
|
+
yield cell_from_xml(cell_element, hyperlinks, coordinate)
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
@@ -53,13 +57,13 @@ module Roo
|
|
53
57
|
|
54
58
|
def cell_value_type(type, format)
|
55
59
|
case type
|
56
|
-
when 's'
|
60
|
+
when 's'
|
57
61
|
:shared
|
58
|
-
when 'b'
|
62
|
+
when 'b'
|
59
63
|
:boolean
|
60
|
-
when 'str'
|
64
|
+
when 'str'
|
61
65
|
:string
|
62
|
-
when 'inlineStr'
|
66
|
+
when 'inlineStr'
|
63
67
|
:inlinestr
|
64
68
|
else
|
65
69
|
Excelx::Format.to_type(format)
|
@@ -74,42 +78,58 @@ module Roo
|
|
74
78
|
# </c>
|
75
79
|
# hyperlink - a String for the hyperlink for the cell or nil when no
|
76
80
|
# hyperlink is present.
|
81
|
+
# coordinate - a Roo::Excelx::Coordinate for the coordinate for the cell
|
82
|
+
# or nil to extract coordinate from cell_xml.
|
83
|
+
# empty_cell - an Optional Boolean value.
|
77
84
|
#
|
78
85
|
# Examples
|
79
86
|
#
|
80
|
-
# cells_from_xml(<Nokogiri::XML::Element>, nil)
|
87
|
+
# cells_from_xml(<Nokogiri::XML::Element>, nil, nil)
|
81
88
|
# # => <Excelx::Cell::String>
|
82
89
|
#
|
83
90
|
# Returns a type of <Excelx::Cell>.
|
84
|
-
def cell_from_xml(cell_xml, hyperlink)
|
85
|
-
coordinate
|
86
|
-
|
91
|
+
def cell_from_xml(cell_xml, hyperlink, coordinate, empty_cell=true)
|
92
|
+
coordinate ||= ::Roo::Utils.extract_coordinate(cell_xml["r"])
|
93
|
+
cell_xml_children = cell_xml.children
|
94
|
+
return create_empty_cell(coordinate, empty_cell) if cell_xml_children.empty?
|
87
95
|
|
88
96
|
# NOTE: This is error prone, to_i will silently turn a nil into a 0.
|
89
97
|
# This works by coincidence because Format[0] is General.
|
90
|
-
style = cell_xml[
|
91
|
-
format = styles.style_format(style)
|
92
|
-
value_type = cell_value_type(cell_xml['t'], format)
|
98
|
+
style = cell_xml["s"].to_i
|
93
99
|
formula = nil
|
94
100
|
|
95
|
-
|
101
|
+
cell_xml_children.each do |cell|
|
96
102
|
case cell.name
|
97
103
|
when 'is'
|
98
|
-
|
99
|
-
|
100
|
-
|
104
|
+
content = +""
|
105
|
+
cell.children.each do |inline_str|
|
106
|
+
if inline_str.name == 't'
|
107
|
+
content << inline_str.content
|
108
|
+
end
|
109
|
+
end
|
110
|
+
unless content.empty?
|
111
|
+
return Excelx::Cell.cell_class(:string).new(content, formula, style, hyperlink, coordinate)
|
101
112
|
end
|
102
113
|
when 'f'
|
103
114
|
formula = cell.content
|
104
115
|
when 'v'
|
105
|
-
|
116
|
+
format = style_format(style)
|
117
|
+
value_type = cell_value_type(cell_xml["t"], format)
|
118
|
+
|
119
|
+
return create_cell_from_value(value_type, cell, formula, format, style, hyperlink, coordinate)
|
106
120
|
end
|
107
121
|
end
|
108
122
|
|
109
|
-
|
123
|
+
create_empty_cell(coordinate)
|
110
124
|
end
|
111
125
|
|
112
|
-
def
|
126
|
+
def create_empty_cell(coordinate, empty_cell)
|
127
|
+
if empty_cell
|
128
|
+
Excelx::Cell::Empty.new(coordinate)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def create_cell_from_value(value_type, cell, formula, format, style, hyperlink, coordinate)
|
113
133
|
# NOTE: format.to_s can replace excelx_type as an argument for
|
114
134
|
# Cell::Time, Cell::DateTime, Cell::Date or Cell::Number, but
|
115
135
|
# it will break some brittle tests.
|
@@ -125,11 +145,12 @@ module Roo
|
|
125
145
|
# 3. formula
|
126
146
|
case value_type
|
127
147
|
when :shared
|
128
|
-
|
129
|
-
|
148
|
+
cell_content = cell.content.to_i
|
149
|
+
value = shared_strings.use_html?(cell_content) ? shared_strings.to_html[cell_content] : shared_strings[cell_content]
|
150
|
+
Excelx::Cell.cell_class(:string).new(value, formula, style, hyperlink, coordinate)
|
130
151
|
when :boolean, :string
|
131
152
|
value = cell.content
|
132
|
-
Excelx::Cell.
|
153
|
+
Excelx::Cell.cell_class(value_type).new(value, formula, style, hyperlink, coordinate)
|
133
154
|
when :time, :datetime
|
134
155
|
cell_content = cell.content.to_f
|
135
156
|
# NOTE: A date will be a whole number. A time will have be > 1. And
|
@@ -148,35 +169,32 @@ module Roo
|
|
148
169
|
else
|
149
170
|
:date
|
150
171
|
end
|
151
|
-
|
172
|
+
base_value = cell_type == :date ? base_date : base_timestamp
|
173
|
+
Excelx::Cell.cell_class(cell_type).new(cell_content, formula, excelx_type, style, hyperlink, base_value, coordinate)
|
152
174
|
when :date
|
153
|
-
Excelx::Cell.
|
175
|
+
Excelx::Cell.cell_class(:date).new(cell.content, formula, excelx_type, style, hyperlink, base_date, coordinate)
|
154
176
|
else
|
155
|
-
Excelx::Cell.
|
177
|
+
Excelx::Cell.cell_class(:number).new(cell.content, formula, excelx_type, style, hyperlink, coordinate)
|
156
178
|
end
|
157
179
|
end
|
158
180
|
|
159
|
-
def extract_coordinate(coordinate)
|
160
|
-
row, column = ::Roo::Utils.split_coordinate(coordinate)
|
161
|
-
|
162
|
-
Excelx::Coordinate.new(row, column)
|
163
|
-
end
|
164
|
-
|
165
181
|
def extract_hyperlinks(relationships)
|
166
182
|
return {} unless (hyperlinks = doc.xpath('/worksheet/hyperlinks/hyperlink'))
|
167
183
|
|
168
|
-
|
169
|
-
if
|
170
|
-
|
184
|
+
hyperlinks.each_with_object({}) do |hyperlink, hash|
|
185
|
+
if relationship = relationships[hyperlink['id']]
|
186
|
+
target_link = relationship['Target']
|
187
|
+
target_link += "##{hyperlink['location']}" if hyperlink['location']
|
188
|
+
hash[::Roo::Utils.ref_to_key(hyperlink["ref"].to_s)] = target_link
|
171
189
|
end
|
172
|
-
end
|
190
|
+
end
|
173
191
|
end
|
174
192
|
|
175
193
|
def expand_merged_ranges(cells)
|
176
194
|
# Extract merged ranges from xml
|
177
195
|
merges = {}
|
178
196
|
doc.xpath('/worksheet/mergeCells/mergeCell').each do |mergecell_xml|
|
179
|
-
tl, br = mergecell_xml[
|
197
|
+
tl, br = mergecell_xml["ref"].split(/:/).map { |ref| ::Roo::Utils.ref_to_key(ref) }
|
180
198
|
for row in tl[0]..br[0] do
|
181
199
|
for col in tl[1]..br[1] do
|
182
200
|
next if row == tl[0] && col == tl[1]
|
@@ -191,10 +209,14 @@ module Roo
|
|
191
209
|
end
|
192
210
|
|
193
211
|
def extract_cells(relationships)
|
194
|
-
extracted_cells =
|
195
|
-
|
196
|
-
|
197
|
-
|
212
|
+
extracted_cells = {}
|
213
|
+
empty_cell = @options[:empty_cell]
|
214
|
+
|
215
|
+
doc.xpath('/worksheet/sheetData/row/c').each do |cell_xml|
|
216
|
+
coordinate = ::Roo::Utils.extract_coordinate(cell_xml["r"])
|
217
|
+
cell = cell_from_xml(cell_xml, hyperlinks(relationships)[coordinate], coordinate, empty_cell)
|
218
|
+
extracted_cells[coordinate] = cell if cell
|
219
|
+
end
|
198
220
|
|
199
221
|
expand_merged_ranges(extracted_cells) if @options[:expand_merged_ranges]
|
200
222
|
|
@@ -203,9 +225,25 @@ module Roo
|
|
203
225
|
|
204
226
|
def extract_dimensions
|
205
227
|
Roo::Utils.each_element(@path, 'dimension') do |dimension|
|
206
|
-
return dimension
|
228
|
+
return dimension["ref"]
|
207
229
|
end
|
208
230
|
end
|
231
|
+
|
232
|
+
def style_format(style)
|
233
|
+
@shared.styles.style_format(style)
|
234
|
+
end
|
235
|
+
|
236
|
+
def base_date
|
237
|
+
@shared.base_date
|
238
|
+
end
|
239
|
+
|
240
|
+
def base_timestamp
|
241
|
+
@shared.base_timestamp
|
242
|
+
end
|
243
|
+
|
244
|
+
def shared_strings
|
245
|
+
@shared.shared_strings
|
246
|
+
end
|
209
247
|
end
|
210
248
|
end
|
211
249
|
end
|
data/lib/roo/excelx/styles.rb
CHANGED
@@ -55,9 +55,9 @@ module Roo
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def extract_num_fmts
|
58
|
-
|
59
|
-
[num_fmt['numFmtId']
|
60
|
-
end
|
58
|
+
doc.xpath('//numFmt').each_with_object({}) do |num_fmt, hash|
|
59
|
+
hash[num_fmt['numFmtId']] = num_fmt['formatCode']
|
60
|
+
end
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
data/lib/roo/excelx/workbook.rb
CHANGED
@@ -29,13 +29,17 @@ module Roo
|
|
29
29
|
|
30
30
|
# aka labels
|
31
31
|
def defined_names
|
32
|
-
|
32
|
+
doc.xpath('//definedName').each_with_object({}) do |defined_name, hash|
|
33
33
|
# "Sheet1!$C$5"
|
34
34
|
sheet, coordinates = defined_name.text.split('!$', 2)
|
35
35
|
col, row = coordinates.split('$')
|
36
36
|
name = defined_name['name']
|
37
|
-
[name
|
38
|
-
end
|
37
|
+
hash[name] = Label.new(name, sheet, row, col)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def base_timestamp
|
42
|
+
@base_timestamp ||= base_date.to_datetime.to_time.to_i
|
39
43
|
end
|
40
44
|
|
41
45
|
def base_date
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Roo
|
4
|
+
module Helpers
|
5
|
+
module DefaultAttrReader
|
6
|
+
def attr_reader_with_default(attr_hash)
|
7
|
+
attr_hash.each do |attr_name, default_value|
|
8
|
+
instance_variable = :"@#{attr_name}"
|
9
|
+
define_method attr_name do
|
10
|
+
if instance_variable_defined? instance_variable
|
11
|
+
instance_variable_get instance_variable
|
12
|
+
else
|
13
|
+
default_value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "weakref"
|
4
|
+
|
5
|
+
module Roo
|
6
|
+
module Helpers
|
7
|
+
module WeakInstanceCache
|
8
|
+
private
|
9
|
+
|
10
|
+
def instance_cache(key)
|
11
|
+
object = nil
|
12
|
+
|
13
|
+
if instance_variable_defined?(key) && (ref = instance_variable_get(key)) && ref.weakref_alive?
|
14
|
+
begin
|
15
|
+
object = ref.__getobj__
|
16
|
+
rescue => e
|
17
|
+
unless (defined?(::WeakRef::RefError) && e.is_a?(::WeakRef::RefError)) || (defined?(RefError) && e.is_a?(RefError))
|
18
|
+
raise e
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
unless object
|
24
|
+
object = yield
|
25
|
+
ObjectSpace.define_finalizer(object, instance_cache_finalizer(key))
|
26
|
+
instance_variable_set(key, WeakRef.new(object))
|
27
|
+
end
|
28
|
+
|
29
|
+
object
|
30
|
+
end
|
31
|
+
|
32
|
+
def instance_cache_finalizer(key)
|
33
|
+
proc do |object_id|
|
34
|
+
if instance_variable_defined?(key) && (ref = instance_variable_get(key)) && (!ref.weakref_alive? || ref.__getobj__.object_id == object_id)
|
35
|
+
remove_instance_variable(key)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/roo/open_office.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'date'
|
2
4
|
require 'nokogiri'
|
3
5
|
require 'cgi'
|
@@ -11,9 +13,9 @@ module Roo
|
|
11
13
|
class OpenOffice < Roo::Base
|
12
14
|
extend Roo::Tempdir
|
13
15
|
|
14
|
-
ERROR_MISSING_CONTENT_XML = 'file missing required content.xml'
|
15
|
-
XPATH_FIND_TABLE_STYLES = "//*[local-name()='automatic-styles']"
|
16
|
-
XPATH_LOCAL_NAME_TABLE = "//*[local-name()='table']"
|
16
|
+
ERROR_MISSING_CONTENT_XML = 'file missing required content.xml'
|
17
|
+
XPATH_FIND_TABLE_STYLES = "//*[local-name()='automatic-styles']"
|
18
|
+
XPATH_LOCAL_NAME_TABLE = "//*[local-name()='table']"
|
17
19
|
|
18
20
|
# initialization and opening of a spreadsheet file
|
19
21
|
# values for packed: :zip
|
@@ -561,7 +563,7 @@ module Roo
|
|
561
563
|
end
|
562
564
|
|
563
565
|
def read_labels
|
564
|
-
@label ||=
|
566
|
+
@label ||= doc.xpath('//table:named-range').each_with_object({}) do |ne, hash|
|
565
567
|
#-
|
566
568
|
# $Sheet1.$C$5
|
567
569
|
#+
|
@@ -569,8 +571,8 @@ module Roo
|
|
569
571
|
sheetname, coords = attribute(ne, 'cell-range-address').to_s.split('.$')
|
570
572
|
col, row = coords.split('$')
|
571
573
|
sheetname = sheetname[1..-1] if sheetname[0, 1] == '$'
|
572
|
-
[name
|
573
|
-
end
|
574
|
+
hash[name] = [sheetname, row, col]
|
575
|
+
end
|
574
576
|
end
|
575
577
|
|
576
578
|
def read_styles(style_elements)
|