ooxl 0.0.1.4.26 → 0.0.1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -0
- data/.rspec +0 -0
- data/.travis.yml +0 -0
- data/Gemfile +0 -0
- data/README.md +0 -0
- data/Rakefile +0 -0
- data/bin/console +0 -0
- data/bin/setup +0 -0
- data/lib/ooxl/list_helper.rb +0 -0
- data/lib/ooxl/ooxl.rb +0 -0
- data/lib/ooxl/util.rb +0 -0
- data/lib/ooxl/version.rb +1 -1
- data/lib/ooxl/xl_objects/cell.rb +0 -0
- data/lib/ooxl/xl_objects/cell_style_reference.rb +0 -0
- data/lib/ooxl/xl_objects/column.rb +0 -0
- data/lib/ooxl/xl_objects/comments.rb +0 -0
- data/lib/ooxl/xl_objects/fill.rb +0 -0
- data/lib/ooxl/xl_objects/font.rb +0 -0
- data/lib/ooxl/xl_objects/number_formatting.rb +0 -0
- data/lib/ooxl/xl_objects/relationships.rb +0 -0
- data/lib/ooxl/xl_objects/row.rb +12 -8
- data/lib/ooxl/xl_objects/row_cache.rb +100 -0
- data/lib/ooxl/xl_objects/sheet/data_validation.rb +0 -0
- data/lib/ooxl/xl_objects/sheet.rb +57 -88
- data/lib/ooxl/xl_objects/styles.rb +0 -0
- data/lib/ooxl/xl_objects/table.rb +0 -0
- data/lib/ooxl/xl_objects/workbook.rb +0 -0
- data/lib/ooxl.rb +0 -0
- data/ooxml_excel.gemspec +2 -1
- metadata +22 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3da0847d61333cf06c4a9e3212604a6b6f1e1e0
|
4
|
+
data.tar.gz: 2b5d30b7c28f88c14adfe0fcbe4e1c0085ccfb61
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb1e938d50dbfa698605986ae790670f0b2c557438aeb73925baf261326fe8f79b05948d409d06a5fbf620aaa88adba26642206b3beed11ca05e05372487a0ac
|
7
|
+
data.tar.gz: e30534d829e6b0ba29388a950cf5743977ee0b73c942c798df26eca177f9e17a70d365515c76bf37d20d6bb42c027ddad937223a75b582143a1cf1cac7c00d82
|
data/.gitignore
CHANGED
File without changes
|
data/.rspec
CHANGED
File without changes
|
data/.travis.yml
CHANGED
File without changes
|
data/Gemfile
CHANGED
File without changes
|
data/README.md
CHANGED
File without changes
|
data/Rakefile
CHANGED
File without changes
|
data/bin/console
CHANGED
File without changes
|
data/bin/setup
CHANGED
File without changes
|
data/lib/ooxl/list_helper.rb
CHANGED
File without changes
|
data/lib/ooxl/ooxl.rb
CHANGED
File without changes
|
data/lib/ooxl/util.rb
CHANGED
File without changes
|
data/lib/ooxl/version.rb
CHANGED
data/lib/ooxl/xl_objects/cell.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/ooxl/xl_objects/fill.rb
CHANGED
File without changes
|
data/lib/ooxl/xl_objects/font.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
data/lib/ooxl/xl_objects/row.rb
CHANGED
@@ -10,20 +10,18 @@ class OOXL
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def [](id)
|
13
|
-
|
14
|
-
|
13
|
+
if id.is_a?(String)
|
14
|
+
cell(id)
|
15
15
|
else
|
16
|
-
cells[id]
|
16
|
+
cells[id] || BlankCell.new(id)
|
17
17
|
end
|
18
|
-
(cell.present?) ? cell : BlankCell.new(id)
|
19
18
|
end
|
20
19
|
|
21
20
|
def cells
|
22
21
|
if @options[:padded_cells]
|
23
22
|
unless @cells.blank?
|
24
23
|
'A'.upto(@cells.last.column).map do |column_letter|
|
25
|
-
cell
|
26
|
-
(cell.blank?) ? BlankCell.new("#{column_letter}#{id}") : cell
|
24
|
+
cell(column_letter)
|
27
25
|
end
|
28
26
|
end
|
29
27
|
else
|
@@ -32,8 +30,14 @@ class OOXL
|
|
32
30
|
end
|
33
31
|
|
34
32
|
def cell(cell_id)
|
35
|
-
cell_final_id = cell_id[/[A-Z]
|
36
|
-
|
33
|
+
cell_final_id = cell_id[/[A-Z]+\d+/] ? cell_id : "#{cell_id}#{id}"
|
34
|
+
cell_id_map[cell_final_id]
|
35
|
+
end
|
36
|
+
|
37
|
+
def cell_id_map
|
38
|
+
@cell_id_map ||= cells.each_with_object(Hash.new { |_, k| BlankCell.new(k) }) do |cell, result|
|
39
|
+
result[cell.id] = cell
|
40
|
+
end
|
37
41
|
end
|
38
42
|
|
39
43
|
def each
|
@@ -0,0 +1,100 @@
|
|
1
|
+
class OOXL
|
2
|
+
class RowCache
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_accessor :styles
|
6
|
+
|
7
|
+
# built on-demand -- use rows instead
|
8
|
+
attr_reader :row_cache
|
9
|
+
|
10
|
+
# built on-demand -- use fetch_row_by_id instead
|
11
|
+
attr_reader :row_id_map
|
12
|
+
|
13
|
+
def initialize(sheet_xml, shared_strings, options = {})
|
14
|
+
@shared_strings = shared_strings
|
15
|
+
@sheet_xml = sheet_xml
|
16
|
+
@options = options
|
17
|
+
@row_cache = []
|
18
|
+
@row_id_map = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def [](id)
|
22
|
+
fetch_row_by_id(id)
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :row, :[]
|
26
|
+
|
27
|
+
def each(&block)
|
28
|
+
if @options[:padded_rows]
|
29
|
+
padded_rows(&block)
|
30
|
+
else
|
31
|
+
rows(&block)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def rows(&block)
|
36
|
+
# track yield count to know if caller broke out of loop
|
37
|
+
rows_yielded = 0
|
38
|
+
row_cache.each do |r|
|
39
|
+
yield r if block_given?
|
40
|
+
rows_yielded += 1
|
41
|
+
end
|
42
|
+
|
43
|
+
if !all_rows_loaded? && rows_yielded == row_cache.count
|
44
|
+
parse_more_rows(&block)
|
45
|
+
end
|
46
|
+
|
47
|
+
row_cache
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def parse_more_rows
|
53
|
+
row_nodes.drop(row_cache.count).each do |row_node|
|
54
|
+
row = Row.load_from_node(row_node, @shared_strings, @styles, @options)
|
55
|
+
row_cache << row
|
56
|
+
row_id_map[row.id] = row
|
57
|
+
yield row if block_given?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def all_rows_loaded?
|
62
|
+
row_cache.count == row_nodes.count
|
63
|
+
end
|
64
|
+
|
65
|
+
def row_nodes
|
66
|
+
@row_nodes ||= @sheet_xml.xpath('//sheetData/row')
|
67
|
+
end
|
68
|
+
|
69
|
+
def fetch_row_by_id(row_id)
|
70
|
+
row_id = row_id.to_s
|
71
|
+
return row_id_map[row_id] if all_rows_loaded? || row_id_map.key?(row_id)
|
72
|
+
|
73
|
+
parse_more_rows do |row|
|
74
|
+
return row if row.id == row_id
|
75
|
+
end
|
76
|
+
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
|
80
|
+
def padded_rows
|
81
|
+
real_rows_yielded = 0
|
82
|
+
yielded_rows = []
|
83
|
+
(1..Float::INFINITY).each do |row_index|
|
84
|
+
row = row(row_index)
|
85
|
+
if row.blank?
|
86
|
+
row = Row.new(id: row_index.to_s, cells: [])
|
87
|
+
else
|
88
|
+
real_rows_yielded += 1
|
89
|
+
end
|
90
|
+
|
91
|
+
yielded_rows << row
|
92
|
+
yield row if block_given?
|
93
|
+
|
94
|
+
break if real_rows_yielded == row_cache.count && all_rows_loaded?
|
95
|
+
end
|
96
|
+
yielded_rows
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
File without changes
|
@@ -1,10 +1,14 @@
|
|
1
1
|
require_relative 'sheet/data_validation'
|
2
|
+
require_relative 'row_cache'
|
3
|
+
|
2
4
|
class OOXL
|
3
5
|
class Sheet
|
4
6
|
include OOXL::Util
|
5
7
|
include Enumerable
|
6
|
-
|
7
|
-
|
8
|
+
|
9
|
+
attr_reader :columns, :data_validations, :shared_strings, :styles
|
10
|
+
attr_accessor :comments, :defined_names, :name
|
11
|
+
delegate :[], :each, :rows, :row, to: :@row_cache
|
8
12
|
|
9
13
|
def initialize(xml, shared_strings, options={})
|
10
14
|
@xml = Nokogiri.XML(xml).remove_namespaces!
|
@@ -12,8 +16,8 @@ class OOXL
|
|
12
16
|
@comments = {}
|
13
17
|
@defined_names = {}
|
14
18
|
@styles = []
|
15
|
-
@loaded_cache = {}
|
16
19
|
@options = options
|
20
|
+
@row_cache = RowCache.new(@xml, @shared_strings, options)
|
17
21
|
end
|
18
22
|
|
19
23
|
def code_name
|
@@ -41,82 +45,35 @@ class OOXL
|
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
44
|
-
def [](id)
|
45
|
-
if id.is_a?(String)
|
46
|
-
rows.find { |row| row.id == id}
|
47
|
-
else
|
48
|
-
rows[id]
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def row(index, stream: false)
|
53
|
-
if @loaded_cache[:rows] || !stream
|
54
|
-
rows.find { |row| row.id == index.to_s}
|
55
|
-
else
|
56
|
-
found_row = nil
|
57
|
-
rows do |row|
|
58
|
-
if row.id == index.to_s
|
59
|
-
found_row = row
|
60
|
-
break
|
61
|
-
end
|
62
|
-
end
|
63
|
-
found_row
|
64
|
-
end
|
65
|
-
end
|
66
48
|
|
49
|
+
# DEPRECATED: stream is no longer separate
|
67
50
|
def stream_row(index)
|
68
|
-
row(index
|
51
|
+
row(index)
|
69
52
|
end
|
70
53
|
|
71
54
|
# test mode
|
72
55
|
def cells_by_column(column_letter)
|
73
|
-
|
74
|
-
|
75
|
-
columns << row.cells.find { |cell| to_column_letter(cell.id) == column_letter}
|
56
|
+
rows.map do |row|
|
57
|
+
row.cells.find { |cell| to_column_letter(cell.id) == column_letter}
|
76
58
|
end
|
77
|
-
columns
|
78
59
|
end
|
79
60
|
|
80
61
|
def last_column(row_index=1)
|
81
62
|
@last_column ||= {}
|
82
63
|
@last_column[row_index] ||= begin
|
83
|
-
cells =
|
64
|
+
cells = row(row_index).try(:cells)
|
84
65
|
cells.last.column if cells.present?
|
85
66
|
end
|
86
67
|
end
|
87
68
|
|
88
|
-
def cell(cell_id
|
69
|
+
def cell(cell_id)
|
89
70
|
column_letter, row_index = cell_id.partition(/\d+/)
|
90
|
-
current_row = row(row_index
|
71
|
+
current_row = row(row_index)
|
91
72
|
current_row.cell(column_letter) unless current_row.nil?
|
92
73
|
end
|
93
74
|
|
94
|
-
def formula(cell_id
|
95
|
-
cell(cell_id
|
96
|
-
end
|
97
|
-
|
98
|
-
def rows
|
99
|
-
@rows ||= begin
|
100
|
-
all_rows = @xml.xpath('//sheetData/row').map do |row_node|
|
101
|
-
row = Row.load_from_node(row_node, @shared_strings, @styles, @options)
|
102
|
-
yield row if block_given?
|
103
|
-
row
|
104
|
-
end
|
105
|
-
@loaded_cache[:rows] = true
|
106
|
-
all_rows
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def each
|
111
|
-
if @options[:padded_rows]
|
112
|
-
last_row_index = rows.last.id.to_i
|
113
|
-
(1.upto(last_row_index)).each do |row_index|
|
114
|
-
row = row(row_index)
|
115
|
-
yield (row.blank?) ? Row.new(id: "#{row_index}", cells: []) : row
|
116
|
-
end
|
117
|
-
else
|
118
|
-
rows { |row| yield row }
|
119
|
-
end
|
75
|
+
def formula(cell_id)
|
76
|
+
cell(cell_id).try(:formula)
|
120
77
|
end
|
121
78
|
|
122
79
|
def font(cell_reference)
|
@@ -127,7 +84,6 @@ class OOXL
|
|
127
84
|
cell(cell_reference).try(:fill)
|
128
85
|
end
|
129
86
|
|
130
|
-
|
131
87
|
def data_validations
|
132
88
|
@data_validations ||= begin
|
133
89
|
|
@@ -146,6 +102,11 @@ class OOXL
|
|
146
102
|
end
|
147
103
|
end
|
148
104
|
|
105
|
+
def styles=(styles)
|
106
|
+
@styles = styles
|
107
|
+
@row_cache.styles = styles
|
108
|
+
end
|
109
|
+
|
149
110
|
# a shortcut for:
|
150
111
|
# formula = data_validation('A1').formula
|
151
112
|
# ooxl.named_range(formula)
|
@@ -168,40 +129,51 @@ class OOXL
|
|
168
129
|
if cell_range.include?(":")
|
169
130
|
cell_letters = cell_range.gsub(/[\d]/, '').split(':')
|
170
131
|
start_index, end_index = cell_range[/[A-Z]{1,}\d+/] ? cell_range.gsub(/[^\d:]/, '').split(':').map(&:to_i) : [1, rows.size]
|
171
|
-
# This will allow values from this pattern
|
172
|
-
# 'SheetName!A1:C3'
|
173
|
-
# The number after the cell letter will be the index
|
174
|
-
# 1 => start_index
|
175
|
-
# 3 => end_index
|
176
|
-
# Expected output would be: [['value', 'value', 'value'], ['value', 'value', 'value'], ['value', 'value', 'value']]
|
177
132
|
if cell_letters.uniq.size > 1
|
178
|
-
start_index
|
179
|
-
(letter_index(cell_letters.first)..letter_index(cell_letters.last)).map do |cell_index|
|
180
|
-
row = fetch_row_by_id(row_index.to_s)
|
181
|
-
next if row.blank?
|
182
|
-
|
183
|
-
cell_letter = letter_equivalent(cell_index)
|
184
|
-
row["#{cell_letter}#{row_index}"].value
|
185
|
-
end
|
186
|
-
end
|
133
|
+
list_values_from_rectangle(cell_letters, start_index, end_index)
|
187
134
|
else
|
188
|
-
|
189
|
-
(start_index..end_index).to_a.map do |row_index|
|
190
|
-
row = fetch_row_by_id(row_index.to_s)
|
191
|
-
next if row.blank?
|
192
|
-
row["#{cell_letter}#{row_index}"].value
|
193
|
-
end
|
135
|
+
list_values_from_column(cell_letters.uniq.first, start_index, end_index)
|
194
136
|
end
|
195
137
|
else
|
196
138
|
# when only one value: B2
|
197
|
-
|
198
|
-
row = fetch_row_by_id(row_index.to_s)
|
199
|
-
return if row.blank?
|
200
|
-
[row[cell_range].value]
|
139
|
+
list_values_from_cell(cell_range)
|
201
140
|
end
|
202
141
|
end
|
203
142
|
alias_method :list_values_from_formula, :list_values_from_cell_range
|
204
143
|
|
144
|
+
# This will allow values from this pattern
|
145
|
+
# 'SheetName!A1:C3'
|
146
|
+
# The number after the cell letter will be the index
|
147
|
+
# 1 => start_index
|
148
|
+
# 3 => end_index
|
149
|
+
# Expected output would be: [['value', 'value', 'value'], ['value', 'value', 'value'], ['value', 'value', 'value']]
|
150
|
+
def list_values_from_rectangle(cell_letters, start_index, end_index)
|
151
|
+
start_index.upto(end_index).map do |row_index|
|
152
|
+
(letter_index(cell_letters.first)..letter_index(cell_letters.last)).map do |cell_index|
|
153
|
+
row = row(row_index)
|
154
|
+
next if row.blank?
|
155
|
+
|
156
|
+
cell_letter = letter_equivalent(cell_index)
|
157
|
+
row["#{cell_letter}#{row_index}"].value
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def list_values_from_column(column_letter, start_index, end_index)
|
163
|
+
(start_index..end_index).to_a.map do |row_index|
|
164
|
+
row = row(row_index)
|
165
|
+
next if row.blank?
|
166
|
+
row["#{column_letter}#{row_index}"].value
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def list_values_from_cell(cell_ref)
|
171
|
+
row_index = cell_ref.gsub(/[^\d:]/, '').split(':').map(&:to_i).first
|
172
|
+
row = row(row_index)
|
173
|
+
return if row.blank?
|
174
|
+
[row[cell_ref].value]
|
175
|
+
end
|
176
|
+
|
205
177
|
def self.load_from_stream(xml_stream, shared_strings)
|
206
178
|
self.new(Nokogiri.XML(xml_stream).remove_namespaces!, shared_strings)
|
207
179
|
end
|
@@ -213,9 +185,6 @@ class OOXL
|
|
213
185
|
end
|
214
186
|
|
215
187
|
private
|
216
|
-
def fetch_row_by_id(row_id)
|
217
|
-
rows.find { |row| row.id == row_id.to_s}
|
218
|
-
end
|
219
188
|
|
220
189
|
def merged_cells_range
|
221
190
|
@merged_cells ||= @xml.xpath('//mergeCells/mergeCell').map do |merged_cell|
|
File without changes
|
File without changes
|
File without changes
|
data/lib/ooxl.rb
CHANGED
File without changes
|
data/ooxml_excel.gemspec
CHANGED
@@ -28,7 +28,8 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.add_dependency 'nokogiri', '~> 1'
|
29
29
|
spec.add_dependency 'rubyzip', '~> 1.0', '< 2.0.0'
|
30
30
|
|
31
|
-
spec.add_development_dependency "bundler"
|
31
|
+
spec.add_development_dependency "bundler"
|
32
|
+
spec.add_development_dependency "pry-byebug"
|
32
33
|
spec.add_development_dependency "rake", "~> 10.0"
|
33
34
|
spec.add_development_dependency "rspec", "~> 3.0"
|
34
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ooxl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1.
|
4
|
+
version: 0.0.1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Mones
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -62,16 +62,30 @@ dependencies:
|
|
62
62
|
name: bundler
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
|
-
- - "
|
65
|
+
- - ">="
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '
|
67
|
+
version: '0'
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
|
-
- - "
|
72
|
+
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '
|
74
|
+
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: pry-byebug
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
75
89
|
- !ruby/object:Gem::Dependency
|
76
90
|
name: rake
|
77
91
|
requirement: !ruby/object:Gem::Requirement
|
@@ -129,6 +143,7 @@ files:
|
|
129
143
|
- lib/ooxl/xl_objects/number_formatting.rb
|
130
144
|
- lib/ooxl/xl_objects/relationships.rb
|
131
145
|
- lib/ooxl/xl_objects/row.rb
|
146
|
+
- lib/ooxl/xl_objects/row_cache.rb
|
132
147
|
- lib/ooxl/xl_objects/sheet.rb
|
133
148
|
- lib/ooxl/xl_objects/sheet/data_validation.rb
|
134
149
|
- lib/ooxl/xl_objects/styles.rb
|
@@ -154,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
169
|
version: '0'
|
155
170
|
requirements: []
|
156
171
|
rubyforge_project:
|
157
|
-
rubygems_version: 2.6.
|
172
|
+
rubygems_version: 2.6.12
|
158
173
|
signing_key:
|
159
174
|
specification_version: 4
|
160
175
|
summary: OOXL Excel - Parse Excel Spreadsheets (xlsx, xlsm).
|