donibuchanan-roo 1.3.12 → 1.9.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +26 -6
- data/lib/roo/excel.rb +83 -45
- data/lib/roo/excelx.rb +241 -69
- data/lib/roo/generic_spreadsheet.rb +34 -8
- data/lib/roo/google.rb +63 -117
- data/lib/roo/openoffice.rb +79 -27
- data/lib/roo/version.rb +9 -9
- data/lib/roo.rb +56 -13
- data/test/1900_base.xls +0 -0
- data/test/1904_base.xls +0 -0
- data/test/Bibelbund.csv +0 -0
- data/test/bode-v1.ods.zip +0 -0
- data/test/bode-v1.xls.zip +0 -0
- data/test/boolean.xls +0 -0
- data/test/datetime.xls +0 -0
- data/test/numbers1.csv +0 -0
- data/test/test_helper.rb +1 -1
- data/test/test_roo.rb +381 -269
- data/test/whitespace.xls +0 -0
- metadata +2 -1
data/History.txt
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
== 1.9.2 2009-?????
|
2
|
+
|
3
|
+
* 1 bugfix
|
4
|
+
* double quoting of '"' fixed
|
5
|
+
|
6
|
+
== 1.9.1 2009-11-10
|
7
|
+
|
8
|
+
* 2 bugfixes
|
9
|
+
* syntax in nokogiri methods
|
10
|
+
* missing dependency ...rubyzip
|
11
|
+
|
12
|
+
== 1.9.0 2009-10-29
|
13
|
+
|
14
|
+
* 4 enhancements
|
15
|
+
* Ruby 1.9 compatible
|
16
|
+
* oo.aa42 as a shortcut of oo.cell('aa',42)
|
17
|
+
* oo.aa42('sheet1') as a shortcut of oo.cell('aa',42,'sheet1')
|
18
|
+
* oo.anton as a reference to a cell labelled 'anton' (or any other label name)
|
19
|
+
(currently only for Openoffice spreadsheets)
|
20
|
+
|
1
21
|
== 1.2.3 2009-01-04
|
2
22
|
|
3
23
|
* bugfix
|
@@ -89,8 +109,8 @@
|
|
89
109
|
* some methods common to more than one class were factored out to the GenericSpreadsheet (virtual) class
|
90
110
|
== 0.7.0 2007-11-23
|
91
111
|
* 6 enhancements:
|
92
|
-
* Openoffice/Excel: the most methods can be called with an option 'sheet'
|
93
|
-
parameter which will be used instead of the default sheet
|
112
|
+
* Openoffice/Excel: the most methods can be called with an option 'sheet'
|
113
|
+
parameter which will be used instead of the default sheet
|
94
114
|
* Excel: improved the speed of CVS output
|
95
115
|
* Openoffice/Excel: new method #column
|
96
116
|
* Openoffice/Excel: new method #find
|
@@ -118,7 +138,7 @@
|
|
118
138
|
== 0.5.1 2007-08-26
|
119
139
|
* 4 enhancements:
|
120
140
|
* Openoffice: Exception if an illegal sheet-name is selected
|
121
|
-
* Openoffice/Excel: no need to set a default_sheet if there is only one in
|
141
|
+
* Openoffice/Excel: no need to set a default_sheet if there is only one in
|
122
142
|
the document
|
123
143
|
* Excel: can now read zip-ed files
|
124
144
|
* Excel: can now read files from http://-URL over the net
|
@@ -136,7 +156,7 @@
|
|
136
156
|
== 0.4.0 2007-06-27
|
137
157
|
* 7 enhancements:
|
138
158
|
* robustness: Exception if no default_sheet was set
|
139
|
-
* new method reload() implemented
|
159
|
+
* new method reload() implemented
|
140
160
|
* about 15 % more method documentation
|
141
161
|
* optimization: huge increase of speed (no need to use fixed borders anymore)
|
142
162
|
* added the method 'formulas' which gives you all formulas in a spreadsheet
|
@@ -158,7 +178,7 @@
|
|
158
178
|
|
159
179
|
== 0.2.6 2007-06-19
|
160
180
|
* 1 bugfix:
|
161
|
-
* Openoffice: two or more consecutive cells with string content failed
|
181
|
+
* Openoffice: two or more consecutive cells with string content failed
|
162
182
|
|
163
183
|
== 0.2.5 2007-06-17
|
164
184
|
|
@@ -188,7 +208,7 @@
|
|
188
208
|
|
189
209
|
== 0.2.2 2007-06-01
|
190
210
|
* 1 bugfix:
|
191
|
-
* incorrect dependencies fixed
|
211
|
+
* incorrect dependencies fixed
|
192
212
|
|
193
213
|
== 0.2.0 2007-06-01
|
194
214
|
* 1 major enhancement:
|
data/lib/roo/excel.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
require 'rubygems'
|
1
2
|
require 'spreadsheet'
|
3
|
+
#require 'lib/roo/generic_spreadsheet'
|
4
|
+
#require 'parseexcel'
|
2
5
|
CHARGUESS = begin
|
3
6
|
require 'charguess'
|
4
7
|
true
|
@@ -9,6 +12,26 @@ end
|
|
9
12
|
# The Spreadsheet library has a bug in handling Excel
|
10
13
|
# base dates so if the file is a 1904 base date then
|
11
14
|
# dates are off by a day. 1900 base dates work fine
|
15
|
+
module Spreadsheet
|
16
|
+
module Excel
|
17
|
+
class Row < Spreadsheet::Row
|
18
|
+
def _date data # :nodoc:
|
19
|
+
return data if data.is_a?(Date)
|
20
|
+
date = @worksheet.date_base + data.to_i
|
21
|
+
if LEAP_ERROR > @worksheet.date_base
|
22
|
+
date -= 1
|
23
|
+
end
|
24
|
+
date
|
25
|
+
end
|
26
|
+
public :_datetime
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
#=====================================================================
|
32
|
+
# TODO:
|
33
|
+
# redefinition of this method, the method in the spreadsheet gem has a bug
|
34
|
+
# redefinition can be removed, if spreadsheet does it in the correct way
|
12
35
|
module Spreadsheet
|
13
36
|
module Excel
|
14
37
|
class Row < Spreadsheet::Row
|
@@ -38,45 +61,10 @@ module Spreadsheet
|
|
38
61
|
end
|
39
62
|
DateTime.new(date.year, date.month, date.day, hour, min, sec)
|
40
63
|
end
|
41
|
-
public :_date
|
42
|
-
public :_datetime
|
43
|
-
end
|
44
|
-
# patch for ruby-spreadsheet parsing formulas
|
45
|
-
class Reader
|
46
|
-
def read_formula worksheet, addr, work
|
47
|
-
row, column, xf, rtype, rval, rcheck, opts = work.unpack 'v3CxCx3v2'
|
48
|
-
formula = Formula.new
|
49
|
-
formula.shared = (opts & 0x08) > 0
|
50
|
-
formula.data = work[20..-1]
|
51
|
-
if rcheck != 0xffff || rtype > 3
|
52
|
-
value, = work.unpack 'x6E'
|
53
|
-
unless value
|
54
|
-
# on architectures where sizeof(double) > 8
|
55
|
-
value, = work.unpack 'x6e'
|
56
|
-
end
|
57
|
-
formula.value = value
|
58
|
-
elsif rtype == 0
|
59
|
-
pos, op, len, work = get_next_chunk
|
60
|
-
if op == :string
|
61
|
-
formula.value = client read_string(work, 2), @workbook.encoding
|
62
|
-
else
|
63
|
-
# This seems to work but I don't know why :). It at least
|
64
|
-
# seems to correct the case we saw but doubtful it's the right fix
|
65
|
-
formula.value = client read_string(work[10..-1], 2), @workbook.encoding
|
66
|
-
end
|
67
|
-
elsif rtype == 1
|
68
|
-
formula.value = rval > 0
|
69
|
-
elsif rtype == 2
|
70
|
-
formula.value = Error.new rval
|
71
|
-
else
|
72
|
-
# leave the Formula value blank
|
73
|
-
end
|
74
|
-
set_cell worksheet, row, column, xf, formula
|
75
|
-
end
|
76
64
|
end
|
77
65
|
end
|
78
66
|
end
|
79
|
-
|
67
|
+
#=====================================================================
|
80
68
|
|
81
69
|
# ruby-spreadsheet has a font object so we're extending it
|
82
70
|
# with our own functionality but still providing full access
|
@@ -86,9 +74,9 @@ module ExcelFontExtensions
|
|
86
74
|
#From ruby-spreadsheet doc: 100 <= weight <= 1000, bold => 700, normal => 400
|
87
75
|
case weight
|
88
76
|
when 700
|
89
|
-
|
77
|
+
true
|
90
78
|
else
|
91
|
-
|
79
|
+
false
|
92
80
|
end
|
93
81
|
end
|
94
82
|
|
@@ -134,6 +122,7 @@ class Excel < GenericSpreadsheet
|
|
134
122
|
#end
|
135
123
|
end
|
136
124
|
@cell = Hash.new
|
125
|
+
@read_first_100_rows = Hash.new
|
137
126
|
@cell_type = Hash.new
|
138
127
|
@formula = Hash.new
|
139
128
|
@first_row = Hash.new
|
@@ -158,8 +147,11 @@ class Excel < GenericSpreadsheet
|
|
158
147
|
def cell(row,col,sheet=nil)
|
159
148
|
sheet = @default_sheet unless sheet
|
160
149
|
raise ArgumentError unless sheet
|
161
|
-
|
162
|
-
|
150
|
+
unless @cells_read[sheet] or (@read_first_100_rows[sheet] and row < 100)
|
151
|
+
read_cells(sheet)
|
152
|
+
raise "should be read" unless @cells_read[sheet]
|
153
|
+
end
|
154
|
+
|
163
155
|
row,col = normalize(row,col)
|
164
156
|
if celltype(row,col,sheet) == :date
|
165
157
|
yyyy,mm,dd = @cell[sheet][[row,col]].split('-')
|
@@ -182,7 +174,9 @@ class Excel < GenericSpreadsheet
|
|
182
174
|
# * :datetime
|
183
175
|
def celltype(row,col,sheet=nil)
|
184
176
|
sheet = @default_sheet unless sheet
|
185
|
-
|
177
|
+
unless @cells_read[sheet] or (@read_first_100_rows[sheet] and row < 100)
|
178
|
+
read_cells(sheet)
|
179
|
+
end
|
186
180
|
row,col = normalize(row,col)
|
187
181
|
begin
|
188
182
|
if @formula[sheet][[row,col]]
|
@@ -227,6 +221,41 @@ class Excel < GenericSpreadsheet
|
|
227
221
|
@cell[sheet].inspect
|
228
222
|
end
|
229
223
|
|
224
|
+
# returns the row,col values of the labelled cell
|
225
|
+
# (nil,nil) if label is not defined
|
226
|
+
# sheet parameter is not really needed because label names are global
|
227
|
+
# to the whole spreadsheet
|
228
|
+
def label(labelname,sheet=nil)
|
229
|
+
sheet = @default_sheet unless sheet
|
230
|
+
read_cells(sheet) unless @cells_read[sheet]
|
231
|
+
if @labels.has_key? labelname
|
232
|
+
return @labels[labelname][1].to_i,
|
233
|
+
GenericSpreadsheet.letter_to_number(@labels[labelname][2]),
|
234
|
+
@labels[labelname][0]
|
235
|
+
else
|
236
|
+
return nil,nil,nil
|
237
|
+
end
|
238
|
+
end
|
239
|
+
def first_row(sheet=nil)
|
240
|
+
if sheet == nil
|
241
|
+
sheet = @default_sheet
|
242
|
+
end
|
243
|
+
read_first_100_rows(sheet) unless @read_first_100_rows[sheet] or @cells_read[sheet]
|
244
|
+
if @first_row[sheet]
|
245
|
+
return @first_row[sheet]
|
246
|
+
end
|
247
|
+
impossible_value = 999_999 # more than a spreadsheet can hold
|
248
|
+
result = impossible_value
|
249
|
+
@cell[sheet].each_pair {|key,value|
|
250
|
+
y,x = key # _to_string(key).split(',')
|
251
|
+
y = y.to_i
|
252
|
+
result = [result, y].min if value
|
253
|
+
} if @cell[sheet]
|
254
|
+
result = nil if result == impossible_value
|
255
|
+
@first_row[sheet] = result
|
256
|
+
result
|
257
|
+
end
|
258
|
+
|
230
259
|
private
|
231
260
|
|
232
261
|
# converts name of a sheet to index (0,1,2,..)
|
@@ -338,9 +367,14 @@ class Excel < GenericSpreadsheet
|
|
338
367
|
@cell[sheet][key] = v
|
339
368
|
end
|
340
369
|
end
|
341
|
-
|
370
|
+
|
371
|
+
def read_first_100_rows(sheet=nil)
|
372
|
+
read_cells(sheet, 100)
|
373
|
+
@cells_read[sheet] = false
|
374
|
+
@read_first_100_rows[sheet] = true
|
375
|
+
end
|
342
376
|
# read all cells in the selected sheet
|
343
|
-
def read_cells(sheet=nil)
|
377
|
+
def read_cells(sheet=nil, limit=nil)
|
344
378
|
sheet = @default_sheet unless sheet
|
345
379
|
raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
|
346
380
|
raise RangeError unless self.sheets.include? sheet
|
@@ -353,6 +387,7 @@ class Excel < GenericSpreadsheet
|
|
353
387
|
row_index=1
|
354
388
|
worksheet.each(0) do |row|
|
355
389
|
(0..row.size).each do |cell_index|
|
390
|
+
|
356
391
|
cell = row.at(cell_index)
|
357
392
|
next if cell.nil? #skip empty cells
|
358
393
|
next if cell.class == Spreadsheet::Formula && cell.value.nil? # skip empty formla cells
|
@@ -368,6 +403,9 @@ class Excel < GenericSpreadsheet
|
|
368
403
|
set_cell_values(sheet,row_index,col_index,0,v,vt,formula,tr,font)
|
369
404
|
end #row
|
370
405
|
row_index += 1
|
406
|
+
unless limit.nil? or (row_index < limit )
|
407
|
+
break
|
408
|
+
end
|
371
409
|
end # worksheet
|
372
410
|
@cells_read[sheet] = true
|
373
411
|
end
|
@@ -414,8 +452,8 @@ class Excel < GenericSpreadsheet
|
|
414
452
|
datetime = row.datetime(idx)
|
415
453
|
end
|
416
454
|
if datetime.hour != 0 or
|
417
|
-
|
418
|
-
|
455
|
+
datetime.min != 0 or
|
456
|
+
datetime.sec != 0
|
419
457
|
value_type = :datetime
|
420
458
|
value = datetime
|
421
459
|
else
|