oxcelix 0.3.2 → 0.3.3
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.
- data/.yardopts +1 -1
- data/CHANGES +5 -0
- data/LICENSE +20 -20
- data/README.md +70 -70
- data/README.rdoc +61 -61
- data/lib/oxcelix.rb +47 -47
- data/lib/oxcelix/cell.rb +22 -22
- data/lib/oxcelix/cellhelper.rb +48 -48
- data/lib/oxcelix/nf.rb +172 -172
- data/lib/oxcelix/numformats.rb +114 -114
- data/lib/oxcelix/sax/comments.rb +28 -28
- data/lib/oxcelix/sax/sharedstrings.rb +17 -17
- data/lib/oxcelix/sax/styles.rb +48 -48
- data/lib/oxcelix/sax/xlsheet.rb +78 -78
- data/lib/oxcelix/sheet.rb +75 -75
- data/lib/oxcelix/workbook.rb +256 -252
- data/oxcelix.gemspec +26 -26
- data/spec/cell_spec.rb +13 -13
- data/spec/fixnum_spec.rb +11 -11
- data/spec/matrix_spec.rb +11 -11
- data/spec/oxcelix_spec.rb +36 -36
- data/spec/spec_helper.rb +3 -3
- data/spec/string_spec.rb +19 -19
- metadata +9 -10
data/lib/oxcelix/workbook.rb
CHANGED
@@ -1,252 +1,256 @@
|
|
1
|
-
# The namespace for all classes and modules included on Oxcelix.
|
2
|
-
module Oxcelix
|
3
|
-
# Helper methods for the Workbook class
|
4
|
-
module Workbookhelper
|
5
|
-
# returns a sheet based on its name
|
6
|
-
|
7
|
-
# @example Select a sheet
|
8
|
-
# w = Workbook.new('Example.xlsx')
|
9
|
-
# sheet = w["Examplesheet"]
|
10
|
-
def [] (sheetname=String)
|
11
|
-
@sheets.select{|s| s.name==sheetname}[0]
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
# The Workbook class will open the excel file, and convert it to a collection of
|
16
|
-
# Matrix objects
|
17
|
-
# @!attribute [rw] sheets
|
18
|
-
# @return [Array] a collection of {Sheet} objects
|
19
|
-
class Workbook
|
20
|
-
include Cellhelper
|
21
|
-
include Workbookhelper
|
22
|
-
include Numformats
|
23
|
-
|
24
|
-
attr_accessor :sheets
|
25
|
-
|
26
|
-
##
|
27
|
-
# Create a new {Workbook} object.
|
28
|
-
#
|
29
|
-
# filename is the name of the Excel 2007/2010 file to be opened (xlsx)
|
30
|
-
#
|
31
|
-
# options is a collection of options that can be passed to Workbook.
|
32
|
-
# Options may include:
|
33
|
-
# * :copymerge (=> true/false) - Copy and repeat the content of the merged cells into the whole group, e.g.
|
34
|
-
# the group of three merged cells <tt>| a |</tt> will become <tt>|a|a|a|</tt>
|
35
|
-
# * :include (Ary) - an array of sheet names to be included
|
36
|
-
# * :exclude (Ary) - an array of sheet names not to be processed
|
37
|
-
# * :values (Symbol) - cell values. This can be: :false, if the whole cell is needed, :excel, if the raw excel values need to be inserted
|
38
|
-
# and :ruby if ruby objects are preferred.
|
39
|
-
#
|
40
|
-
# The excel file is first getting unzipped, then the workbook.xml file gets
|
41
|
-
# processed. This file stores sheet metadata, which will be filtered (by including
|
42
|
-
# and excluding sheets from further processing)
|
43
|
-
#
|
44
|
-
# The next stage is building sheets.
|
45
|
-
# This includes:
|
46
|
-
# * Parsing the XML files representing the sheets
|
47
|
-
# * Interpolation of the shared strings
|
48
|
-
# * adding comments to the cells
|
49
|
-
# * Converting each sheet to a Matrix object
|
50
|
-
def initialize(filename, options={})
|
51
|
-
@destination = Dir.pwd+'/tmp'
|
52
|
-
FileUtils.
|
53
|
-
Zip::File.open(filename){ |zip_file|
|
54
|
-
zip_file.each{ |f|
|
55
|
-
f_path=File.join(@destination, f.name)
|
56
|
-
FileUtils.mkdir_p(File.dirname(f_path))
|
57
|
-
zip_file.extract(f, f_path) unless File.exists?(f_path)
|
58
|
-
}
|
59
|
-
}
|
60
|
-
@sheets=[]
|
61
|
-
@sheetbase={}
|
62
|
-
@sharedstrings=[]
|
63
|
-
|
64
|
-
f=IO.read(@destination + '/xl/workbook.xml')
|
65
|
-
@a=Ox::load(f)
|
66
|
-
|
67
|
-
sheetdata(options); commentsrel; shstrings;
|
68
|
-
|
69
|
-
styles = Styles.new()
|
70
|
-
File.open(@destination + '/xl/styles.xml', 'r') do |f|
|
71
|
-
Ox.sax_parse(styles, f)
|
72
|
-
end
|
73
|
-
|
74
|
-
styles.temparray.sort_by!{|st| st[:numFmtId].to_i}
|
75
|
-
add_custom_formats styles.temparray
|
76
|
-
styles.styleary.map!{|s| Numformats::Formatarray[s.to_i][:id].to_i}
|
77
|
-
|
78
|
-
@sheets.each do |x|
|
79
|
-
|
80
|
-
@sheet = Xlsheet.new()
|
81
|
-
|
82
|
-
File.open(@destination+"/xl/#{x[:filename]}", 'r') do |f|
|
83
|
-
Ox.sax_parse(@sheet, f)
|
84
|
-
end
|
85
|
-
comments = mkcomments(x[:comments])
|
86
|
-
@sheet.cellarray.each do |sh|
|
87
|
-
sh.numformat = styles.styleary[sh.style.to_i]
|
88
|
-
if sh.type=="s"
|
89
|
-
sh.value = @sharedstrings[sh.value.to_i]
|
90
|
-
end
|
91
|
-
if !comments.nil?
|
92
|
-
comm=comments.select {|c| c[:ref]==(sh.xlcoords)}
|
93
|
-
if comm.size > 0
|
94
|
-
sh.comment=comm[0][:comment]
|
95
|
-
end
|
96
|
-
comments.delete_if{|c| c[:ref]==(sh.xlcoords)}
|
97
|
-
end
|
98
|
-
end
|
99
|
-
x[:cells] = @sheet.cellarray
|
100
|
-
x[:mergedcells] = @sheet.mergedcells
|
101
|
-
end
|
102
|
-
FileUtils.remove_dir(@destination, true)
|
103
|
-
matrixto options[:copymerge]
|
104
|
-
end
|
105
|
-
|
106
|
-
private
|
107
|
-
# @private
|
108
|
-
# Given the data found in workbook.xml, create a hash and push it to the sheets
|
109
|
-
# array.
|
110
|
-
#
|
111
|
-
# The hash will not be pushed into the array if the sheet name is blacklisted
|
112
|
-
# (it appears in the *excluded_sheets* array) or does not appear in the list of
|
113
|
-
# included sheets.
|
114
|
-
#
|
115
|
-
# If *included_sheets* (the array of whitelisted sheets) is *nil*, the hash is added.
|
116
|
-
def sheetdata options={}
|
117
|
-
@a.locate("workbook/sheets/*").each do |x|
|
118
|
-
@sheetbase[:name] = x[:name]
|
119
|
-
@sheetbase[:sheetId] = x[:sheetId]
|
120
|
-
@sheetbase[:relationId] = x[:"r:id"]
|
121
|
-
|
122
|
-
relationshipfile=nil
|
123
|
-
fname=nil
|
124
|
-
unless Dir[@destination + '/xl/_rels'].empty?
|
125
|
-
Find.find(@destination + '/xl/_rels') do |path|
|
126
|
-
if File.basename(path).split(".").last=='rels'
|
127
|
-
g=IO.read(path)
|
128
|
-
relationshipfile=Ox::load(g)
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
relationshipfile.locate("Relationships/*").each do |rship|
|
133
|
-
if rship[:Id] == x[:"r:id"]
|
134
|
-
@sheetbase[:filename]=rship[:Target]
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
|
139
|
-
@sheets << @sheetbase
|
140
|
-
@sheetbase=Hash.new
|
141
|
-
end
|
142
|
-
sheetarr=@sheets.map{|i| i[:name]}
|
143
|
-
if options[:include].nil?; options[:include]=[]; end
|
144
|
-
if options[:include].to_a.size>0
|
145
|
-
sheetarr.keep_if{|item| options[:include].to_a.detect{|d| d==item}}
|
146
|
-
end
|
147
|
-
sheetarr=sheetarr-options[:exclude].to_a
|
148
|
-
@sheets.keep_if{|item| sheetarr.detect{|d| d==item[:name]}}
|
149
|
-
@sheets.uniq!
|
150
|
-
end
|
151
|
-
|
152
|
-
# Build the relationship between sheets and the XML files storing the comments
|
153
|
-
# to the actual sheet.
|
154
|
-
def commentsrel
|
155
|
-
unless Dir[@destination + '/xl/worksheets/_rels'].empty?
|
156
|
-
Find.find(@destination + '/xl/worksheets/_rels') do |path|
|
157
|
-
if File.basename(path).split(".").last=='rels'
|
158
|
-
a=IO.read(path)
|
159
|
-
f=Ox::load(a)
|
160
|
-
f.locate("Relationships/*").each do |x|
|
161
|
-
if x[:Target].include?"comments"
|
162
|
-
@sheets.each do |s|
|
163
|
-
if "worksheets/" + File.basename(path,".rels")==s[:filename]
|
164
|
-
s[:comments]=x[:Target]
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
else
|
172
|
-
@sheets.each do |s|
|
173
|
-
s[:comments]=nil
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
# Invokes the Sharedstrings helper class
|
179
|
-
def shstrings
|
180
|
-
strings = Sharedstrings.new()
|
181
|
-
File.open(@destination + '/xl/sharedStrings.xml', 'r') do |f|
|
182
|
-
Ox.sax_parse(strings, f)
|
183
|
-
end
|
184
|
-
@sharedstrings=strings.stringarray
|
185
|
-
end
|
186
|
-
|
187
|
-
# Parses the comments related to the actual sheet.
|
188
|
-
# @param [String] commentfile
|
189
|
-
# @return [Array] a collection of comments relative to the Excel sheet currently processed
|
190
|
-
def mkcomments(commentfile)
|
191
|
-
unless commentfile.nil?
|
192
|
-
comms = Comments.new()
|
193
|
-
File.open(@destination + '/xl/'+commentfile.gsub('../', ''), 'r') do |f|
|
194
|
-
Ox.sax_parse(comms, f)
|
195
|
-
end
|
196
|
-
return comms.commarray
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
# Returns an array of Matrix objects.
|
201
|
-
# For each sheet, matrixto first checks the address (xlcoords) of the
|
202
|
-
# last cell in the cellarray, then builds a *nil*-filled Matrix object of
|
203
|
-
# size *xlcoords.x, xlcoords.y*.
|
204
|
-
#
|
205
|
-
# The matrix will then be filled with Cell objects according to their coordinates.
|
206
|
-
#
|
207
|
-
# If the *copymerge* parameter is *true*, it creates a submatrix (minor)
|
208
|
-
# of every mergegroup (based on the mergedcells array relative to the actual
|
209
|
-
# sheet), and after the only meaningful cell of the minor is found, it is
|
210
|
-
# copied back to the remaining cells of the group. The coordinates (xlcoords)
|
211
|
-
# of each copied cell is changed to reflect the actual Excel coordinate.
|
212
|
-
#
|
213
|
-
# The matrix will replace the array of cells in the actual sheet.
|
214
|
-
# @param [Bool] copymerge
|
215
|
-
# @yield a value to be put as a cell. e.g: matrixto true, { |x| x = x.value.to_ru }
|
216
|
-
# @return [Matrix] a Matrix object that stores the cell values, and, depending on the copymerge parameter, will copy the merged value
|
217
|
-
# into every merged cell
|
218
|
-
def matrixto(copymerge)
|
219
|
-
@sheets.each_with_index do |sheet, i|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
(y1..y2)
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
end
|
1
|
+
# The namespace for all classes and modules included on Oxcelix.
|
2
|
+
module Oxcelix
|
3
|
+
# Helper methods for the Workbook class
|
4
|
+
module Workbookhelper
|
5
|
+
# returns a sheet based on its name
|
6
|
+
|
7
|
+
# @example Select a sheet
|
8
|
+
# w = Workbook.new('Example.xlsx')
|
9
|
+
# sheet = w["Examplesheet"]
|
10
|
+
def [] (sheetname=String)
|
11
|
+
@sheets.select{|s| s.name==sheetname}[0]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# The Workbook class will open the excel file, and convert it to a collection of
|
16
|
+
# Matrix objects
|
17
|
+
# @!attribute [rw] sheets
|
18
|
+
# @return [Array] a collection of {Sheet} objects
|
19
|
+
class Workbook
|
20
|
+
include Cellhelper
|
21
|
+
include Workbookhelper
|
22
|
+
include Numformats
|
23
|
+
|
24
|
+
attr_accessor :sheets
|
25
|
+
|
26
|
+
##
|
27
|
+
# Create a new {Workbook} object.
|
28
|
+
#
|
29
|
+
# filename is the name of the Excel 2007/2010 file to be opened (xlsx)
|
30
|
+
#
|
31
|
+
# options is a collection of options that can be passed to Workbook.
|
32
|
+
# Options may include:
|
33
|
+
# * :copymerge (=> true/false) - Copy and repeat the content of the merged cells into the whole group, e.g.
|
34
|
+
# the group of three merged cells <tt>| a |</tt> will become <tt>|a|a|a|</tt>
|
35
|
+
# * :include (Ary) - an array of sheet names to be included
|
36
|
+
# * :exclude (Ary) - an array of sheet names not to be processed
|
37
|
+
# * :values (Symbol) - cell values. This can be: :false, if the whole cell is needed, :excel, if the raw excel values need to be inserted
|
38
|
+
# and :ruby if ruby objects are preferred.
|
39
|
+
#
|
40
|
+
# The excel file is first getting unzipped, then the workbook.xml file gets
|
41
|
+
# processed. This file stores sheet metadata, which will be filtered (by including
|
42
|
+
# and excluding sheets from further processing)
|
43
|
+
#
|
44
|
+
# The next stage is building sheets.
|
45
|
+
# This includes:
|
46
|
+
# * Parsing the XML files representing the sheets
|
47
|
+
# * Interpolation of the shared strings
|
48
|
+
# * adding comments to the cells
|
49
|
+
# * Converting each sheet to a Matrix object
|
50
|
+
def initialize(filename, options={})
|
51
|
+
@destination = Dir.pwd+'/tmp'
|
52
|
+
FileUtils.mkdir_p(@destination)
|
53
|
+
Zip::File.open(filename){ |zip_file|
|
54
|
+
zip_file.each{ |f|
|
55
|
+
f_path=File.join(@destination, f.name)
|
56
|
+
FileUtils.mkdir_p(File.dirname(f_path))
|
57
|
+
zip_file.extract(f, f_path) unless File.exists?(f_path)
|
58
|
+
}
|
59
|
+
}
|
60
|
+
@sheets=[]
|
61
|
+
@sheetbase={}
|
62
|
+
@sharedstrings=[]
|
63
|
+
|
64
|
+
f=IO.read(@destination + '/xl/workbook.xml')
|
65
|
+
@a=Ox::load(f)
|
66
|
+
|
67
|
+
sheetdata(options); commentsrel; shstrings;
|
68
|
+
|
69
|
+
styles = Styles.new()
|
70
|
+
File.open(@destination + '/xl/styles.xml', 'r') do |f|
|
71
|
+
Ox.sax_parse(styles, f)
|
72
|
+
end
|
73
|
+
|
74
|
+
styles.temparray.sort_by!{|st| st[:numFmtId].to_i}
|
75
|
+
add_custom_formats styles.temparray
|
76
|
+
styles.styleary.map!{|s| Numformats::Formatarray[s.to_i][:id].to_i}
|
77
|
+
|
78
|
+
@sheets.each do |x|
|
79
|
+
|
80
|
+
@sheet = Xlsheet.new()
|
81
|
+
|
82
|
+
File.open(@destination+"/xl/#{x[:filename]}", 'r') do |f|
|
83
|
+
Ox.sax_parse(@sheet, f)
|
84
|
+
end
|
85
|
+
comments = mkcomments(x[:comments])
|
86
|
+
@sheet.cellarray.each do |sh|
|
87
|
+
sh.numformat = styles.styleary[sh.style.to_i]
|
88
|
+
if sh.type=="s"
|
89
|
+
sh.value = @sharedstrings[sh.value.to_i]
|
90
|
+
end
|
91
|
+
if !comments.nil?
|
92
|
+
comm=comments.select {|c| c[:ref]==(sh.xlcoords)}
|
93
|
+
if comm.size > 0
|
94
|
+
sh.comment=comm[0][:comment]
|
95
|
+
end
|
96
|
+
comments.delete_if{|c| c[:ref]==(sh.xlcoords)}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
x[:cells] = @sheet.cellarray
|
100
|
+
x[:mergedcells] = @sheet.mergedcells
|
101
|
+
end
|
102
|
+
FileUtils.remove_dir(@destination, true)
|
103
|
+
matrixto options[:copymerge]
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
# @private
|
108
|
+
# Given the data found in workbook.xml, create a hash and push it to the sheets
|
109
|
+
# array.
|
110
|
+
#
|
111
|
+
# The hash will not be pushed into the array if the sheet name is blacklisted
|
112
|
+
# (it appears in the *excluded_sheets* array) or does not appear in the list of
|
113
|
+
# included sheets.
|
114
|
+
#
|
115
|
+
# If *included_sheets* (the array of whitelisted sheets) is *nil*, the hash is added.
|
116
|
+
def sheetdata options={}
|
117
|
+
@a.locate("workbook/sheets/*").each do |x|
|
118
|
+
@sheetbase[:name] = x[:name]
|
119
|
+
@sheetbase[:sheetId] = x[:sheetId]
|
120
|
+
@sheetbase[:relationId] = x[:"r:id"]
|
121
|
+
|
122
|
+
relationshipfile=nil
|
123
|
+
fname=nil
|
124
|
+
unless Dir[@destination + '/xl/_rels'].empty?
|
125
|
+
Find.find(@destination + '/xl/_rels') do |path|
|
126
|
+
if File.basename(path).split(".").last=='rels'
|
127
|
+
g=IO.read(path)
|
128
|
+
relationshipfile=Ox::load(g)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
relationshipfile.locate("Relationships/*").each do |rship|
|
133
|
+
if rship[:Id] == x[:"r:id"]
|
134
|
+
@sheetbase[:filename]=rship[:Target]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
@sheets << @sheetbase
|
140
|
+
@sheetbase=Hash.new
|
141
|
+
end
|
142
|
+
sheetarr=@sheets.map{|i| i[:name]}
|
143
|
+
if options[:include].nil?; options[:include]=[]; end
|
144
|
+
if options[:include].to_a.size>0
|
145
|
+
sheetarr.keep_if{|item| options[:include].to_a.detect{|d| d==item}}
|
146
|
+
end
|
147
|
+
sheetarr=sheetarr-options[:exclude].to_a
|
148
|
+
@sheets.keep_if{|item| sheetarr.detect{|d| d==item[:name]}}
|
149
|
+
@sheets.uniq!
|
150
|
+
end
|
151
|
+
|
152
|
+
# Build the relationship between sheets and the XML files storing the comments
|
153
|
+
# to the actual sheet.
|
154
|
+
def commentsrel
|
155
|
+
unless Dir[@destination + '/xl/worksheets/_rels'].empty?
|
156
|
+
Find.find(@destination + '/xl/worksheets/_rels') do |path|
|
157
|
+
if File.basename(path).split(".").last=='rels'
|
158
|
+
a=IO.read(path)
|
159
|
+
f=Ox::load(a)
|
160
|
+
f.locate("Relationships/*").each do |x|
|
161
|
+
if x[:Target].include?"comments"
|
162
|
+
@sheets.each do |s|
|
163
|
+
if "worksheets/" + File.basename(path,".rels")==s[:filename]
|
164
|
+
s[:comments]=x[:Target]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
else
|
172
|
+
@sheets.each do |s|
|
173
|
+
s[:comments]=nil
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# Invokes the Sharedstrings helper class
|
179
|
+
def shstrings
|
180
|
+
strings = Sharedstrings.new()
|
181
|
+
File.open(@destination + '/xl/sharedStrings.xml', 'r') do |f|
|
182
|
+
Ox.sax_parse(strings, f)
|
183
|
+
end
|
184
|
+
@sharedstrings=strings.stringarray
|
185
|
+
end
|
186
|
+
|
187
|
+
# Parses the comments related to the actual sheet.
|
188
|
+
# @param [String] commentfile
|
189
|
+
# @return [Array] a collection of comments relative to the Excel sheet currently processed
|
190
|
+
def mkcomments(commentfile)
|
191
|
+
unless commentfile.nil?
|
192
|
+
comms = Comments.new()
|
193
|
+
File.open(@destination + '/xl/'+commentfile.gsub('../', ''), 'r') do |f|
|
194
|
+
Ox.sax_parse(comms, f)
|
195
|
+
end
|
196
|
+
return comms.commarray
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Returns an array of Matrix objects.
|
201
|
+
# For each sheet, matrixto first checks the address (xlcoords) of the
|
202
|
+
# last cell in the cellarray, then builds a *nil*-filled Matrix object of
|
203
|
+
# size *xlcoords.x, xlcoords.y*.
|
204
|
+
#
|
205
|
+
# The matrix will then be filled with Cell objects according to their coordinates.
|
206
|
+
#
|
207
|
+
# If the *copymerge* parameter is *true*, it creates a submatrix (minor)
|
208
|
+
# of every mergegroup (based on the mergedcells array relative to the actual
|
209
|
+
# sheet), and after the only meaningful cell of the minor is found, it is
|
210
|
+
# copied back to the remaining cells of the group. The coordinates (xlcoords)
|
211
|
+
# of each copied cell is changed to reflect the actual Excel coordinate.
|
212
|
+
#
|
213
|
+
# The matrix will replace the array of cells in the actual sheet.
|
214
|
+
# @param [Bool] copymerge
|
215
|
+
# @yield a value to be put as a cell. e.g: matrixto true, { |x| x = x.value.to_ru }
|
216
|
+
# @return [Matrix] a Matrix object that stores the cell values, and, depending on the copymerge parameter, will copy the merged value
|
217
|
+
# into every merged cell
|
218
|
+
def matrixto(copymerge)
|
219
|
+
@sheets.each_with_index do |sheet, i|
|
220
|
+
if sheet[:cells].empty?
|
221
|
+
m=Sheet.build(0,0)
|
222
|
+
else
|
223
|
+
m=Sheet.build(sheet[:cells].last.y+1, sheet[:cells].last.x+1) {nil}
|
224
|
+
sheet[:cells].each do |c|
|
225
|
+
m[c.y, c.x] = c
|
226
|
+
end
|
227
|
+
if copymerge==true
|
228
|
+
sheet[:mergedcells].each do |mc|
|
229
|
+
a = mc.split(':')
|
230
|
+
x1=x(a[0])
|
231
|
+
y1=y(a[0])
|
232
|
+
x2=x(a[1])
|
233
|
+
y2=y(a[1])
|
234
|
+
mrange=m.minor(y1..y2, x1..x2)
|
235
|
+
valuecell=mrange.to_a.flatten.compact[0]
|
236
|
+
(x1..x2).each do |col|
|
237
|
+
(y1..y2).each do |row|
|
238
|
+
if valuecell != nil
|
239
|
+
valuecell.xlcoords=(col.col_name)+(row+1).to_s
|
240
|
+
m[row, col]=valuecell
|
241
|
+
else
|
242
|
+
valuecell=Cell.new
|
243
|
+
valuecell.xlcoords=(col.col_name)+(row+1).to_s
|
244
|
+
m[row, col]=valuecell
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
m.name=@sheets[i][:name]; m.sheetId=@sheets[i][:sheetId]; m.relationId=@sheets[i][:relationId]
|
251
|
+
@sheets[i]=m
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|