roo 1.2.3 → 1.3.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +1,17 @@
1
- README for roo
2
- ==============
1
+ # README for Roo
3
2
 
4
- Installation:
3
+ This is now the official roo repository and I'll be making a release on RubyForge in the next few weeks.
5
4
 
6
- sudo gem install roo
7
5
 
8
- Usage:
6
+ ## Installation
7
+
8
+ # Run the following if you haven't done so before:
9
+ gem sources -a http://gems.github.com/
10
+
11
+ # Install the gem:
12
+ sudo gem install hmcgowan-roo
13
+
14
+ ## Usage:
9
15
 
10
16
  require 'rubygems'
11
17
  require 'roo'
@@ -1,16 +1,33 @@
1
- require 'rubygems'
2
- gem 'parseexcel', '>= 0.5.2'
3
- require 'parseexcel'
4
- CHARGUESS = false
5
- require 'charguess' if CHARGUESS
1
+ require 'spreadsheet'
2
+ CHARGUESS = begin
3
+ require 'charguess'
4
+ true
5
+ rescue LoadError => e
6
+ false
7
+ end
6
8
 
7
- module Spreadsheet # :nodoc
8
- module ParseExcel
9
- class Worksheet
10
- include Enumerable
11
- attr_reader :min_row, :max_row, :min_col, :max_col
12
- end
9
+ # ruby-spreadsheet has a font object so we're extending it
10
+ # with our own functionality but still providing full access
11
+ # to the user for other font information
12
+ module ExcelFontExtensions
13
+ def bold?(*args)
14
+ #From ruby-spreadsheet doc: 100 <= weight <= 1000, bold => 700, normal => 400
15
+ case weight
16
+ when 700
17
+ true
18
+ else
19
+ false
20
+ end
21
+ end
22
+
23
+ def italic?
24
+ italic
13
25
  end
26
+
27
+ def underline?
28
+ underline != :none
29
+ end
30
+
14
31
  end
15
32
 
16
33
  # Class for handling Excel-Spreadsheets
@@ -37,7 +54,7 @@ class Excel < GenericSpreadsheet
37
54
  unless File.file?(@filename)
38
55
  raise IOError, "file #{@filename} does not exist"
39
56
  end
40
- @workbook = Spreadsheet::ParseExcel.parse(filename)
57
+ @workbook = Spreadsheet.open(filename)
41
58
  @default_sheet = nil
42
59
  # no need to set default_sheet if there is only one sheet in the document
43
60
  if self.sheets.size == 1
@@ -57,25 +74,14 @@ class Excel < GenericSpreadsheet
57
74
  @last_column = Hash.new
58
75
  @header_line = 1
59
76
  @cells_read = Hash.new
77
+ @fonts = Hash.new
60
78
  end
61
79
 
62
80
  # returns an array of sheet names in the spreadsheet
63
81
  def sheets
64
82
  result = []
65
- #0.upto(@workbook.worksheets.size - 1) do |i| # spreadsheet
66
- 0.upto(@workbook.sheet_count - 1) do |i| # parseexcel
67
- # TODO: is there a better way to do conversion?
68
- if CHARGUESS
69
- encoding = CharGuess::guess(@workbook.worksheet(i).name)
70
- encoding = 'unicode' unless encoding
71
-
72
-
73
- result << Iconv.new('utf-8',encoding).iconv(
74
- @workbook.worksheet(i).name
75
- )
76
- else
77
- result << platform_specific_iconv(@workbook.worksheet(i).name)
78
- end
83
+ @workbook.worksheets.each do |worksheet|
84
+ result << normalize_string(worksheet.name)
79
85
  end
80
86
  return result
81
87
  end
@@ -169,6 +175,14 @@ class Excel < GenericSpreadsheet
169
175
  raise EXCEL_NO_FORMULAS
170
176
  end
171
177
 
178
+ # Given a cell, return the cell's font
179
+ def font(row, col, sheet=nil)
180
+ sheet = @default_sheet unless sheet
181
+ read_cells(sheet) unless @cells_read[sheet]
182
+ row,col = normalize(row,col)
183
+ @fonts[sheet][[row,col]]
184
+ end
185
+
172
186
  # shows the internal representation of all cells
173
187
  # mainly for debugging purposes
174
188
  def to_s(sheet=nil)
@@ -218,14 +232,10 @@ class Excel < GenericSpreadsheet
218
232
  # converts name of a sheet to index (0,1,2,..)
219
233
  def sheet_no(name)
220
234
  return name-1 if name.kind_of?(Fixnum)
221
- 0.upto(@workbook.sheet_count - 1) do |i|
222
- #0.upto(@workbook.worksheets.size - 1) do |i|
223
- # TODO: is there a better way to do conversion?
224
- return i if name == platform_specific_iconv(
225
- @workbook.worksheet(i).name)
226
- #Iconv.new('utf-8','unicode').iconv(
227
- # @workbook.worksheet(i).name
228
- # )
235
+ i = 0
236
+ @workbook.worksheets.each do |worksheet|
237
+ return i if name == normalize_string(worksheet.name)
238
+ i += 1
229
239
  end
230
240
  raise StandardError, "sheet '#{name}' not found"
231
241
  end
@@ -249,7 +259,16 @@ class Excel < GenericSpreadsheet
249
259
  }
250
260
  ! content
251
261
  end
252
-
262
+
263
+ def normalize_string(value)
264
+ value = every_second_null?(value) ? remove_every_second_null(value) : value
265
+ if CHARGUESS && encoding = CharGuess::guess(value)
266
+ Iconv.new('utf-8', encoding)
267
+ else
268
+ platform_specific_iconv(value)
269
+ end
270
+ end
271
+
253
272
  def platform_specific_iconv(value)
254
273
  case RUBY_PLATFORM.downcase
255
274
  when /darwin/
@@ -291,19 +310,22 @@ class Excel < GenericSpreadsheet
291
310
  end
292
311
 
293
312
  # helper function to set the internal representation of cells
294
- def set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v)
313
+ def set_cell_values(sheet,row,col,i,v,vt,formula,tr,font)
295
314
  #key = "#{y},#{x+i}"
296
- key = [y,x+i]
315
+ key = [row,col+i]
297
316
  @cell_type[sheet] = {} unless @cell_type[sheet]
298
317
  @cell_type[sheet][key] = vt
299
318
  @formula[sheet] = {} unless @formula[sheet]
300
319
  @formula[sheet][key] = formula if formula
301
320
  @cell[sheet] = {} unless @cell[sheet]
321
+ @fonts[sheet] = {} unless @fonts[sheet]
322
+ @fonts[sheet][key] = font
323
+
302
324
  case vt # @cell_type[sheet][key]
303
325
  when :float
304
326
  @cell[sheet][key] = v.to_f
305
327
  when :string
306
- @cell[sheet][key] = str_v
328
+ @cell[sheet][key] = v
307
329
  when :date
308
330
  @cell[sheet][key] = v
309
331
  when :datetime
@@ -328,63 +350,90 @@ class Excel < GenericSpreadsheet
328
350
  end
329
351
 
330
352
  worksheet = @workbook.worksheet(sheet_no(sheet))
331
- skip = 0
332
- x =1
333
- y=1
334
- i=0
335
- worksheet.each(skip) { |row_par|
336
- if row_par
337
- x =1
338
- row_par.each do # |void|
339
- cell = row_par.at(x-1)
340
- if cell
341
- case cell.type
342
- when :numeric
343
- vt = :float
344
- v = cell.to_f
345
- when :text
346
- vt = :string
347
- str_v = cell.to_s('utf-8')
348
- when :date
349
- if cell.to_s.to_f < 1.0
350
- vt = :time
351
- f = cell.to_s.to_f*24.0*60.0*60.0
352
- secs = f.round
353
- h = (secs / 3600.0).floor
354
- secs = secs - 3600*h
355
- m = (secs / 60.0).floor
356
- secs = secs - 60*m
357
- s = secs
358
- v = h*3600+m*60+s
359
- else
360
- if cell.datetime.hour != 0 or
361
- cell.datetime.min != 0 or
362
- cell.datetime.sec != 0 or
363
- cell.datetime.msec != 0
364
- vt = :datetime
365
- v = cell.datetime
366
- else
367
- vt = :date
368
- v = cell.date
369
- v = sprintf("%04d-%02d-%02d",v.year,v.month,v.day)
370
- end
371
- end
372
- else
373
- vt = cell.type.to_s.downcase.to_sym
374
- v = nil
375
- end # case
376
- formula = tr = nil #TODO:???
377
- set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v)
378
- end # if cell
379
-
380
- x += 1
353
+ row_index=1
354
+ worksheet.each(0) do |row|
355
+ (0..row.size).each do |cell_index|
356
+ cell = row.at(cell_index)
357
+ next if cell.nil? #skip empty cells
358
+ next if cell.class == Spreadsheet::Formula
359
+ if date_or_time?(row, cell_index)
360
+ vt, v = read_cell_date_or_time(row, cell_index)
361
+ else
362
+ vt, v = read_cell(row, cell_index)
381
363
  end
382
- end
383
- y += 1
384
- }
364
+ formula = tr = nil #TODO:???
365
+ col_index = cell_index + 1
366
+ font = row.format(cell_index).font
367
+ font.extend(ExcelFontExtensions)
368
+ set_cell_values(sheet,row_index,col_index,0,v,vt,formula,tr,font)
369
+ end #row
370
+ row_index += 1
371
+ end # worksheet
385
372
  @cells_read[sheet] = true
386
373
  end
387
-
374
+
375
+ # Test the cell to see if it's a valid date/time.
376
+ def date_or_time?(row, idx)
377
+ format = row.format(idx)
378
+ if format.date_or_time?
379
+ cell = row.at(idx)
380
+ true if Float(cell) > 0 rescue false
381
+ else
382
+ false
383
+ end
384
+ end
385
+ private :date_or_time?
386
+
387
+ # Read the date-time cell and convert to,
388
+ # the date-time values for Roo
389
+ def read_cell_date_or_time(row, idx)
390
+ cell = row.at(idx).to_s.to_f
391
+ if cell < 1.0
392
+ value_type = :time
393
+ f = cell*24.0*60.0*60.0
394
+ secs = f.round
395
+ h = (secs / 3600.0).floor
396
+ secs = secs - 3600*h
397
+ m = (secs / 60.0).floor
398
+ secs = secs - 60*m
399
+ s = secs
400
+ value = h*3600+m*60+s
401
+ else
402
+ datetime = row.datetime(idx)
403
+ if datetime.hour != 0 or
404
+ datetime.min != 0 or
405
+ datetime.sec != 0
406
+ value_type = :datetime
407
+ value = datetime
408
+ else
409
+ value_type = :date
410
+ value = row.date(idx)
411
+ value = sprintf("%04d-%02d-%02d",value.year,value.month,value.day)
412
+ end
413
+ end
414
+ return value_type, value
415
+ end
416
+ private :read_cell_date_or_time
417
+
418
+ # Read the cell and based on the class,
419
+ # return the values for Roo
420
+ def read_cell(row, idx)
421
+ cell = row.at(idx)
422
+ case cell
423
+ when Float, Integer, Fixnum, Bignum
424
+ value_type = :float
425
+ value = cell.to_f
426
+ when String, TrueClass, FalseClass
427
+ value_type = :string
428
+ value = cell.to_s
429
+ else
430
+ value_type = cell.class.to_s.downcase.to_sym
431
+ value = nil
432
+ end # case
433
+ return value_type, value
434
+ end
435
+ private :read_cell
436
+
388
437
  #TODO: testing only
389
438
  # def inject_null_characters(str)
390
439
  # if str.class != String
@@ -1,6 +1,4 @@
1
-
2
- require 'rubygems'
3
- require 'rexml/document'
1
+ require 'xml'
4
2
  require 'fileutils'
5
3
  require 'zip/zipfilesystem'
6
4
  require 'date'
@@ -102,26 +100,27 @@ class Excelx < GenericSpreadsheet
102
100
  @file_nr = @@nr
103
101
  extract_content(@filename)
104
102
  file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_workbook.xml"))
105
- @workbook_doc = REXML::Document.new file
103
+ @workbook_doc = XML::Parser.io(file).parse
106
104
  file.close
107
105
  @shared_table = []
108
106
  if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
109
107
  file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
110
- @sharedstring_doc = REXML::Document.new file
108
+ @sharedstring_doc = XML::Parser.io(file).parse
111
109
  file.close
112
110
  read_shared_strings(@sharedstring_doc)
113
111
  end
114
112
  @styles_table = []
113
+ @style_definitions = Array.new { |h,k| h[k] = {} }
115
114
  if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
116
115
  file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
117
- @styles_doc = REXML::Document.new file
116
+ @styles_doc = XML::Parser.io(file).parse
118
117
  file.close
119
118
  read_styles(@styles_doc)
120
119
  end
121
120
  @sheet_doc = []
122
121
  @sheet_files.each_with_index do |item, i|
123
122
  file = File.new(item)
124
- @sheet_doc[i] = REXML::Document.new file
123
+ @sheet_doc[i] = XML::Parser.io(file).parse
125
124
  file.close
126
125
  end
127
126
  ensure
@@ -163,7 +162,6 @@ class Excelx < GenericSpreadsheet
163
162
  yyyy,mm,dd = date_part.split('-')
164
163
  hh,mi,ss = time_part.split(':')
165
164
  return DateTime.civil(yyyy.to_i,mm.to_i,dd.to_i,hh.to_i,mi.to_i,ss.to_i)
166
-
167
165
  end
168
166
  @cell[sheet][[row,col]]
169
167
  end
@@ -189,6 +187,33 @@ class Excelx < GenericSpreadsheet
189
187
  row,col = normalize(row,col)
190
188
  formula(row,col) != nil
191
189
  end
190
+
191
+ class Font
192
+ attr_accessor :bold, :italic, :underline
193
+
194
+ def bold?
195
+ @bold == true
196
+ end
197
+
198
+ def italic?
199
+ @italic == true
200
+ end
201
+
202
+ def underline?
203
+ @underline == true
204
+ end
205
+ end
206
+
207
+ # Given a cell, return the cell's style
208
+ def font(row, col, sheet=nil)
209
+ sheet = @default_sheet unless sheet
210
+ read_cells(sheet) unless @cells_read[sheet]
211
+ row,col = normalize(row,col)
212
+ s_attribute = @s_attribute[sheet][[row,col]]
213
+ s_attribute ||= 0
214
+ s_attribute = s_attribute.to_i
215
+ @style_definitions[s_attribute]
216
+ end
192
217
 
193
218
  # set a cell to a certain value
194
219
  # (this will not be saved back to the spreadsheet file!)
@@ -260,18 +285,11 @@ class Excelx < GenericSpreadsheet
260
285
  # returns an array of sheet names in the spreadsheet
261
286
  def sheets
262
287
  return_sheets = []
263
- @workbook_doc.each_element do |workbook|
264
- workbook.each_element do |el|
265
- if el.name == "sheets"
266
- el.each_element do |sheet|
267
- return_sheets << sheet.attributes['name']
268
- end
269
- end
270
- end
288
+ @workbook_doc.find("//*[local-name()='sheet']").each do |sheet|
289
+ return_sheets << sheet.attributes.to_h['name']
271
290
  end
272
291
  return_sheets
273
292
  end
274
-
275
293
  # shows the internal representation of all cells
276
294
  # for debugging purposes
277
295
  def to_s(sheet=nil)
@@ -376,82 +394,62 @@ class Excelx < GenericSpreadsheet
376
394
  raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
377
395
  raise RangeError unless self.sheets.include? sheet
378
396
  n = self.sheets.index(sheet)
379
- @sheet_doc[n].each_element do |worksheet|
380
- worksheet.each_element do |elem|
381
- if elem.name == 'sheetData'
382
- elem.each_element do |sheetdata|
383
- if sheetdata.name == 'row'
384
- sheetdata.each_element do |row|
385
- if row.name == 'c'
386
- if row.attributes['t'] == 's'
387
- tmp_type = :shared
388
- else
389
- s_attribute = row.attributes['s']
390
- format = attribute2format(s_attribute)
391
- tmp_type = format2type(format)
392
- end
393
- formula = nil
394
- row.each_element do |cell|
395
- # puts "cell.name: #{cell.name}" if cell.text.include? "22606.5120"
396
- # puts "cell.text: #{cell.text}" if cell.text.include? "22606.5120"
397
- if cell.name == 'f'
398
- formula = cell.text
399
- end
400
- if cell.name == 'v'
401
- #puts "tmp_type: #{tmp_type}" if cell.text.include? "22606.5120"
402
- #puts cell.name
403
- if tmp_type == :time or tmp_type == :datetime #2008-07-26
404
- #p cell.text
405
- # p cell.text.to_f if cell.text.include? "22606.5120"
406
- if cell.text.to_f >= 1.0 # 2008-07-26
407
- # puts ">= 1.0" if cell.text.include? "22606.5120"
408
- # puts "cell.text.to_f: #{cell.text.to_f}" if cell.text.include? "22606.5120"
409
- #puts "cell.text.to_f.floor: #{cell.text.to_f.floor}" if cell.text.include? "22606.5120"
410
- if (cell.text.to_f - cell.text.to_f.floor).abs > 0.000001 #TODO:
411
- # puts "abs ist groesser" if cell.text.include? "22606.5120"
412
- # @cell[sheet][key] = DateTime.parse(tr.attributes['date-value'])
413
- tmp_type = :datetime
414
-
415
- else
416
- #puts ":date"
417
- tmp_type = :date # 2008-07-26
418
- end
419
- else
420
- #puts "<1.0"
421
- end # 2008-07-26
422
- end # 2008-07-26
423
- excelx_type = [:numeric_or_formula,format]
424
- excelx_value = cell.text
425
- if tmp_type == :shared
426
- vt = :string
427
- str_v = @shared_table[cell.text.to_i]
428
- excelx_type = :string
429
- elsif tmp_type == :date
430
- vt = :date
431
- v = cell.text
432
- elsif tmp_type == :time
433
- vt = :time
434
- v = cell.text
435
- elsif tmp_type == :datetime
436
- vt = :datetime
437
- v = cell.text
438
- elsif tmp_type == :formula
439
- vt = :formula
440
- v = cell.text.to_f #TODO: !!!!
441
- else
442
- vt = :float
443
- v = cell.text
444
- end
445
- #puts "vt: #{vt}" if cell.text.include? "22606.5120"
446
- x,y = split_coordinate(row.attributes['r'])
447
- tr=nil #TODO: ???s
448
- set_cell_values(sheet,x,y,0,v,vt,formula,tr,str_v,excelx_type,excelx_value,s_attribute)
449
- end
450
- end
451
- end
397
+ @sheet_doc[n].find("//*[local-name()='c']").each do |c|
398
+ s_attribute = c.attributes.to_h['s'].to_i # should be here
399
+ if (c.attributes.to_h['t'] == 's')
400
+ tmp_type = :shared
401
+ elsif (c.attributes.to_h['t'] == 'b')
402
+ tmp_type = :boolean
403
+ else
404
+ # s_attribute = c.attributes.to_h['s'].to_i # was here
405
+ format = attribute2format(s_attribute)
406
+ tmp_type = format2type(format)
407
+ end
408
+ formula = nil
409
+ c.each_element do |cell|
410
+ if cell.name == 'f'
411
+ formula = cell.content
412
+ end
413
+ if cell.name == 'v'
414
+ if tmp_type == :time or tmp_type == :datetime
415
+ if cell.content.to_f >= 1.0
416
+ if (cell.content.to_f - cell.content.to_f.floor).abs > 0.000001
417
+ tmp_type = :datetime
418
+ else
419
+ tmp_type = :date
452
420
  end
453
- end
421
+ else
422
+ end
423
+ end
424
+ excelx_type = [:numeric_or_formula,format]
425
+ excelx_value = cell.content
426
+ if tmp_type == :shared
427
+ vt = :string
428
+ str_v = @shared_table[cell.content.to_i]
429
+ excelx_type = :string
430
+ elsif tmp_type == :boolean
431
+ vt = :boolean
432
+ cell.content.to_i == 1 ? v = 'TRUE' : v = 'FALSE'
433
+ elsif tmp_type == :date
434
+ vt = :date
435
+ v = cell.content
436
+ elsif tmp_type == :time
437
+ vt = :time
438
+ v = cell.content
439
+ elsif tmp_type == :datetime
440
+ vt = :datetime
441
+ v = cell.content
442
+ elsif tmp_type == :formula
443
+ vt = :formula
444
+ v = cell.content.to_f #TODO: !!!!
445
+ else
446
+ vt = :float
447
+ v = cell.content
454
448
  end
449
+ #puts "vt: #{vt}" if cell.text.include? "22606.5120"
450
+ x,y = split_coordinate(c.attributes.to_h['r'])
451
+ tr=nil #TODO: ???s
452
+ set_cell_values(sheet,x,y,0,v,vt,formula,tr,str_v,excelx_type,excelx_value,s_attribute)
455
453
  end
456
454
  end
457
455
  end
@@ -467,17 +465,9 @@ class Excelx < GenericSpreadsheet
467
465
  def check_default_sheet
468
466
  sheet_found = false
469
467
  raise ArgumentError, "Error: default_sheet not set" if @default_sheet == nil
470
- @workbook_doc.each_element do |workbook|
471
- workbook.each_element do |el|
472
- if el.name == "sheets"
473
- el.each_element do |sheet|
474
- if @default_sheet == sheet.attributes['name']
475
- sheet_found = true
476
- end
477
- end
478
- end
479
- end
480
- end
468
+
469
+ sheet_found = true if sheets.include?(@default_sheet)
470
+
481
471
  if ! sheet_found
482
472
  raise RangeError, "sheet '#{@default_sheet}' not found"
483
473
  end
@@ -537,18 +527,21 @@ class Excelx < GenericSpreadsheet
537
527
 
538
528
  # read the shared strings xml document
539
529
  def read_shared_strings(doc)
540
- doc.each_element do |sst|
541
- if sst.name == 'sst'
542
- sst.each_element do |si|
543
- if si.name == 'si'
544
- si.each_element do |elem|
545
- if elem.name == 't'
546
- @shared_table << elem.text
547
- end
530
+ doc.find("//*[local-name()='si']").each do |si|
531
+ shared_table_entry = ''
532
+ si.each_element do |elem|
533
+ if (elem.name == 'r')
534
+ elem.each_element do |r_elem|
535
+ if (r_elem.name == 't')
536
+ shared_table_entry << r_elem.content
548
537
  end
549
538
  end
550
539
  end
540
+ if (elem.name == 't')
541
+ shared_table_entry = elem.content
542
+ end
551
543
  end
544
+ @shared_table << shared_table_entry
552
545
  end
553
546
  end
554
547
 
@@ -556,28 +549,40 @@ class Excelx < GenericSpreadsheet
556
549
  def read_styles(doc)
557
550
  @numFmts = []
558
551
  @cellXfs = []
559
- doc.each_element do |e1|
560
- if e1.name == "styleSheet"
561
- e1.each_element do |e2|
562
- if e2.name == "numFmts"
563
- e2.each_element do |e3|
564
- if e3.name == 'numFmt'
565
- numFmtId = e3.attributes['numFmtId']
566
- formatCode = e3.attributes['formatCode']
567
- @numFmts << [numFmtId, formatCode]
568
- end
569
- end
570
- elsif e2.name == "cellXfs"
571
- e2.each_element do |e3|
572
- if e3.name == 'xf'
573
- numFmtId = e3.attributes['numFmtId']
574
- @cellXfs << [numFmtId]
552
+ fonts = []
553
+
554
+ doc.find("//*[local-name()='numFmt']").each do |numFmt|
555
+ numFmtId = numFmt.attributes.to_h['numFmtId']
556
+ formatCode = numFmt.attributes.to_h['formatCode']
557
+ @numFmts << [numFmtId, formatCode]
558
+ end
559
+ doc.find("//*[local-name()='fonts']").each do |fonts_el|
560
+ fonts_el.each_element do |font_el|
561
+ if font_el.name == 'font'
562
+ font = Excelx::Font.new
563
+ font_el.each_element do |font_sub_el|
564
+ case font_sub_el.name
565
+ when 'b'
566
+ font.bold = true
567
+ when 'i'
568
+ font.italic = true
569
+ when 'u'
570
+ font.underline = true
575
571
  end
576
- end
577
572
  end
573
+ fonts << font
578
574
  end
579
575
  end
580
576
  end
577
+
578
+ doc.find("//*[local-name()='cellXfs']").each do |xfs|
579
+ xfs.each do |xf|
580
+ numFmtId = xf.attributes.to_h['numFmtId']
581
+ @cellXfs << [numFmtId]
582
+ fontId = xf.attributes.to_h['fontId'].to_i
583
+ @style_definitions << fonts[fontId]
584
+ end
585
+ end
581
586
  end
582
587
 
583
588
  # convert internal excelx attribute to a format