1
1
require 'rubygems'
2
- gem 'parseexcel ' , '>= 0.5.3 '
3
- require 'parseexcel '
2
+ gem 'spreadsheet ' , '>= 0.6.3.1 '
3
+ require 'spreadsheet '
4
4
CHARGUESS = false
5
5
require 'charguess' if CHARGUESS
6
6
@@ -37,7 +37,7 @@ def initialize(filename, packed = nil, file_warning = :error)
37
37
unless File . file? ( @filename )
38
38
raise IOError , "file #{ @filename } does not exist"
39
39
end
40
- @workbook = Spreadsheet :: ParseExcel . parse ( filename )
40
+ @workbook = Spreadsheet . open ( filename )
41
41
@default_sheet = nil
42
42
# no need to set default_sheet if there is only one sheet in the document
43
43
if self . sheets . size == 1
@@ -63,19 +63,18 @@ def initialize(filename, packed = nil, file_warning = :error)
63
63
# returns an array of sheet names in the spreadsheet
64
64
def sheets
65
65
result = [ ]
66
- #0.upto(@workbook.worksheets.size - 1) do |i| # spreadsheet
67
- 0 . upto ( @workbook . sheet_count - 1 ) do |i | # parseexcel
66
+ @workbook . worksheets . each do |worksheet |
68
67
# TODO: is there a better way to do conversion?
69
68
if CHARGUESS
70
- encoding = CharGuess ::guess ( @workbook . worksheet ( i ) . name )
69
+ encoding = CharGuess ::guess ( worksheet . name )
71
70
encoding = 'unicode' unless encoding
72
71
73
72
74
73
result << Iconv . new ( 'utf-8' , encoding ) . iconv (
75
- @workbook . worksheet ( i ) . name
74
+ worksheet . name
76
75
)
77
76
else
78
- result << platform_specific_iconv ( @workbook . worksheet ( i ) . name )
77
+ result << platform_specific_iconv ( worksheet . name )
79
78
end
80
79
end
81
80
return result
@@ -181,17 +180,23 @@ def cell_font(row, col, sheet=nil)
181
180
182
181
# true if the cell style is bold
183
182
def bold? ( *args )
184
- cell_font ( *args ) [ :bold ]
183
+ #From ruby-spreadsheet doc: 100 <= weight <= 1000, bold => 700, normal => 400
184
+ case cell_font ( *args ) . weight
185
+ when 700
186
+ true
187
+ else
188
+ false
189
+ end
185
190
end
186
191
187
192
# true if the cell style is italic
188
193
def italic? ( *args )
189
- cell_font ( *args ) [ : italic]
194
+ cell_font ( *args ) . italic
190
195
end
191
196
192
197
# true if the cell style is underline
193
198
def underline? ( *args )
194
- cell_font ( *args ) [ : underline]
199
+ cell_font ( *args ) . underline != :none
195
200
end
196
201
197
202
# shows the internal representation of all cells
@@ -243,14 +248,15 @@ def get_firsts_lasts(sheet=nil)
243
248
# converts name of a sheet to index (0,1,2,..)
244
249
def sheet_no ( name )
245
250
return name -1 if name . kind_of? ( Fixnum )
246
- 0 . upto ( @workbook . sheet_count - 1 ) do | i |
247
- #0.upto( @workbook.worksheets.size - 1) do |i |
251
+ i = 0
252
+ @workbook . worksheets . each do |worksheet |
248
253
# TODO: is there a better way to do conversion?
249
254
return i if name == platform_specific_iconv (
250
- @workbook . worksheet ( i ) . name )
255
+ worksheet . name )
251
256
#Iconv.new('utf-8','unicode').iconv(
252
257
# @workbook.worksheet(i).name
253
258
# )
259
+ i += 1
254
260
end
255
261
raise StandardError , "sheet '#{ name } ' not found"
256
262
end
@@ -316,9 +322,9 @@ def remove_every_second_null(str)
316
322
end
317
323
318
324
# helper function to set the internal representation of cells
319
- def set_cell_values ( sheet , x , y , i , v , vt , formula , tr , str_v , font )
325
+ def set_cell_values ( sheet , row , col , i , v , vt , formula , tr , font )
320
326
#key = "#{y},#{x+i}"
321
- key = [ y , x +i ]
327
+ key = [ row , col +i ]
322
328
@cell_type [ sheet ] = { } unless @cell_type [ sheet ]
323
329
@cell_type [ sheet ] [ key ] = vt
324
330
@formula [ sheet ] = { } unless @formula [ sheet ]
@@ -331,7 +337,7 @@ def set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v, font)
331
337
when :float
332
338
@cell [ sheet ] [ key ] = v . to_f
333
339
when :string
334
- @cell [ sheet ] [ key ] = str_v
340
+ @cell [ sheet ] [ key ] = v
335
341
when :date
336
342
@cell [ sheet ] [ key ] = v
337
343
when :datetime
@@ -356,67 +362,89 @@ def read_cells(sheet=nil)
356
362
end
357
363
358
364
worksheet = @workbook . worksheet ( sheet_no ( sheet ) )
359
- skip = 0
360
- x = 1
361
- y = 1
362
- i = 0
363
- worksheet . each ( skip ) { |row_par |
364
- if row_par
365
- x = 1
366
- row_par . each do # |void|
367
- cell = row_par . at ( x -1 )
368
- if cell
369
- case cell . type
370
- when :numeric
371
- vt = :float
372
- v = cell . to_f
373
- when :text
374
- vt = :string
375
- if cell . to_s . downcase == 'true'
376
- str_v = cell . to_s
377
- else
378
- str_v = cell . to_s ( 'utf-8' )
379
- end
380
- when :date
381
- if cell . to_s . to_f < 1.0
382
- vt = :time
383
- f = cell . to_s . to_f *24.0 *60.0 *60.0
384
- secs = f . round
385
- h = ( secs / 3600.0 ) . floor
386
- secs = secs - 3600 *h
387
- m = ( secs / 60.0 ) . floor
388
- secs = secs - 60 *m
389
- s = secs
390
- v = h *3600 +m *60 +s
391
- else
392
- if cell . datetime . hour != 0 or
393
- cell . datetime . min != 0 or
394
- cell . datetime . sec != 0 or
395
- cell . datetime . msec != 0
396
- vt = :datetime
397
- v = cell . datetime
398
- else
399
- vt = :date
400
- v = cell . date
401
- v = sprintf ( "%04d-%02d-%02d" , v . year , v . month , v . day )
402
- end
403
- end
404
- else
405
- vt = cell . type . to_s . downcase . to_sym
406
- v = nil
407
- end # case
408
- formula = tr = nil #TODO:???
409
- set_cell_values ( sheet , x , y , i , v , vt , formula , tr , str_v , cell . font )
410
- end # if cell
411
-
412
- x += 1
365
+ row_index = 1
366
+ worksheet . each ( 0 ) do |row |
367
+ ( 0 ..row . size ) . each do |cell_index |
368
+ cell = row . at ( cell_index )
369
+ next if cell . nil? #skip empty cells
370
+ next if cell . class == Spreadsheet ::Formula
371
+ if date_or_time? ( row , cell_index )
372
+ vt , v = read_cell_date_or_time ( row , cell_index )
373
+ else
374
+ vt , v = read_cell ( row , cell_index )
413
375
end
414
- end
415
- y += 1
416
- }
376
+ formula = tr = nil #TODO:???
377
+ col_index = cell_index + 1
378
+ font = row . format ( cell_index ) . font
379
+ #puts [row_index, col_index].inspect
380
+ #puts vt, v
381
+ set_cell_values ( sheet , row_index , col_index , 0 , v , vt , formula , tr , font )
382
+ end #row
383
+ row_index += 1
384
+ end # worksheets
417
385
@cells_read [ sheet ] = true
418
386
end
419
-
387
+
388
+ # Test the cell to see if it's a valid date/time.
389
+ def date_or_time? ( row , idx )
390
+ format = row . format ( idx )
391
+ if format . date_or_time?
392
+ cell = row . at ( idx )
393
+ cell . to_s . to_f > 0 ? true : false # cell value must be numeric
394
+ else
395
+ false
396
+ end
397
+ end
398
+ private :date_or_time?
399
+
400
+ def read_cell_date_or_time ( row , idx )
401
+ cell = row . at ( idx ) . to_s . to_f
402
+ if cell < 1.0
403
+ value_type = :time
404
+ f = cell *24.0 *60.0 *60.0
405
+ secs = f . round
406
+ h = ( secs / 3600.0 ) . floor
407
+ secs = secs - 3600 *h
408
+ m = ( secs / 60.0 ) . floor
409
+ secs = secs - 60 *m
410
+ s = secs
411
+ value = h *3600 +m *60 +s
412
+ else
413
+ datetime = row . datetime ( idx )
414
+ if datetime . hour != 0 or
415
+ datetime . min != 0 or
416
+ datetime . sec != 0
417
+ value_type = :datetime
418
+ value = datetime
419
+ else
420
+ value_type = :date
421
+ value = row . date ( idx )
422
+ value = sprintf ( "%04d-%02d-%02d" , value . year , value . month , value . day )
423
+ end
424
+ end
425
+ return value_type , value
426
+ end
427
+ private :read_cell_date_or_time
428
+
429
+ # Read the cell and based on the class,
430
+ # return the value and value types for Roo
431
+ def read_cell ( row , idx )
432
+ cell = row . at ( idx )
433
+ case cell
434
+ when Float , Integer , Fixnum , Bignum
435
+ value_type = :float
436
+ value = cell . to_f
437
+ when String , TrueClass , FalseClass
438
+ value_type = :string
439
+ value = cell . to_s
440
+ else
441
+ value_type = cell . class . to_s . downcase . to_sym
442
+ value = nil
443
+ end # case
444
+ return value_type , value
445
+ end
446
+ private :read_cell
447
+
420
448
#TODO: testing only
421
449
# def inject_null_characters(str)
422
450
# if str.class != String
0 commit comments