listen360-rubyXL 1.2.10.1

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.
@@ -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