listen360-rubyXL 1.2.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,265 @@
1
+ module RubyXL
2
+ class PrivateClass
3
+ private
4
+
5
+ #validate and modify methods
6
+ def validate_horizontal_alignment(alignment)
7
+ if alignment.to_s == '' || alignment == 'center' || alignment == 'distributed' || alignment == 'justify' || alignment == 'left' || alignment == 'right'
8
+ return true
9
+ end
10
+ raise 'Only center, distributed, justify, left, and right are valid horizontal alignments'
11
+ end
12
+
13
+ def validate_vertical_alignment(alignment)
14
+ if alignment.to_s == '' || alignment == 'center' || alignment == 'distributed' || alignment == 'justify' || alignment == 'top' || alignment == 'bottom'
15
+ return true
16
+ end
17
+ raise 'Only center, distributed, justify, top, and bottom are valid vertical alignments'
18
+ end
19
+
20
+ def validate_border(weight)
21
+ if weight.to_s == '' || weight == 'thin' || weight == 'thick' || weight == 'hairline' || weight == 'medium'
22
+ return true
23
+ end
24
+ raise 'Border weights must only be "hairline", "thin", "medium", or "thick"'
25
+ end
26
+
27
+ def validate_nonnegative(row_or_col)
28
+ if row_or_col < 0
29
+ raise 'Row and Column arguments must be nonnegative'
30
+ end
31
+ end
32
+
33
+ # This method checks to see if there is an equivalent font that exists
34
+ def find_font(workbook, font)
35
+ workbook.fonts.each {|font_id, f|
36
+ if f[:font][:i] == font[:i] &&
37
+ f[:font][:b] == font[:b] &&
38
+ f[:font][:u] == font[:u] &&
39
+ f[:font][:strike] == font[:strike] &&
40
+ f[:font][:name][:attributes][:val] == font[:name][:attributes][:val] &&
41
+ f[:font][:sz][:attributes][:val] == font[:sz][:attributes][:val] &&
42
+ (f[:font][:color] && f[:font][:color][:attributes][:rgb]) == (font[:color] && font[:color][:attributes][:rgb])
43
+ return font_id
44
+ end
45
+ }
46
+ return nil
47
+ end
48
+
49
+ # Helper method to modify the font color
50
+ def modify_font_color(font, font_color)
51
+ if font[:color].nil?
52
+ font[:color] = {:attributes => {:rgb => ''}}
53
+ end
54
+ font[:color][:attributes][:rgb] = font_color.to_s
55
+ return font
56
+ end
57
+
58
+ # Helper method to modify the font's italics settings
59
+ def modify_font_italics(font, italicized)
60
+ if italicized
61
+ font[:i] = {}
62
+ else
63
+ font[:i] = nil
64
+ end
65
+ return font
66
+ end
67
+
68
+ # Helper method to modify the font's bold settings
69
+ def modify_font_bold(font, bolded)
70
+ if bolded
71
+ font[:b] = {}
72
+ else
73
+ font[:b] = nil
74
+ end
75
+ return font
76
+ end
77
+
78
+ # Helper method to modify the font's underline settings
79
+ def modify_font_underline(font, underlined)
80
+ if underlined
81
+ font[:u] = {}
82
+ else
83
+ font[:u] = nil
84
+ end
85
+ return font
86
+ end
87
+
88
+ # Helper method to modify the font's strikethrough settings
89
+ def modify_font_strikethrough(font, struckthrough)
90
+ if struckthrough
91
+ font[:strike] = {}
92
+ else
93
+ font[:strike] = nil
94
+ end
95
+ return font
96
+ end
97
+
98
+ # Determines if font exists
99
+ # If yes, return id of existing font
100
+ # If no, appends font to font array
101
+ def modify_font(workbook, font, old_font_id)
102
+ font_id = old_font_id
103
+ existing_font_id = find_font(workbook, font)
104
+ if !existing_font_id.nil?
105
+ font_id = existing_font_id
106
+ workbook.fonts[font_id][:count] += 1
107
+ workbook.fonts[old_font_id][:count] -= 1
108
+ elsif workbook.fonts[old_font_id.to_s][:count] > 1 || old_font_id == '0'
109
+ font_id = workbook.fonts.size.to_s
110
+ workbook.fonts[font_id] = {}
111
+ workbook.fonts[font_id][:font] = font
112
+ workbook.fonts[font_id][:count] = 1
113
+ workbook.fonts[old_font_id][:count] -= 1
114
+ else
115
+ workbook.fonts[font_id][:font] = font
116
+ end
117
+ return font_id
118
+ end
119
+
120
+ # This method checks to see if there is an equivalent xf that exists
121
+ def find_xf(workbook, xf)
122
+ workbook.cell_xfs[:xf].each_with_index {|xfs, index|
123
+ if xfs[:attributes][:borderId] == xf[:borderId] &&
124
+ xfs[:attributes][:xfId] == xf[:xfId] &&
125
+ xfs[:attributes][:fillId] == xf[:fillId] &&
126
+ xfs[:attributes][:numFmtId] == xf[:numFmtId] &&
127
+ xfs[:attributes][:fontId] == xf[:fontId]
128
+ return index
129
+ end
130
+ }
131
+ return nil
132
+ end
133
+
134
+ # Determines if xf exists
135
+ # If yes, return id of existing xf
136
+ # If no, appends xf to xf array
137
+ def modify_xf(workbook, xf)
138
+ existing_xf_id = find_xf(workbook, xf)
139
+ if !existing_xf_id.nil?
140
+ xf_id = existing_xf_id
141
+ else
142
+ if workbook.cell_xfs[:xf].is_a?Array
143
+ workbook.cell_xfs[:xf] << {:attributes=>xf}
144
+ else
145
+ workbook.cell_xfs[:xf] = [workbook.cell_xfs[:xf], {:attributes=>xf}]
146
+ end
147
+ xf[:applyFont] = '1'
148
+ workbook.cell_xfs[:attributes][:count] += 1
149
+ xf_id = workbook.cell_xfs[:xf].size - 1
150
+ end
151
+ return xf_id
152
+ end
153
+
154
+ #modifies fill array (copies, appends, adds color and solid attribute)
155
+ #then styles array (copies, appends)
156
+ def modify_fill(workbook, style_index, rgb)
157
+ xf_obj = workbook.get_style(style_index)
158
+ xf = workbook.get_style_attributes(xf_obj)
159
+ #modify fill array
160
+ fill_id = xf[:fillId]
161
+
162
+ fill = workbook.fills[fill_id.to_s][:fill]
163
+ if workbook.fills[fill_id.to_s][:count] > 1 || fill_id == 0 || fill_id == 1
164
+ old_size = workbook.fills.size.to_s
165
+ workbook.fills[old_size] = {}
166
+ workbook.fills[old_size][:fill] = deep_copy(fill)
167
+ workbook.fills[old_size][:count] = 1
168
+ workbook.fills[fill_id.to_s][:count] -= 1
169
+
170
+ change_wb_fill(workbook, old_size,rgb)
171
+
172
+ #modify styles array
173
+ fill_id = old_size
174
+ if workbook.cell_xfs[:xf].is_a?Array
175
+ workbook.cell_xfs[:xf] << deep_copy({:attributes=>xf})
176
+ else
177
+ workbook.cell_xfs[:xf] = [workbook.cell_xfs[:xf], deep_copy({:attributes=>xf})]
178
+ end
179
+ xf = workbook.get_style_attributes(workbook.cell_xfs[:xf].last)
180
+ xf[:fillId] = fill_id
181
+ xf[:applyFill] = '1'
182
+ workbook.cell_xfs[:attributes][:count] += 1
183
+ return workbook.cell_xfs[:xf].size-1
184
+ else
185
+ change_wb_fill(workbook, fill_id.to_s,rgb)
186
+ return style_index
187
+ end
188
+ end
189
+
190
+ def modify_border(workbook, style_index)
191
+ xf_obj = workbook.get_style(style_index)
192
+ xf = workbook.get_style_attributes(xf_obj)
193
+
194
+ border_id = Integer(xf[:borderId])
195
+ border = workbook.borders[border_id.to_s][:border]
196
+ if workbook.borders[border_id.to_s][:count] > 1 || border_id == 0 || border_id == 1
197
+ old_size = workbook.borders.size.to_s
198
+ workbook.borders[old_size] = {}
199
+ workbook.borders[old_size][:border] = deep_copy(border)
200
+ workbook.borders[old_size][:count] = 1
201
+
202
+ border_id = old_size
203
+
204
+ if workbook.cell_xfs[:xf].is_a?Array
205
+ workbook.cell_xfs[:xf] << deep_copy(xf_obj)
206
+ else
207
+ workbook.cell_xfs[:xf] = [workbook.cell_xfs[:xf], deep_copy(xf_obj)]
208
+ end
209
+
210
+ xf = workbook.get_style_attributes(workbook.cell_xfs[:xf].last)
211
+ xf[:borderId] = border_id
212
+ xf[:applyBorder] = '1'
213
+ workbook.cell_xfs[:attributes][:count] += 1
214
+ return workbook.cell_xfs[:xf].size-1
215
+ else
216
+ return style_index
217
+ end
218
+ end
219
+
220
+ #is_horizontal is true when doing horizontal alignment,
221
+ #false when doing vertical alignment
222
+ def modify_alignment(workbook, style_index, is_horizontal, alignment)
223
+ old_xf_obj = workbook.get_style(style_index)
224
+
225
+ xf_obj = deep_copy(old_xf_obj)
226
+
227
+ if xf_obj[:alignment].nil? || xf_obj[:alignment][:attributes].nil?
228
+ xf_obj[:alignment] = {:attributes=>{:horizontal=>nil, :vertical=>nil}}
229
+ end
230
+
231
+ if is_horizontal
232
+ xf_obj[:alignment][:attributes][:horizontal] = alignment.to_s
233
+ else
234
+ xf_obj[:alignment][:attributes][:vertical] = alignment.to_s
235
+ end
236
+
237
+ if workbook.cell_xfs[:xf].is_a?Array
238
+ workbook.cell_xfs[:xf] << deep_copy(xf_obj)
239
+ else
240
+ workbook.cell_xfs[:xf] = [workbook.cell_xfs[:xf], deep_copy(xf_obj)]
241
+ end
242
+
243
+ xf = workbook.get_style_attributes(workbook.cell_xfs[:xf].last)
244
+ xf[:applyAlignment] = '1'
245
+ workbook.cell_xfs[:attributes][:count] += 1
246
+ workbook.cell_xfs[:xf].size-1
247
+ end
248
+
249
+ #returns non-shallow copy of hash
250
+ def deep_copy(hash)
251
+ Marshal.load(Marshal.dump(hash))
252
+ end
253
+
254
+ def change_wb_fill(workbook, fill_index, rgb)
255
+ if workbook.fills[fill_index][:fill][:patternFill][:fgColor].nil?
256
+ workbook.fills[fill_index][:fill][:patternFill][:fgColor] = {:attributes => {:rgb => ''}}
257
+ end
258
+ workbook.fills[fill_index][:fill][:patternFill][:fgColor][:attributes][:rgb] = rgb
259
+
260
+ #previously none, doesn't show fill
261
+ workbook.fills[fill_index][:fill][:patternFill][:attributes][:patternType] = 'solid'
262
+ end
263
+
264
+ end
265
+ end
@@ -0,0 +1,450 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__),'writer','content_types_writer'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__),'writer','root_rels_writer'))
3
+ require File.expand_path(File.join(File.dirname(__FILE__),'writer','app_writer'))
4
+ require File.expand_path(File.join(File.dirname(__FILE__),'writer','core_writer'))
5
+ require File.expand_path(File.join(File.dirname(__FILE__),'writer','theme_writer'))
6
+ require File.expand_path(File.join(File.dirname(__FILE__),'writer','workbook_rels_writer'))
7
+ require File.expand_path(File.join(File.dirname(__FILE__),'writer','workbook_writer'))
8
+ require File.expand_path(File.join(File.dirname(__FILE__),'writer','styles_writer'))
9
+ require File.expand_path(File.join(File.dirname(__FILE__),'writer','shared_strings_writer'))
10
+ require File.expand_path(File.join(File.dirname(__FILE__),'writer','worksheet_writer'))
11
+ require 'rubyXL/zip'
12
+ require 'date'
13
+
14
+ module RubyXL
15
+ class Workbook
16
+ include Enumerable
17
+ attr_accessor :worksheets, :filepath, :creator, :modifier, :created_at,
18
+ :modified_at, :company, :application, :appversion, :num_fmts, :num_fmts_hash, :fonts, :fills,
19
+ :borders, :cell_xfs, :cell_style_xfs, :cell_styles, :shared_strings, :calc_chain,
20
+ :num_strings, :size, :date1904, :external_links, :style_corrector, :drawings,
21
+ :worksheet_rels, :printer_settings, :macros, :colors, :shared_strings_XML, :defined_names, :column_lookup_hash
22
+
23
+
24
+ APPLICATION = 'Microsoft Macintosh Excel'
25
+ APPVERSION = '12.0000'
26
+ SHEET_NAME = 'Sheet1'
27
+ def initialize(worksheets=[], filepath=nil, creator=nil, modifier=nil, created_at=nil,
28
+ company='', application=APPLICATION,
29
+ appversion=APPVERSION, date1904=0)
30
+ if worksheets.nil? || worksheets.empty?
31
+ @worksheets = [Worksheet.new(self,SHEET_NAME)]
32
+ else
33
+ @worksheets = worksheets
34
+ end
35
+ @filepath = filepath
36
+ @creator = creator
37
+ @modifier = modifier
38
+ @company = company
39
+ @application = application
40
+ @appversion = appversion
41
+ @num_fmts = nil
42
+ @num_fmts_hash = nil
43
+ @fonts = nil
44
+ @fills = nil
45
+ @borders = nil
46
+ @cell_xfs = nil
47
+ @cell_style_xfs = nil
48
+ @cell_styles = nil
49
+ @shared_strings = nil
50
+ @calc_chain = nil #unnecessary?
51
+ @num_strings = 0 #num strings total
52
+ @size = 0 #num strings in shared_strings array
53
+ @date1904 = date1904 > 0
54
+ @external_links = nil
55
+ @style_corrector = nil
56
+ @drawings = nil
57
+ @worksheet_rels = nil
58
+ @printer_settings = nil
59
+ @macros = nil
60
+ @colors = nil
61
+ @shared_strings_XML = nil
62
+ @defined_names = nil
63
+ @column_lookup_hash = {}
64
+
65
+ begin
66
+ @created_at = DateTime.parse(created_at).strftime('%Y-%m-%dT%TZ')
67
+ rescue
68
+ t = Time.now
69
+ @created_at = t.strftime('%Y-%m-%dT%TZ')
70
+ end
71
+ @modified_at = @created_at
72
+
73
+ fill_styles()
74
+ fill_shared_strings()
75
+ end
76
+
77
+ # allows easier access to worksheets
78
+ def [](worksheet)
79
+ return worksheets[worksheet]
80
+ end
81
+
82
+ def each
83
+ worksheets.each{|i| yield i}
84
+ end
85
+
86
+ def num_fmts_by_id
87
+
88
+ return @num_fmts_hash unless @num_fmts_hash.nil?
89
+ if num_fmts
90
+ @num_fmts_hash={}
91
+ num_fmts[:numFmt].each do |num_fmt|
92
+ @num_fmts_hash[num_fmt[:attributes][:numFmtId]]=num_fmt
93
+ end
94
+ @num_fmts_hash
95
+ else
96
+ {}
97
+ end
98
+ end
99
+
100
+ #filepath of xlsx file (including file itself)
101
+ def write(filepath=@filepath)
102
+ validate_before_write
103
+ if !(filepath =~ /(.+)\.xls(x|m)/)
104
+ raise "Only xlsx and xlsm files are supported. Unsupported type for file: #{filepath}"
105
+ end
106
+ dirpath = ''
107
+ extension = 'xls'
108
+ if(filepath =~ /((.|\s)*)\.xls(x|m)$/)
109
+ dirpath = $1.to_s()
110
+ extension += $3.to_s
111
+ end
112
+ filename = ''
113
+ if(filepath =~ /\/((.|\s)*)\/((.|\s)*)\.xls(x|m)$/)
114
+ filename = $3.to_s()
115
+ end
116
+
117
+ #creates zip file, writes each type of file to zip folder
118
+ #zips package and renames it to xlsx.
119
+ zippath = File.join(dirpath, filename + '.zip')
120
+ File.unlink(zippath) if File.exists?(zippath)
121
+ FileUtils.mkdir_p(File.join(dirpath,zippath))
122
+ Zip::ZipFile.open(zippath, Zip::ZipFile::CREATE) do |zipfile|
123
+ writer = Writer::ContentTypesWriter.new(dirpath,self)
124
+ zipfile.get_output_stream('[Content_Types].xml') {|f| f.puts(writer.write())}
125
+
126
+ writer = Writer::RootRelsWriter.new(dirpath,self)
127
+ zipfile.get_output_stream(File.join('_rels','.rels')) {|f| f.puts(writer.write())}
128
+
129
+ writer = Writer::AppWriter.new(dirpath,self)
130
+ zipfile.get_output_stream(File.join('docProps','app.xml')) {|f| f.puts(writer.write())}
131
+
132
+ writer = Writer::CoreWriter.new(dirpath,self)
133
+ zipfile.get_output_stream(File.join('docProps','core.xml')) {|f| f.puts(writer.write())}
134
+
135
+ writer = Writer::ThemeWriter.new(dirpath,self)
136
+ zipfile.get_output_stream(File.join('xl','theme','theme1.xml')) {|f| f.puts(writer.write())}
137
+
138
+ writer = Writer::WorkbookRelsWriter.new(dirpath,self)
139
+ zipfile.get_output_stream(File.join('xl','_rels','workbook.xml.rels')) {|f| f.puts(writer.write())}
140
+
141
+ writer = Writer::WorkbookWriter.new(dirpath,self)
142
+ zipfile.get_output_stream(File.join('xl','workbook.xml')) {|f| f.puts(writer.write())}
143
+
144
+ writer = Writer::StylesWriter.new(dirpath,self)
145
+ zipfile.get_output_stream(File.join('xl','styles.xml')) {|f| f.puts(writer.write())}
146
+
147
+ unless @shared_strings.nil?
148
+ writer = Writer::SharedStringsWriter.new(dirpath,self)
149
+ zipfile.get_output_stream(File.join('xl','sharedStrings.xml')) {|f| f.puts(writer.write())}
150
+ end
151
+
152
+ #preserves external links (exactly, no modification allowed)
153
+ unless @external_links.nil?
154
+ #-1 because of rels
155
+ 1.upto(@external_links.size-1) do |i|
156
+ zipfile.get_output_stream(
157
+ File.join('xl','externalLinks',"externalLink#{i}.xml")) {|f|
158
+ f.puts(@external_links[i])
159
+ }
160
+ end
161
+ @external_links['rels'].each_index do |i|
162
+ unless @external_links['rels'][i].nil?
163
+ zipfile.get_output_stream(
164
+ File.join('xl','externalLinks','_rels',"externalLink#{i}.xml.rels")) {|f|
165
+ f.puts(@external_links['rels'][i])
166
+ }
167
+ end
168
+ end
169
+ end
170
+
171
+ #preserves drawings (exactly, no modification allowed)
172
+ unless @drawings.nil?
173
+ 1.upto(@drawings.size) do |i|
174
+ zipfile.get_output_stream(
175
+ File.join('xl','drawings',"vmlDrawing#{i}.vml")) {|f|
176
+ f.puts(@drawings[i])
177
+ }
178
+ end
179
+ end
180
+
181
+ unless @printer_settings.nil?
182
+ 1.upto(@printer_settings.size) do |i|
183
+ zipfile.get_output_stream(
184
+ File.join('xl','printerSettings',"printerSettings#{i}.bin")) {|f|
185
+ f.puts(@printer_settings[i])
186
+ }
187
+ end
188
+ end
189
+
190
+ unless @worksheet_rels.nil?
191
+ 1.upto(@worksheet_rels.size) do |i|
192
+ zipfile.get_output_stream(
193
+ File.join('xl','worksheets','_rels',"sheet#{i}.xml.rels")) {|f|
194
+ f.puts(@worksheet_rels[i])
195
+ }
196
+ end
197
+ end
198
+
199
+ unless @macros.nil?
200
+ zipfile.get_output_stream(File.join('xl','vbaProject.bin')) {|f| f.puts(@macros)}
201
+ end
202
+
203
+ @worksheets.each_with_index do |sheet,i|
204
+ writer = Writer::WorksheetWriter.new(dirpath,self,i)
205
+ zipfile.get_output_stream(File.join('xl','worksheets',"sheet#{i+1}.xml")) {|f| f.puts(writer.write())}
206
+ end
207
+ end
208
+
209
+ FileUtils.cp(zippath,File.join(dirpath,filename+".#{extension}"))
210
+ FileUtils.cp(File.join(dirpath,filename+".#{extension}"),filepath)
211
+ if File.exist?(filepath)
212
+ FileUtils.rm_rf(dirpath)
213
+ end
214
+ return filepath
215
+ end
216
+
217
+ def date_to_num(date)
218
+ return nil if date.nil?
219
+ if @date1904
220
+ compare_date = DateTime.parse('December 31, 1903')
221
+ else
222
+ compare_date = DateTime.parse('December 31, 1899')
223
+ end
224
+ # add one day to compare date for erroneous 1900 leap year compatibility
225
+ date.ajd + 1 - compare_date.ajd
226
+ end
227
+
228
+ def num_to_date(num)
229
+ return nil if num.nil?
230
+ if @date1904
231
+ compare_date = DateTime.parse('December 31, 1903')
232
+ else
233
+ compare_date = DateTime.parse('December 31, 1899')
234
+ end
235
+ # subtract one day to compare date for erroneous 1900 leap year compatibility
236
+ compare_date - 1 + num
237
+ end
238
+
239
+ def date_num_fmt?(num_fmt)
240
+ @num_fmt_date_hash ||= {}
241
+ if @num_fmt_date_hash[num_fmt].nil?
242
+ @num_fmt_date_hash[num_fmt] = is_date_format?(num_fmt)
243
+ end
244
+ return @num_fmt_date_hash[num_fmt]
245
+ end
246
+
247
+ def is_date_format?(num_fmt)
248
+ skip_chars = ['$', '-', '+', '/', '(', ')', ':', ' ']
249
+ num_chars = ['0', '#', '?']
250
+ non_date_formats = ['0.00E+00', '##0.0E+0', 'General', 'GENERAL', 'general', '@']
251
+ date_chars = ['y','m','d','h','s']
252
+
253
+ state = 0
254
+ s = ''
255
+ num_fmt.split(//).each do |c|
256
+ if state == 0
257
+ if c == '"'
258
+ state = 1
259
+ elsif ['\\', '_', '*'].include?(c)
260
+ state = 2
261
+ elsif skip_chars.include?(c)
262
+ next
263
+ else
264
+ s << c
265
+ end
266
+ elsif state == 1
267
+ if c == '"'
268
+ state = 0
269
+ end
270
+ elsif state == 2
271
+ state = 0
272
+ end
273
+ end
274
+ s.gsub!(/\[[^\]]*\]/, '')
275
+ if non_date_formats.include?(s)
276
+ return false
277
+ end
278
+ separator = ';'
279
+ got_sep = 0
280
+ date_count = 0
281
+ num_count = 0
282
+ s.split(//).each do |c|
283
+ if date_chars.include?(c)
284
+ date_count += 1
285
+ elsif num_chars.include?(c)
286
+ num_count += 1
287
+ elsif c == separator
288
+ got_sep = 1
289
+ end
290
+ end
291
+ if date_count > 0 && num_count == 0
292
+ return true
293
+ elsif num_count > 0 && date_count == 0
294
+ return false
295
+ elsif date_count
296
+ # ambiguous result
297
+ elsif got_sep == 0
298
+ # constant result
299
+ end
300
+ return date_count > num_count
301
+ end
302
+
303
+ #gets style object from style array given index
304
+ def get_style(style_index)
305
+ if !@cell_xfs[:xf].is_a?Array
306
+ @cell_xfs[:xf] = [@cell_xfs[:xf]]
307
+ end
308
+
309
+ xf_obj = @cell_xfs[:xf]
310
+ if xf_obj.is_a?Array
311
+ xf_obj = xf_obj[Integer(style_index)]
312
+ end
313
+ xf_obj
314
+ end
315
+
316
+ #gets attributes of above style object
317
+ #necessary because can take the form of hash or array,
318
+ #based on odd behavior of Nokogiri
319
+ def get_style_attributes(xf_obj)
320
+ if xf_obj.is_a?Array
321
+ xf = xf_obj[1]
322
+ else
323
+ xf = xf_obj[:attributes]
324
+ end
325
+ end
326
+
327
+ def get_fill_color(xf_attributes)
328
+ if @fills[xf_attributes[:fillId]].nil? || @fills[xf_attributes[:fillId]][:fill].nil? || @fills[xf_attributes[:fillId]][:fill][:patternFill].nil? || @fills[xf_attributes[:fillId]][:fill][:patternFill][:fgColor].nil?
329
+ 'ffffff' #white
330
+ else
331
+ @fills[xf_attributes[:fillId]][:fill][:patternFill][:fgColor][:attributes][:rgb]
332
+ end
333
+ end
334
+
335
+
336
+ private
337
+
338
+ # Do not change. Excel requires that some of these styles be default,
339
+ # and will simply assume that the 0 and 1 indexed fonts are the default values.
340
+ def fill_styles()
341
+ @fonts = {
342
+ '0' => {
343
+ :font => {
344
+ :sz => { :attributes => { :val => 10 } },
345
+ :name => { :attributes => { :val => "Verdana" } }
346
+ },
347
+ :count=>1
348
+ },
349
+ '1' => {
350
+ :font => {
351
+ :sz => { :attributes => { :val => 8 } },
352
+ :name => { :attributes => { :val => "Verdana" } }
353
+ },
354
+ :count=>0
355
+ }
356
+ }
357
+
358
+ @fills = {
359
+ '0' => {
360
+ :fill => {
361
+ :patternFill => { :attributes => { :patternType => "none" } }
362
+ },
363
+ :count=>1} ,
364
+ '1' => {
365
+ :fill => {
366
+ :patternFill => { :attributes => { :patternType => "gray125" } }
367
+ },
368
+ :count=>0
369
+ }
370
+ }
371
+
372
+ @borders = {
373
+ '0' => {
374
+ :border => {
375
+ :left => { },
376
+ :right => { },
377
+ :top => { },
378
+ :bottom => { },
379
+ :diagonal => { }
380
+ },
381
+ :count => 1 #count = how many styles reference it
382
+ }
383
+ }
384
+
385
+ @cell_style_xfs = {
386
+ :attributes => {
387
+ :count => 1
388
+ },
389
+ :xf => {
390
+ :attributes => { :numFmtId => 0, :fontId => 0, :fillId => 0, :borderId => 0 }
391
+ }
392
+ }
393
+ @cell_xfs = {
394
+ :attributes => {
395
+ :count => 1
396
+ },
397
+ :xf => {
398
+ :attributes => { :numFmtId => 0, :fontId => 0, :fillId => 0, :borderId => 0, :xfId => 0 }
399
+ }
400
+ }
401
+ @cell_styles = {
402
+ :cellStyle => {
403
+ :attributes => { :builtinId=>0, :name=>"Normal", :xfId=>0 }
404
+ },
405
+ :attributes => { :count => 1 }
406
+ }
407
+ end
408
+
409
+
410
+ #fills shared strings hash, contains each unique string
411
+ def fill_shared_strings()
412
+ if @shared_strings.nil?
413
+ string_hash = {}
414
+ string_index = 0
415
+ @num_strings = 0
416
+ #fill hash for shared strings
417
+ @worksheets.each do |sheet|
418
+ unless sheet.nil?
419
+ sheet.sheet_data.each do |row|
420
+ row.each do |cell|
421
+ unless cell.nil? || cell.value.nil?
422
+ #if string not already seen, add it to hash
423
+ if cell.datatype == 's'
424
+ if string_hash[cell.value.to_s].nil?
425
+ string_hash[string_index]=cell.value.to_s
426
+ string_hash[cell.value.to_s]=string_index
427
+ string_index += 1
428
+ end
429
+ @num_strings += 1
430
+ end
431
+ end
432
+ end
433
+ end
434
+ end
435
+ end
436
+
437
+ if string_hash.empty?
438
+ @shared_strings = nil
439
+ else
440
+ @shared_strings = string_hash
441
+ @size = string_index
442
+ end
443
+ end
444
+ end
445
+
446
+ def validate_before_write
447
+ ## TODO CHECK IF STYLE IS OK if not raise
448
+ end
449
+ end
450
+ end