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 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
- true
77
+ true
90
78
  else
91
- false
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
- read_cells(sheet) unless @cells_read[sheet]
162
- raise "should be read" unless @cells_read[sheet]
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
- read_cells(sheet) unless @cells_read[sheet]
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
- datetime.min != 0 or
418
- datetime.sec != 0
455
+ datetime.min != 0 or
456
+ datetime.sec != 0
419
457
  value_type = :datetime
420
458
  value = datetime
421
459
  else