roo 1.2.0 → 1.2.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.
data/History.txt CHANGED
@@ -1,3 +1,6 @@
1
+ == 1.2.1 2008-11-13
2
+ * 1 enhancement
3
+ * added celltype :datetime in Openoffice and Excel
1
4
  == 1.2.0 2008-08-24
2
5
  * 3 major enhancements
3
6
  * Excelx: improved the detection of cell type and conversion into roo types
data/Manifest.txt CHANGED
@@ -58,6 +58,8 @@ test/ric.ods
58
58
  test/bug-row-column-fixnum-float.xls
59
59
  test/emptysheets.ods
60
60
  test/emptysheets.xls
61
+ test/datetime.ods
62
+ test/datetime.xls
61
63
  website/index.html
62
64
  website/index.txt
63
65
  website/javascripts/rounded_corners_lite.inc.js
data/lib/roo/excel.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'rubygems'
2
2
  gem 'parseexcel', '>= 0.5.2'
3
3
  require 'parseexcel'
4
- CHARGUESS=false
4
+ CHARGUESS = false
5
5
  require 'charguess' if CHARGUESS
6
6
 
7
7
  module Spreadsheet # :nodoc
@@ -29,6 +29,7 @@ class Excel < GenericSpreadsheet
29
29
  FileUtils::mkdir(@tmpdir)
30
30
  end
31
31
  filename = open_from_uri(filename) if filename[0,7] == "http://"
32
+ filename = open_from_stream(filename[7..-1]) if filename[0,7] == "stream:"
32
33
  filename = unzip(filename) if packed and packed == :zip
33
34
  begin
34
35
  file_type_check(filename,'.xls','an Excel')
@@ -61,7 +62,8 @@ class Excel < GenericSpreadsheet
61
62
  # returns an array of sheet names in the spreadsheet
62
63
  def sheets
63
64
  result = []
64
- 0.upto(@workbook.sheet_count - 1) do |i|
65
+ #0.upto(@workbook.worksheets.size - 1) do |i| # spreadsheet
66
+ 0.upto(@workbook.sheet_count - 1) do |i| # parseexcel
65
67
  # TODO: is there a better way to do conversion?
66
68
  if CHARGUESS
67
69
  encoding = CharGuess::guess(@workbook.worksheet(i).name)
@@ -81,13 +83,15 @@ class Excel < GenericSpreadsheet
81
83
  # returns the content of a cell. The upper left corner is (1,1) or ('A',1)
82
84
  def cell(row,col,sheet=nil)
83
85
  sheet = @default_sheet unless sheet
86
+ raise ArgumentError unless sheet
84
87
  read_cells(sheet) unless @cells_read[sheet]
88
+ raise "should be read" unless @cells_read[sheet]
85
89
  row,col = normalize(row,col)
86
90
  if celltype(row,col,sheet) == :date
87
- yyyy,mm,dd = @cell[sheet]["#{row},#{col}"].split('-')
91
+ yyyy,mm,dd = @cell[sheet][[row,col]].split('-')
88
92
  return Date.new(yyyy.to_i,mm.to_i,dd.to_i)
89
93
  end
90
- return @cell[sheet]["#{row},#{col}"]
94
+ return @cell[sheet][[row,col]]
91
95
  end
92
96
 
93
97
  # returns the type of a cell:
@@ -97,14 +101,20 @@ class Excel < GenericSpreadsheet
97
101
  # * :percentage
98
102
  # * :formula
99
103
  # * :time
104
+ # * :datetime
100
105
  def celltype(row,col,sheet=nil)
101
106
  sheet = @default_sheet unless sheet
102
107
  read_cells(sheet) unless @cells_read[sheet]
103
108
  row,col = normalize(row,col)
104
- if @formula[sheet]["#{row},#{col}"]
105
- return :formula
106
- else
107
- @cell_type[sheet]["#{row},#{col}"]
109
+ begin
110
+ if @formula[sheet][[row,col]]
111
+ return :formula
112
+ else
113
+ @cell_type[sheet][[row,col]]
114
+ end
115
+ rescue
116
+ puts "Error in sheet #{sheet}, row #{row}, col #{col}"
117
+ raise
108
118
  end
109
119
  end
110
120
 
@@ -155,86 +165,45 @@ class Excel < GenericSpreadsheet
155
165
  raise EXCEL_NO_FORMULAS
156
166
  end
157
167
 
158
- private
159
-
160
- # determine the first and last boundaries
161
- def get_firsts_lasts_parseexcel(sheet=nil)
168
+ # shows the internal representation of all cells
169
+ # mainly for debugging purposes
170
+ def to_s(sheet=nil)
162
171
  sheet = @default_sheet unless sheet
163
- fr = fc = 999_999
164
- lr = lc = -999_999
165
- worksheet = @workbook.worksheet(sheet_no(sheet))
166
- unless worksheet.min_row
167
- fr = nil
168
- else
169
- fr = worksheet.min_row + 1
170
- end
171
- unless worksheet.max_row
172
- lr = nil
173
- else
174
- lr = worksheet.max_row + 1
175
- end
176
- unless worksheet.min_col
177
- fc = nil
178
- else
179
- fc = worksheet.min_col + 1
180
- end
181
- unless worksheet.max_col
182
- lc = nil
183
- else
184
- lc = worksheet.max_col + 1
185
- end
186
- if lr
187
- # 2007-11-05 BEGIN
188
- # parsexcel liefert (mir unverstaendlich) eine Zeile als letzte Zeile
189
- # zurueck, die aber leer ist. Deshalb Korrekturfunktion, die wirklich
190
- # die letzte nicht leere Zeile liefert.
191
- # 2008-07-23 meine Loesung funtionierte auch noch nicht unter allen
192
- # Umstaenden row() == nil ergaenzt
193
- while row(lr,sheet) == nil || empty_row?(row(lr,sheet))
194
- lr -= 1
195
- end
196
- end
197
- # 2007-11-05 END
198
-
199
- if lc
200
- letzte_spalte_leer = true
201
- until ! letzte_spalte_leer
202
- worksheet.each(0) {|reihe|
203
- if reihe
204
- cell = reihe.at(lc-1)
205
- if cell
206
- case cell.type
207
- when :numeric, :date
208
- letzte_spalte_leer = false
209
- when :text
210
- letzte_spalte_leer = false if cell.to_s != ""
211
- end
212
- end
213
- end
214
- }
215
- lc -= 1 if letzte_spalte_leer
216
- #puts "letzte Spalte auf #{lc} verringert" if letzte_spalte_leer
217
- end
218
- end
219
-
220
- return fr, lr, fc, lc
172
+ read_cells(sheet) unless @cells_read[sheet]
173
+ @cell[sheet].inspect
221
174
  end
222
175
 
176
+ private
223
177
  # determine the first and last boundaries
224
178
  def get_firsts_lasts(sheet=nil)
225
- fr,lr,fc,lc = get_firsts_lasts_parseexcel(sheet)
226
- if lr
227
- # 2007-11-05 BEGIN
228
- # parsexcel liefert (mir unverstaendlich) eine Zeile als letzte Zeile
229
- # zurueck, die aber leer ist. Deshalb Korrekturfunktion, die wirklich
230
- # die letzte nicht leere Zeile liefert.
231
- # 2008-07-23 meine Loesung funtionierte auch noch nicht unter allen
232
- # Umstaenden row() == nil ergaenzt
233
- while row(lr,sheet) == nil || empty_row?(row(lr,sheet))
234
- lr -= 1
235
- end
179
+
180
+ # 2008-09-14 BEGINf
181
+ fr=lr=fc=lc=nil
182
+ sheet = @default_sheet unless sheet
183
+ if ! @cells_read[sheet]
184
+ read_cells(sheet)
185
+ end
186
+ if @cell[sheet] # nur wenn ueberhaupt Zellen belegt sind
187
+ @cell[sheet].each {|cellitem|
188
+ key = cellitem.first
189
+ y,x = key
190
+
191
+ if cellitem[1].class != String or
192
+ (cellitem[1].class == String and cellitem[1] != "")
193
+ fr = y unless fr
194
+ fr = y if y < fr
195
+
196
+ lr = y unless lr
197
+ lr = y if y > lr
198
+
199
+ fc = x unless fc
200
+ fc = x if x < fc
201
+
202
+ lc = x unless lc
203
+ lc = x if x > lc
204
+ end
205
+ }
236
206
  end
237
- # 2007-11-05 END
238
207
  @first_row[sheet] = fr
239
208
  @last_row[sheet] = lr
240
209
  @first_column[sheet] = fc
@@ -246,6 +215,7 @@ class Excel < GenericSpreadsheet
246
215
  def sheet_no(name)
247
216
  return name-1 if name.kind_of?(Fixnum)
248
217
  0.upto(@workbook.sheet_count - 1) do |i|
218
+ #0.upto(@workbook.worksheets.size - 1) do |i|
249
219
  # TODO: is there a better way to do conversion?
250
220
  return i if name == platform_specific_iconv(
251
221
  @workbook.worksheet(i).name)
@@ -317,19 +287,22 @@ class Excel < GenericSpreadsheet
317
287
 
318
288
  # helper function to set the internal representation of cells
319
289
  def set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v)
320
- key = "#{y},#{x+i}"
290
+ #key = "#{y},#{x+i}"
291
+ key = [y,x+i]
321
292
  @cell_type[sheet] = {} unless @cell_type[sheet]
322
293
  @cell_type[sheet][key] = vt
323
294
  @formula[sheet] = {} unless @formula[sheet]
324
295
  @formula[sheet][key] = formula if formula
325
296
  @cell[sheet] = {} unless @cell[sheet]
326
- case @cell_type[sheet][key]
297
+ case vt # @cell_type[sheet][key]
327
298
  when :float
328
299
  @cell[sheet][key] = v.to_f
329
300
  when :string
330
301
  @cell[sheet][key] = str_v
331
302
  when :date
332
303
  @cell[sheet][key] = v
304
+ when :datetime
305
+ @cell[sheet][key] = DateTime.new(v.year,v.month,v.day,v.hour,v.min,v.sec)
333
306
  when :percentage
334
307
  @cell[sheet][key] = v.to_f
335
308
  when :time
@@ -344,6 +317,11 @@ class Excel < GenericSpreadsheet
344
317
  sheet = @default_sheet unless sheet
345
318
  raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
346
319
  raise RangeError unless self.sheets.include? sheet
320
+
321
+ if @cells_read[sheet]
322
+ raise "sheet #{sheet} already read"
323
+ end
324
+
347
325
  worksheet = @workbook.worksheet(sheet_no(sheet))
348
326
  skip = 0
349
327
  x =1
@@ -352,7 +330,7 @@ class Excel < GenericSpreadsheet
352
330
  worksheet.each(skip) { |row_par|
353
331
  if row_par
354
332
  x =1
355
- row_par.each do # |void|
333
+ row_par.each do # |void|
356
334
  cell = row_par.at(x-1)
357
335
  if cell
358
336
  case cell.type
@@ -374,17 +352,26 @@ class Excel < GenericSpreadsheet
374
352
  s = secs
375
353
  v = h*3600+m*60+s
376
354
  else
377
- vt = :date
378
- v = cell.date
379
- v = sprintf("%04d-%02d-%02d",v.year,v.month,v.day)
355
+ if cell.datetime.hour != 0 or
356
+ cell.datetime.min != 0 or
357
+ cell.datetime.sec != 0 or
358
+ cell.datetime.msec != 0
359
+ vt = :datetime
360
+ v = cell.datetime
361
+ else
362
+ vt = :date
363
+ v = cell.date
364
+ v = sprintf("%04d-%02d-%02d",v.year,v.month,v.day)
365
+ end
380
366
  end
381
367
  else
382
- vt = cell.type.to_sym
368
+ vt = cell.type.to_s.downcase.to_sym
383
369
  v = nil
384
370
  end # case
385
371
  formula = tr = nil #TODO:???
386
372
  set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v)
387
373
  end # if cell
374
+
388
375
  x += 1
389
376
  end
390
377
  end
@@ -393,18 +380,18 @@ class Excel < GenericSpreadsheet
393
380
  @cells_read[sheet] = true
394
381
  end
395
382
 
396
- #TODO: testing only
397
- # def inject_null_characters(str)
398
- # if str.class != String
399
- # return str
400
- # end
401
- # new_str=''
402
- # 0.upto(str.size-1) do |i|
403
- # new_str += str[i,1]
404
- # new_str += "\000"
405
- # end
406
- # new_str
407
- # end
408
- #
383
+ #TODO: testing only
384
+ # def inject_null_characters(str)
385
+ # if str.class != String
386
+ # return str
387
+ # end
388
+ # new_str=''
389
+ # 0.upto(str.size-1) do |i|
390
+ # new_str += str[i,1]
391
+ # new_str += "\000"
392
+ # end
393
+ # new_str
394
+ # end
395
+ #
409
396
 
410
397
  end
data/lib/roo/excelx.rb CHANGED
@@ -4,7 +4,6 @@ require 'rexml/document'
4
4
  require 'fileutils'
5
5
  require 'zip/zipfilesystem'
6
6
  require 'date'
7
- #require 'base64'
8
7
 
9
8
  class String
10
9
  def end_with?(str)
@@ -156,10 +155,10 @@ class Excelx < GenericSpreadsheet
156
155
  read_cells(sheet) unless @cells_read[sheet]
157
156
  row,col = normalize(row,col)
158
157
  if celltype(row,col,sheet) == :date
159
- yyyy,mm,dd = @cell[sheet]["#{row},#{col}"].split('-')
158
+ yyyy,mm,dd = @cell[sheet][[row,col]].split('-')
160
159
  return Date.new(yyyy.to_i,mm.to_i,dd.to_i)
161
160
  end
162
- @cell[sheet]["#{row},#{col}"]
161
+ @cell[sheet][[row,col]]
163
162
  end
164
163
 
165
164
  # Returns the formula at (row,col).
@@ -169,10 +168,10 @@ class Excelx < GenericSpreadsheet
169
168
  sheet = @default_sheet unless sheet
170
169
  read_cells(sheet) unless @cells_read[sheet]
171
170
  row,col = normalize(row,col)
172
- if @formula[sheet]["#{row},#{col}"] == nil
171
+ if @formula[sheet][[row,col]] == nil
173
172
  return nil
174
173
  else
175
- return @formula[sheet]["#{row},#{col}"]
174
+ return @formula[sheet][[row,col]]
176
175
  end
177
176
  end
178
177
 
@@ -209,15 +208,15 @@ class Excelx < GenericSpreadsheet
209
208
  # * :percentage
210
209
  # * :formula
211
210
  # * :time
212
- def celltype(row,col,sheet=nil)
211
+ # * :datetime
212
+ def celltype(row,col,sheet=nil)
213
213
  sheet = @default_sheet unless sheet
214
214
  read_cells(sheet) unless @cells_read[sheet]
215
215
  row,col = normalize(row,col)
216
- # if @formula and @formula[sheet] and @formula[sheet]["#{row},#{col}"]
217
- if @formula[sheet]["#{row},#{col}"]
216
+ if @formula[sheet][[row,col]]
218
217
  return :formula
219
218
  else
220
- @cell_type[sheet]["#{row},#{col}"]
219
+ @cell_type[sheet][[row,col]]
221
220
  end
222
221
  end
223
222
 
@@ -229,7 +228,7 @@ class Excelx < GenericSpreadsheet
229
228
  sheet = @default_sheet unless sheet
230
229
  read_cells(sheet) unless @cells_read[sheet]
231
230
  row,col = normalize(row,col)
232
- return @excelx_type[sheet]["#{row},#{col}"]
231
+ return @excelx_type[sheet][[row,col]]
233
232
  end
234
233
 
235
234
  # returns the internal value of an excelx cell
@@ -238,7 +237,7 @@ class Excelx < GenericSpreadsheet
238
237
  sheet = @default_sheet unless sheet
239
238
  read_cells(sheet) unless @cells_read[sheet]
240
239
  row,col = normalize(row,col)
241
- return @excelx_value[sheet]["#{row},#{col}"]
240
+ return @excelx_value[sheet][[row,col]]
242
241
  end
243
242
 
244
243
  # returns the internal format of an excel cell
@@ -246,7 +245,7 @@ class Excelx < GenericSpreadsheet
246
245
  sheet = @default_sheet unless sheet
247
246
  read_cells(sheet) unless @cells_read[sheet]
248
247
  row,col = normalize(row,col)
249
- s = @s_attribute[sheet]["#{row},#{col}"]
248
+ s = @s_attribute[sheet][[row,col]]
250
249
  result = attribute2format(s)
251
250
  result
252
251
  end
@@ -298,7 +297,7 @@ class Excelx < GenericSpreadsheet
298
297
  excelx_type=nil,
299
298
  excelx_value=nil,
300
299
  s_attribute=nil)
301
- key = "#{y},#{x+i}"
300
+ key = [y,x+i]
302
301
  @cell_type[sheet] = {} unless @cell_type[sheet]
303
302
  @cell_type[sheet][key] = vt
304
303
  @formula[sheet] = {} unless @formula[sheet]
@@ -314,8 +313,6 @@ class Excelx < GenericSpreadsheet
314
313
  when :percentage
315
314
  @cell[sheet][key] = v.to_f
316
315
  when :time
317
- #hms = v.split(':')
318
- #@cell[sheet][key] = hms[0].to_i*3600 + hms[1].to_i*60 + hms[2].to_i
319
316
  @cell[sheet][key] = v.to_f*(24*60*60)
320
317
  else
321
318
  @cell[sheet][key] = v
@@ -497,13 +494,13 @@ class Excelx < GenericSpreadsheet
497
494
  # sets the value of a cell
498
495
  def set_value(row,col,value,sheet=nil)
499
496
  sheet = @default_value unless sheet
500
- @cell[sheet]["#{row},#{col}"] = value
497
+ @cell[sheet][[row,col]] = value
501
498
  end
502
499
 
503
500
  # sets the type of a cell
504
501
  def set_type(row,col,type,sheet=nil)
505
502
  sheet = @default_value unless sheet
506
- @cell_type[sheet]["#{row},#{col}"] = type
503
+ @cell_type[sheet][[row,col]] = type
507
504
  end
508
505
 
509
506
  # read the shared strings xml document
@@ -542,7 +539,6 @@ class Excelx < GenericSpreadsheet
542
539
  e2.each_element do |e3|
543
540
  if e3.name == 'xf'
544
541
  numFmtId = e3.attributes['numFmtId']
545
- # p numFmtId
546
542
  @cellXfs << [numFmtId]
547
543
  end
548
544
  end
@@ -53,7 +53,7 @@ class GenericSpreadsheet
53
53
  impossible_value = 999_999 # more than a spreadsheet can hold
54
54
  result = impossible_value
55
55
  @cell[sheet].each_pair {|key,value|
56
- y,x = key.split(',')
56
+ y,x = key # _to_string(key).split(',')
57
57
  y = y.to_i
58
58
  result = [result, y].min if value
59
59
  } if @cell[sheet]
@@ -72,7 +72,7 @@ class GenericSpreadsheet
72
72
  impossible_value = 0
73
73
  result = impossible_value
74
74
  @cell[sheet].each_pair {|key,value|
75
- y,x = key.split(',')
75
+ y,x = key # _to_string(key).split(',')
76
76
  y = y.to_i
77
77
  result = [result, y].max if value
78
78
  } if @cell[sheet]
@@ -93,8 +93,8 @@ class GenericSpreadsheet
93
93
  impossible_value = 999_999 # more than a spreadsheet can hold
94
94
  result = impossible_value
95
95
  @cell[sheet].each_pair {|key,value|
96
- y,x = key.split(',')
97
- x = x.to_i
96
+ y,x = key # _to_string(key).split(',')
97
+ x = x # .to_i
98
98
  result = [result, x].min if value
99
99
  } if @cell[sheet]
100
100
  result = nil if result == impossible_value
@@ -112,7 +112,7 @@ class GenericSpreadsheet
112
112
  impossible_value = 0
113
113
  result = impossible_value
114
114
  @cell[sheet].each_pair {|key,value|
115
- y,x = key.split(',')
115
+ y,x = key # _to_string(key).split(',')
116
116
  x = x.to_i
117
117
  result = [result, x].max if value
118
118
  } if @cell[sheet]
@@ -227,7 +227,6 @@ class GenericSpreadsheet
227
227
  found *= 0
228
228
  end
229
229
  }
230
- # p self.row(i) if found > 0
231
230
  if found > 0
232
231
  tmp = {}
233
232
  1.upto(self.row(i).size) {|j|
@@ -261,7 +260,7 @@ class GenericSpreadsheet
261
260
  result = []
262
261
  tmp_arr = []
263
262
  @cell[sheet].each_pair {|key,value|
264
- y,x = key.split(',')
263
+ y,x = key # _to_string(key).split(',')
265
264
  x = x.to_i
266
265
  y = y.to_i
267
266
  if y == rownumber
@@ -400,6 +399,21 @@ class GenericSpreadsheet
400
399
  end
401
400
  end
402
401
 
402
+ # konvertiert einen Key in der Form "12,45" (=row,column) in
403
+ # ein Array mit numerischen Werten ([12,45])
404
+ # Diese Methode ist eine temp. Loesung, um zu erforschen, ob der
405
+ # Zugriff mit numerischen Keys schneller ist.
406
+ def key_to_num(str)
407
+ r,c = str.split(',')
408
+ r = r.to_i
409
+ c = c.to_i
410
+ [r,c]
411
+ end
412
+
413
+ # siehe: key_to_num
414
+ def key_to_string(arr)
415
+ "#{arr[0]},#{arr[1]}"
416
+ end
403
417
 
404
418
  private
405
419
 
@@ -435,6 +449,14 @@ class GenericSpreadsheet
435
449
  File.join(@tmpdir, File.basename(uri))
436
450
  end
437
451
 
452
+ def open_from_stream(stream)
453
+ tempfilename = File.join(@tmpdir, "spreadsheet")
454
+ f = File.open(tempfilename,"wb")
455
+ f.write(stream[7..-1])
456
+ f.close
457
+ File.join(@tmpdir, "spreadsheet")
458
+ end
459
+
438
460
  # convert a number to something like 'AB' (1 => 'A', 2 => 'B', ...)
439
461
  def self.number_to_letter(n)
440
462
  letters=""
data/lib/roo/google.rb CHANGED
@@ -162,6 +162,7 @@ class Google < GenericSpreadsheet
162
162
  # * :percentage
163
163
  # * :formula
164
164
  # * :time
165
+ # * :datetime
165
166
  def celltype(row, col, sheet=nil)
166
167
  sheet = @default_sheet unless sheet
167
168
  read_cells(sheet) unless @cells_read[sheet]
@@ -321,6 +322,7 @@ class Google < GenericSpreadsheet
321
322
  # read all cells in a sheet
322
323
  def read_cells(sheet=nil)
323
324
  sheet = @default_sheet unless sheet
325
+ raise RangeError, "illegal sheet <#{sheet}>" unless sheets.index(sheet)
324
326
  sheet_no = sheets.index(sheet)+1
325
327
  doc = @gs.fulldoc(sheet_no)
326
328
  (doc/"gs:cell").each {|item|
@@ -80,10 +80,10 @@ class Openoffice < GenericSpreadsheet
80
80
  read_cells(sheet) unless @cells_read[sheet]
81
81
  row,col = normalize(row,col)
82
82
  if celltype(row,col,sheet) == :date
83
- yyyy,mm,dd = @cell[sheet]["#{row},#{col}"].split('-')
83
+ yyyy,mm,dd = @cell[sheet][[row,col]].split('-')
84
84
  return Date.new(yyyy.to_i,mm.to_i,dd.to_i)
85
85
  end
86
- @cell[sheet]["#{row},#{col}"]
86
+ @cell[sheet][[row,col]]
87
87
  end
88
88
 
89
89
  # Returns the formula at (row,col).
@@ -93,10 +93,10 @@ class Openoffice < GenericSpreadsheet
93
93
  sheet = @default_sheet unless sheet
94
94
  read_cells(sheet) unless @cells_read[sheet]
95
95
  row,col = normalize(row,col)
96
- if @formula[sheet]["#{row},#{col}"] == nil
96
+ if @formula[sheet][[row,col]] == nil
97
97
  return nil
98
98
  else
99
- return @formula[sheet]["#{row},#{col}"]["oooc:".length..-1]
99
+ return @formula[sheet][[row,col]]["oooc:".length..-1]
100
100
  end
101
101
  end
102
102
 
@@ -133,14 +133,15 @@ class Openoffice < GenericSpreadsheet
133
133
  # * :percentage
134
134
  # * :formula
135
135
  # * :time
136
+ # * :datetime
136
137
  def celltype(row,col,sheet=nil)
137
138
  sheet = @default_sheet unless sheet
138
139
  read_cells(sheet) unless @cells_read[sheet]
139
140
  row,col = normalize(row,col)
140
- if @formula[sheet]["#{row},#{col}"]
141
+ if @formula[sheet][[row,col]]
141
142
  return :formula
142
143
  else
143
- @cell_type[sheet]["#{row},#{col}"]
144
+ @cell_type[sheet][[row,col]]
144
145
  end
145
146
  end
146
147
 
@@ -172,7 +173,6 @@ class Openoffice < GenericSpreadsheet
172
173
  # version of the openoffice document
173
174
  # at 2007 this is always "1.0"
174
175
  def officeversion
175
- # read_cells(false) unless @cells_read
176
176
  oo_version
177
177
  @officeversion
178
178
  end
@@ -211,7 +211,6 @@ class Openoffice < GenericSpreadsheet
211
211
 
212
212
  # read the version of the OO-Version
213
213
  def oo_version
214
- #sheet_found = false
215
214
  @doc.each_element do |oo_document|
216
215
  @officeversion = oo_document.attributes['version']
217
216
  end
@@ -219,7 +218,7 @@ class Openoffice < GenericSpreadsheet
219
218
 
220
219
  # helper function to set the internal representation of cells
221
220
  def set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v)
222
- key = "#{y},#{x+i}"
221
+ key = [y,x+i]
223
222
  @cell_type[sheet] = {} unless @cell_type[sheet]
224
223
  @cell_type[sheet][key] = Openoffice.oo_type_2_roo_type(vt)
225
224
  @formula[sheet] = {} unless @formula[sheet]
@@ -231,7 +230,14 @@ class Openoffice < GenericSpreadsheet
231
230
  when :string
232
231
  @cell[sheet][key] = str_v
233
232
  when :date
234
- @cell[sheet][key] = tr.attributes['date-value']
233
+ if tr.attributes['date-value'].size != "XXXX-XX-XX".size
234
+ #-- dann ist noch eine Uhrzeit vorhanden
235
+ #-- "1961-11-21T12:17:18"
236
+ @cell[sheet][key] = DateTime.parse(tr.attributes['date-value'])
237
+ @cell_type[sheet][key] = :datetime
238
+ else
239
+ @cell[sheet][key] = tr.attributes['date-value']
240
+ end
235
241
  when :percentage
236
242
  @cell[sheet][key] = v.to_f
237
243
  when :time
@@ -264,7 +270,7 @@ class Openoffice < GenericSpreadsheet
264
270
  if be.name == "spreadsheet"
265
271
  be.each_element do |se|
266
272
  if se.name == "table"
267
- if se.attributes['name']==sheet #@default_sheet
273
+ if se.attributes['name']==sheet
268
274
  sheet_found = true
269
275
  x=1
270
276
  y=1
@@ -303,13 +309,24 @@ class Openoffice < GenericSpreadsheet
303
309
  str_v.gsub!(/&apos;/,"'")
304
310
  end # == 'p'
305
311
  end
306
- end
307
- if vt == 'time'
312
+ elsif vt == 'time'
308
313
  tr.each_element do |str|
309
314
  if str.name == 'p'
310
315
  v = str.text
311
316
  end
312
317
  end
318
+ elsif vt == '' or vt == nil
319
+ #
320
+ elsif vt == 'date'
321
+ #
322
+ elsif vt == 'percentage'
323
+ #
324
+ elsif vt == 'float'
325
+ #
326
+ elsif vt == 'boolean'
327
+ #
328
+ else
329
+ # raise "unknown type #{vt}"
313
330
  end
314
331
  if skip
315
332
  if v != nil or tr.attributes['date-value']
@@ -373,7 +390,7 @@ class Openoffice < GenericSpreadsheet
373
390
  def process_zipfile(zip, path='')
374
391
  if zip.file.file? path
375
392
  if path == "content.xml"
376
- open(@tmpdir+'/'+@file_nr.to_s+'_roo_content.xml','wb') {|f|
393
+ open(File.join(@tmpdir, @file_nr.to_s+'_roo_content.xml'),'wb') {|f|
377
394
  f << zip.read(path)
378
395
  }
379
396
  end
@@ -395,12 +412,12 @@ class Openoffice < GenericSpreadsheet
395
412
 
396
413
  def set_value(row,col,value,sheet=nil)
397
414
  sheet = @default_value unless sheet
398
- @cell[sheet]["#{row},#{col}"] = value
415
+ @cell[sheet][[row,col]] = value
399
416
  end
400
417
 
401
418
  def set_type(row,col,type,sheet=nil)
402
419
  sheet = @default_value unless sheet
403
- @cell_type[sheet]["#{row},#{col}"] = type
420
+ @cell_type[sheet][[row,col]] = type
404
421
  end
405
422
 
406
423
  A_ROO_TYPE = {