roo 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/Manifest.txt +2 -0
- data/lib/roo/excel.rb +89 -102
- data/lib/roo/excelx.rb +14 -18
- data/lib/roo/generic_spreadsheet.rb +29 -7
- data/lib/roo/google.rb +2 -0
- data/lib/roo/openoffice.rb +33 -16
- data/lib/roo/version.rb +1 -1
- data/test/datetime.ods +0 -0
- data/test/datetime.xls +0 -0
- data/test/test_helper.rb +1 -1
- data/test/test_roo.rb +754 -227
- data/website/index.html +29 -10
- data/website/index.txt +7 -1
- metadata +6 -4
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
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.
|
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][
|
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][
|
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
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
-
|
159
|
-
|
160
|
-
|
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
|
-
|
164
|
-
|
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
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
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
|
-
|
378
|
-
|
379
|
-
|
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
|
-
|
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][
|
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][
|
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][
|
171
|
+
if @formula[sheet][[row,col]] == nil
|
173
172
|
return nil
|
174
173
|
else
|
175
|
-
return @formula[sheet][
|
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
|
-
|
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
|
-
|
217
|
-
if @formula[sheet]["#{row},#{col}"]
|
216
|
+
if @formula[sheet][[row,col]]
|
218
217
|
return :formula
|
219
218
|
else
|
220
|
-
@cell_type[sheet][
|
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][
|
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][
|
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][
|
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 =
|
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][
|
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][
|
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|
|
data/lib/roo/openoffice.rb
CHANGED
@@ -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][
|
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][
|
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][
|
96
|
+
if @formula[sheet][[row,col]] == nil
|
97
97
|
return nil
|
98
98
|
else
|
99
|
-
return @formula[sheet][
|
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][
|
141
|
+
if @formula[sheet][[row,col]]
|
141
142
|
return :formula
|
142
143
|
else
|
143
|
-
@cell_type[sheet][
|
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 =
|
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
|
-
|
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
|
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!(/'/,"'")
|
304
310
|
end # == 'p'
|
305
311
|
end
|
306
|
-
|
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
|
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][
|
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][
|
420
|
+
@cell_type[sheet][[row,col]] = type
|
404
421
|
end
|
405
422
|
|
406
423
|
A_ROO_TYPE = {
|