donibuchanan-roo 1.3.12 → 1.9.1.4

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,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