roo 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,8 @@
1
+ == 0.8.1 2007-12-22
2
+ * 3 bugfixes
3
+ * fixed a bug with first/last-row/column in empty sheet
4
+ * #info prints now '- empty -' if a sheet within a document is empty
5
+ * tried to fix the iconv conversion problem
1
6
  == 0.8.0 2007-12-15
2
7
  * 2 enhancements:
3
8
  * Google online spreadsheets were implemented
data/Manifest.txt CHANGED
@@ -15,6 +15,13 @@ lib/roo/excel.rb
15
15
  lib/roo/google.rb
16
16
  scripts/txt2html
17
17
  setup.rb
18
+ test/false_encoding.xls
19
+ test/Bibelbund1.ods
20
+ test/bbu.xls
21
+ test/bbu.ods
22
+ test/simple_spreadsheet.ods
23
+ test/simple_spreadsheet_from_italo.ods
24
+ test/simple_spreadsheet_from_italo.xls
18
25
  test/test_helper.rb
19
26
  test/test_roo.rb
20
27
  test/numbers1.ods
data/lib/roo/excel.rb CHANGED
@@ -4,7 +4,7 @@ require 'parseexcel'
4
4
  CHARGUESS=false
5
5
  require 'charguess' if CHARGUESS
6
6
 
7
- module Spreadsheet
7
+ module Spreadsheet # :nodoc
8
8
  module ParseExcel
9
9
  class Worksheet
10
10
  include Enumerable
@@ -13,8 +13,8 @@ module Spreadsheet
13
13
  end
14
14
  end
15
15
 
16
-
17
- class Excel < GenericSpreadsheet #Openoffice
16
+ # Class for handling Excel-Spreadsheets
17
+ class Excel < GenericSpreadsheet
18
18
 
19
19
  EXCEL_NO_FORMULAS = 'formulas are not supported for excel spreadsheets'
20
20
 
@@ -51,6 +51,7 @@ class Excel < GenericSpreadsheet #Openoffice
51
51
  @cells_read = Hash.new
52
52
  end
53
53
 
54
+ # returns an array of sheet names in the spreadsheet
54
55
  def sheets
55
56
  result = []
56
57
  0.upto(@workbook.sheet_count - 1) do |i|
@@ -64,9 +65,17 @@ class Excel < GenericSpreadsheet #Openoffice
64
65
  @workbook.worksheet(i).name
65
66
  )
66
67
  else
67
- result << Iconv.new('utf-8','unicode').iconv(
68
- @workbook.worksheet(i).name
69
- )
68
+ result << platform_specific_iconv(@workbook.worksheet(i).name)
69
+ #case RUBY_PLATFORM.downcase
70
+ #when /darwin/
71
+ # result << Iconv.new('utf-8','utf-8').iconv(
72
+ # @workbook.worksheet(i).name
73
+ # )
74
+ #else
75
+ # result << Iconv.new('utf-8','unicode').iconv(
76
+ # @workbook.worksheet(i).name
77
+ # )
78
+ #end # case
70
79
  end
71
80
  end
72
81
  return result
@@ -105,7 +114,7 @@ class Excel < GenericSpreadsheet #Openoffice
105
114
  when :numeric then return cell.to_f
106
115
  when :text then return cell.to_s('utf-8')
107
116
  when :date then return cell.date
108
- else
117
+ else
109
118
  return nil # cell.to_s('utf-8')
110
119
  end
111
120
  end
@@ -128,13 +137,13 @@ class Excel < GenericSpreadsheet #Openoffice
128
137
  cell = row_par.at(col-1)
129
138
  return nil unless cell
130
139
  case cell.type
131
- when :numeric
140
+ when :numeric
132
141
  return :float
133
- when :text
142
+ when :text
134
143
  return :string
135
- when :date
144
+ when :date
136
145
  return :date
137
- else
146
+ else
138
147
  return cell.type.to_sym
139
148
  end
140
149
  end
@@ -148,7 +157,7 @@ class Excel < GenericSpreadsheet #Openoffice
148
157
  sheet = @default_sheet unless sheet
149
158
  default_sheet_check
150
159
  worksheet = @workbook.worksheet(sheet_no(sheet))
151
- #therow = worksheet.row(rownumber-1)
160
+ #therow = worksheet.row(rownumber-1)
152
161
  result = []
153
162
  worksheet.row(rownumber-1).each {|cell|
154
163
  if cell
@@ -195,7 +204,7 @@ class Excel < GenericSpreadsheet #Openoffice
195
204
  else
196
205
  result << nil
197
206
  end
198
- }
207
+ }
199
208
  result
200
209
  end
201
210
 
@@ -230,7 +239,7 @@ class Excel < GenericSpreadsheet #Openoffice
230
239
  fr, lr, fc, lc = get_firsts_lasts(sheet)
231
240
  lr
232
241
  end
233
-
242
+
234
243
  # returns NO formula in excel spreadsheets
235
244
  def formula(row,col,sheet=nil)
236
245
  raise EXCEL_NO_FORMULAS
@@ -240,7 +249,7 @@ class Excel < GenericSpreadsheet #Openoffice
240
249
  def formula?(row,col,sheet=nil)
241
250
  raise EXCEL_NO_FORMULAS
242
251
  end
243
-
252
+
244
253
  # returns NO formulas in excel spreadsheets
245
254
  def formulas(sheet=nil)
246
255
  raise EXCEL_NO_FORMULAS
@@ -257,18 +266,36 @@ class Excel < GenericSpreadsheet #Openoffice
257
266
  def get_firsts_lasts(sheet=nil)
258
267
  sheet = @default_sheet unless sheet
259
268
  fr = fc = 999_999
260
- lr = lc = -999_999
269
+ lr = lc = -999_999
261
270
  worksheet = @workbook.worksheet(sheet_no(sheet))
262
- fr = worksheet.min_row + 1
263
- lr = worksheet.max_row + 1
264
- fc = worksheet.min_col + 1
265
- lc = worksheet.max_col + 1
266
- # 2007-11-05 BEGIN
267
- # parsexcel liefert (mir unverstaendlich) eine Zeile als letzte Zeile
268
- # zurueck, die aber leer ist. Deshalb Korrekturfunktion, die wirklich
269
- # die letzte nicht leere Zeile liefert.
270
- while empty_row? row(lr,sheet)
271
- lr -= 1
271
+ unless worksheet.min_row
272
+ fr = nil
273
+ else
274
+ fr = worksheet.min_row + 1
275
+ end
276
+ unless worksheet.max_row
277
+ lr = nil
278
+ else
279
+ lr = worksheet.max_row + 1
280
+ end
281
+ unless worksheet.min_col
282
+ fc = nil
283
+ else
284
+ fc = worksheet.min_col + 1
285
+ end
286
+ unless worksheet.max_col
287
+ lc = nil
288
+ else
289
+ lc = worksheet.max_col + 1
290
+ end
291
+ if lr
292
+ # 2007-11-05 BEGIN
293
+ # parsexcel liefert (mir unverstaendlich) eine Zeile als letzte Zeile
294
+ # zurueck, die aber leer ist. Deshalb Korrekturfunktion, die wirklich
295
+ # die letzte nicht leere Zeile liefert.
296
+ while empty_row? row(lr,sheet)
297
+ lr -= 1
298
+ end
272
299
  end
273
300
  # 2007-11-05 END
274
301
  @first_row[sheet] = fr
@@ -283,9 +310,11 @@ class Excel < GenericSpreadsheet #Openoffice
283
310
  return name-1 if name.kind_of?(Fixnum)
284
311
  0.upto(@workbook.sheet_count - 1) do |i|
285
312
  # TODO: is there a better way to do conversion?
286
- return i if name == Iconv.new('utf-8','unicode').iconv(
287
- @workbook.worksheet(i).name
288
- )
313
+ return i if name == platform_specific_iconv(
314
+ @workbook.worksheet(i).name)
315
+ #Iconv.new('utf-8','unicode').iconv(
316
+ # @workbook.worksheet(i).name
317
+ # )
289
318
  end
290
319
  raise StandardError, "sheet '#{name}' not found"
291
320
  end
@@ -304,21 +333,21 @@ class Excel < GenericSpreadsheet #Openoffice
304
333
  empty = true
305
334
  else
306
335
  case cell.type
307
- when :numeric
336
+ when :numeric
308
337
  onecelltype = :float
309
338
  onecell = cell.to_f
310
- when :text
339
+ when :text
311
340
  onecelltype = :string
312
341
  onecell = cell.to_s('utf-8')
313
- when :date
342
+ when :date
314
343
  onecelltype = :date
315
344
  onecell = cell.date
316
345
  else
317
346
  onecelltype = nil
318
- onecell = nil
347
+ onecell = nil
319
348
  end
320
- end
321
- file.print one_cell_output(onecelltype,onecell,empty)
349
+ end
350
+ file.print one_cell_output(onecelltype,onecell,empty)
322
351
  }
323
352
  file.print("\n")
324
353
  }
@@ -331,8 +360,20 @@ class Excel < GenericSpreadsheet #Openoffice
331
360
  #if elem.class == String and elem.size > 0
332
361
  content = true
333
362
  end
334
- }
363
+ }
335
364
  ! content
336
365
  end
337
366
 
367
+ def platform_specific_iconv(value)
368
+ case RUBY_PLATFORM.downcase
369
+ when /darwin/
370
+ result = Iconv.new('utf-8','utf-8').iconv(value)
371
+ when /mswin32/
372
+ result = Iconv.new('utf-8','iso-8859-1').iconv(value)
373
+ else
374
+ result = Iconv.new('utf-8','unicode').iconv(value)
375
+ end # case
376
+ result
377
+ end
378
+
338
379
  end
@@ -68,13 +68,24 @@ class GenericSpreadsheet
68
68
  self.default_sheet = sheet
69
69
  # $log.debug("nach default_sheet=")
70
70
  result << "Sheet " + n.to_s + ":\n"
71
- result << " First row: #{first_row}\n"
71
+ if !(first_row) # && last_row && first_column) # && last_column)
72
+ result << " - empty -"
73
+ end
74
+ if first_row
75
+ result << " First row: #{first_row}\n"
76
+ end
72
77
  # $log.debug("nach first_row")
73
- result << " Last row: #{last_row}\n"
78
+ if last_row
79
+ result << " Last row: #{last_row}\n"
80
+ end
74
81
  # $log.debug("nach last_row")
75
- result << " First column: #{GenericSpreadsheet.number_to_letter(first_column)}\n"
82
+ if first_column
83
+ result << " First column: #{GenericSpreadsheet.number_to_letter(first_column)}\n"
84
+ end
76
85
  # $log.debug("nach first_column")
77
- result << " Last column: #{GenericSpreadsheet.number_to_letter(last_column)}"
86
+ if last_column
87
+ result << " Last column: #{GenericSpreadsheet.number_to_letter(last_column)}"
88
+ end
78
89
  # $log.debug("nach last_column")
79
90
  result << "\n" if sheet != sheets.last
80
91
  n += 1
@@ -141,7 +152,7 @@ class GenericSpreadsheet
141
152
 
142
153
  # returns the number of the last non-empty row
143
154
  def last_row(sheet=nil)
144
- sheet = @default_sheet unless sheet
155
+ sheet = @default_sheet unless sheet
145
156
  read_cells(sheet) unless @cells_read[sheet]
146
157
  if @last_row[sheet]
147
158
  return @last_row[sheet]
@@ -153,7 +164,7 @@ class GenericSpreadsheet
153
164
  y = y.to_i
154
165
  result = [result, y].max if value
155
166
  }
156
- result = nil if result == impossible_value
167
+ result = nil if result == impossible_value
157
168
  @last_row[sheet] = result
158
169
  result
159
170
  end
@@ -190,7 +201,7 @@ class GenericSpreadsheet
190
201
  return @first_row[sheet]
191
202
  end
192
203
  impossible_value = 999_999 # more than a spreadsheet can hold
193
- result = impossible_value
204
+ result = impossible_value
194
205
  @cell[sheet].each_pair {|key,value|
195
206
  y,x = key.split(',')
196
207
  y = y.to_i
@@ -211,7 +222,7 @@ class GenericSpreadsheet
211
222
  return @first_column[sheet]
212
223
  end
213
224
  impossible_value = 999_999 # more than a spreadsheet can hold
214
- result = impossible_value
225
+ result = impossible_value
215
226
  @cell[sheet].each_pair {|key,value|
216
227
  y,x = key.split(',')
217
228
  x = x.to_i
@@ -221,7 +232,7 @@ class GenericSpreadsheet
221
232
  @first_column[sheet] = result
222
233
  result
223
234
  end
224
-
235
+
225
236
  # convert a number to something like this: 'AB'
226
237
  def GenericSpreadsheet.number_to_letter(n)
227
238
  letters=""
@@ -261,15 +272,15 @@ class GenericSpreadsheet
261
272
  def after(d)
262
273
  if DateTime.now > d
263
274
  yield
264
- end
265
- end
275
+ end
276
+ end
266
277
 
267
278
  # helper method
268
279
  def before(d)
269
- if DateTime.now <= d
280
+ if DateTime.now <= d
270
281
  yield
271
- end
272
- end
282
+ end
283
+ end
273
284
 
274
285
  private
275
286
 
data/lib/roo/google.rb CHANGED
@@ -8,9 +8,9 @@ module GData
8
8
  #-- modified
9
9
  def evaluate_cell(cell, sheet_no=1)
10
10
  raise ArgumentError, "invalid cell: #{cell}" unless cell
11
- raise ArgumentError, "invalid sheet_no: #{sheet_no}" unless sheet_no >0 and sheet_no.class == Fixnum
11
+ raise ArgumentError, "invalid sheet_no: #{sheet_no}" unless sheet_no >0 and sheet_no.class == Fixnum
12
12
  path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/#{@headers ? "private" : "public"}/basic/#{cell}"
13
-
13
+
14
14
  doc = Hpricot(request(path))
15
15
  result = (doc/"content").inner_html
16
16
  end
@@ -26,7 +26,7 @@ module GData
26
26
  result
27
27
  end
28
28
 
29
- # #-- new (testing only)
29
+ # #-- new (testing only)
30
30
  # def raw_url(url)
31
31
  # path = "/feeds/worksheets/#{@spreadsheet_id}/private/basic"
32
32
  # path = url
@@ -38,7 +38,7 @@ module GData
38
38
  path = "/feeds/cells/#{@spreadsheet_id}/1/#{@headers ? 'private' : 'public'}/full"
39
39
  post(path, entry)
40
40
  end
41
-
41
+
42
42
  #-- new
43
43
  def entry_roo(formula, row=1, col=1)
44
44
  <<XML
@@ -47,7 +47,7 @@ module GData
47
47
  </entry>
48
48
  XML
49
49
  end
50
-
50
+
51
51
  #-- new
52
52
  def add_to_cell_roo(row,col,value)
53
53
  save_entry_roo(entry_roo(value,row,col))
@@ -55,41 +55,20 @@ XML
55
55
 
56
56
  #-- new
57
57
  def get_one_sheet
58
- ath = "/feeds/worksheets/#{@spreadsheet_id}/private/basic"
59
58
  path = "/feeds/cells/#{@spreadsheet_id}/1/private/full"
60
59
  doc = Hpricot(request(path))
61
- #pp doc
62
- #p doc # TODO:prey:
63
- # result = (doc/"content[@type='text']").inner_html
64
- # p (doc/"content").inner_html
65
- #result = (doc/"content").inner_html.each { |item| item + '#'}
66
- #-- result = []
67
- #-- (doc/"content").each { |elem|
68
- #-- #p elem
69
- #-- result << elem.inner_html
70
- #-- }
71
- #-- result
72
60
  end
73
61
 
74
62
  #new
75
63
  def oben_unten_links_rechts(sheet_no)
76
- #sheet_no = sheets.index(sheet) + 1
77
64
  path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/private/full"
78
65
  doc = Hpricot(request(path))
79
- #(doc/"entry").each {|item|
80
66
  rows = []
81
67
  cols = []
82
68
  (doc/"gs:cell").each {|item|
83
- # p item
84
- #p item['row']
85
69
  rows.push item['row'].to_i
86
- #p item['col']
87
70
  cols.push item['col'].to_i
88
71
  }
89
- # $log.debug("row min: #{rows.min}")
90
- # $log.debug("row max: #{rows.max}")
91
- # $log.debug("col min: #{cols.min}")
92
- # $log.debug("col max: #{cols.max}")
93
72
  return rows.min, rows.max, cols.min, cols.max
94
73
  end
95
74
 
@@ -97,54 +76,31 @@ XML
97
76
  path = "/feeds/cells/#{@spreadsheet_id}/#{sheet_no}/private/full"
98
77
  doc = Hpricot(request(path))
99
78
  return doc
100
- #(doc/"entry").each {|item|
101
- rows = []
102
- cols = []
103
- (doc/"gs:cell").each {|item|
104
- # p item
105
- #p item['row']
106
- rows.push item['row'].to_i
107
- #p item['col']
108
- cols.push item['col'].to_i
109
- }
110
- # $log.debug("row min: #{rows.min}")
111
- # $log.debug("row max: #{rows.max}")
112
- # $log.debug("col min: #{cols.min}")
113
- # $log.debug("col max: #{cols.max}")
114
- return rows.min, rows.max, cols.min, cols.max
115
79
  end
116
80
  end # class
117
81
  end # module
118
82
 
119
83
  class Google < GenericSpreadsheet
120
84
  #include Log4r
121
-
122
- attr_accessor :header_line
123
85
 
124
- # TIMEOUT_IN_SECONDS = 42
125
- # GOOGLE_MAX_ROWS = 99
126
- # GOOGLE_MAX_COLS = 10 # TODO:
127
-
86
+ attr_accessor :header_line
87
+
128
88
  # Creates a new Google spreadsheet object.
129
89
  def initialize(spreadsheetkey,user=nil,password=nil)
130
90
  @filename = spreadsheetkey
131
91
  # $log = Logger.new("my_log")
132
92
  # $log.outputters = FileOutputter.new("f1", :filename => "roo.log")
133
-
134
- # $log.debug("created a new Google-object")
93
+
94
+ # $log.debug("created a new Google-object")
135
95
  @spreadsheetkey = spreadsheetkey
136
96
  @user = user
137
97
  @password = password
138
- unless user
98
+ unless user
139
99
  user = ENV['GOOGLE_MAIL']
140
100
  end
141
101
  unless password
142
102
  password = ENV['GOOGLE_PASSWORD']
143
103
  end
144
- #p spreadsheetkey
145
- #p user
146
- #p password
147
- #spreadsheetkey = ENV['GOOGLE_KEY']
148
104
  @default_sheet = nil
149
105
  @cell = Hash.new
150
106
  @cell_type = Hash.new
@@ -155,73 +111,28 @@ class Google < GenericSpreadsheet
155
111
  @last_column = Hash.new
156
112
  @cells_read = Hash.new
157
113
  @header_line = 1
158
- #??? @sheets = Array.new
159
-
114
+
160
115
  @gs = GData::Spreadsheet.new(spreadsheetkey)
161
- #@column = FromGData::Spreadsheet.new(spreadsheetkey)
162
116
  @gs.authenticate(user, password)
163
-
164
- #--Test only
165
- #@gs.get_one_sheet
166
- #@gs.oben_unten_links_rechts
167
- #--
117
+
168
118
  #-- ----------------------------------------------------------------------
169
- #-- Behandlung von Berechtigungen hier noch einbauen
119
+ #-- Behandlung von Berechtigungen hier noch einbauen ???
170
120
  #-- ----------------------------------------------------------------------
171
-
172
- #result = gs.add_to_cell formula
173
- #puts gs.evaluate_cell('A1')
174
- #p gs.evaluate_cell('A1')
175
- #puts gs.evaluate_cell('A2')
176
- #puts gs.evaluate_cell('A3')
177
-
178
- #Timeout.timeout(TIMEOUT_IN_SECONDS) {
179
- # @gs = GoogleSpreadSheet.new(spreadsheetkey)
180
- # @gs.authenticate(user, password)
181
- # @default_sheet = nil
182
- #}
183
- # alle eigenen Spreadsheets bei Google
184
- # @spreadsheets= GData::Spreadsheet.spreadsheets("emmanuel.pirsch@gmail.com", "secret") # funktioniert anscheinend noch nicht!!!!!!!!!
185
- # ein einzelnes Spreadsheet bei Google
186
- # @spreadsheet= spreadsheet[spreadsheetname]
187
-
188
- #gb = GData::Base.new
189
- #gb.authenticate("thopre@gmail.com","secret")
190
-
191
- #g = GData::Spreadsheet.new("ttt")
192
- #@default_sheet = nil
121
+
193
122
  if self.sheets.size == 1
194
123
  @default_sheet = self.sheets.first
195
- end
124
+ end
196
125
  end
197
126
 
198
- #def gssheetlist
199
- # @gs.sheetlist
200
- #end
201
-
202
127
  # returns an array of sheet names in the spreadsheet
203
128
  def sheets
204
- #if @sheets == []
205
- # @sheets = @gs.sheetlist
206
- #end
207
- #return @sheets
208
- #p gssheetlist
209
- return @gs.sheetlist
129
+ return @gs.sheetlist
210
130
  end
211
131
 
212
- #def reload
213
- # sav_default_sheet = default_sheet
214
- # super
215
- # @sheets = sheets #[]
216
- # puts "DEBUG: reload: erneutes Einlesen ergibt @sheets=#{@sheets.to_s}"
217
- # @default_sheet = sav_default_sheet
218
- #end
219
-
220
132
  # set the working sheet in the document
221
133
  #--
222
134
  # TODO: eigenlich identisch mit Openoffice => refactoring
223
135
  def default_sheet=(sheet)
224
- #puts "DEBUG: default_sheet=#{sheet}"
225
136
  if ! sheet.kind_of?(String)
226
137
  raise TypeError, "what are you trying to set as default sheet?"
227
138
  end
@@ -249,23 +160,23 @@ class Google < GenericSpreadsheet
249
160
  row,col = normalize(row,col)
250
161
 
251
162
  if celltype(row,col,sheet) == :date
252
- # $log.debug("splitte Datumsfeld auf (#{row},#{col}): #{ @cell[sheet]["#{row},#{col}"]}")
163
+ # $log.debug("splitte Datumsfeld auf (#{row},#{col}): #{ @cell[sheet]["#{row},#{col}"]}")
253
164
  yyyy,mm,dd = @cell[sheet]["#{row},#{col}"].split('-')
254
165
  # $log.debug(yyyy)
255
166
  # $log.debug(mm)
256
167
  # $log.debug(dd)
257
- #TODO:
258
- if dd.to_i < 1 or dd.to_i >31 or mm.to_i < 1 or mm.to_i > 12 or yyyy.to_i < 1900 or yyyy.to_i > 3000
259
- raise "Invalid date parameter: #{yyyy}, #{mm}, #{dd}"
260
- end
168
+ #TODO:
169
+ if dd.to_i < 1 or dd.to_i >31 or mm.to_i < 1 or mm.to_i > 12 or yyyy.to_i < 1900 or yyyy.to_i > 3000
170
+ raise "Invalid date parameter: #{yyyy}, #{mm}, #{dd}"
171
+ end
261
172
  return Date.new(yyyy.to_i,mm.to_i,dd.to_i)
262
173
  end
263
174
  return @cell[sheet]["#{row},#{col}"]
264
175
  end
265
176
 
266
177
  # returns the type of a cell:
267
- # * :float
268
- # * :string,
178
+ # * :float
179
+ # * :string,
269
180
  # * :date
270
181
  # * :percentage
271
182
  def celltype(row, col, sheet=nil)
@@ -278,7 +189,7 @@ end
278
189
  @cell_type[sheet]["#{row},#{col}"]
279
190
  end
280
191
  end
281
-
192
+
282
193
  # Returns the formula at (row,col).
283
194
  # Returns nil if there is no formula.
284
195
  # The method #formula? checks if there is a formula.
@@ -314,25 +225,10 @@ end
314
225
  theformulas << f
315
226
  end
316
227
  }
317
- }
228
+ }
318
229
  theformulas
319
230
  end
320
231
 
321
- # # returns all values in this row as an array
322
- # # row numbers are 1,2,3,... like in the spreadsheet
323
- # def row_old(rownumber,sheet=nil)
324
- # sheet = @default_sheet unless sheet
325
- # result = []
326
- # 1.upto(GOOGLE_MAX_ROWS) { |col| # TODO: maximum size of x-coordinate of google spreadsheet
327
- # result[col] = cell(rownumber,col,sheet)
328
- # }
329
- # result = result[1..-1]
330
- # while result[-1] == '' #TODO: besser?
331
- # result = result[0..-2]
332
- # end
333
- # result
334
- # end
335
-
336
232
  # returns all values in this row as an array
337
233
  # row numbers are 1,2,3,... like in the spreadsheet
338
234
  def row(rownumber,sheet=nil)
@@ -346,15 +242,15 @@ end
346
242
  y = y.to_i
347
243
  if y == rownumber
348
244
  tmp_arr[x] = value
349
- end
350
- }
245
+ end
246
+ }
351
247
  result = tmp_arr[1..-1]
352
- while result[-1] == nil
248
+ while result[-1] == nil
353
249
  result = result[0..-2]
354
- end
250
+ end
355
251
  result
356
- end
357
-
252
+ end
253
+
358
254
  # true, if the cell is empty
359
255
  def empty?(row, col, sheet=nil)
360
256
  value = cell(row, col, sheet)
@@ -363,7 +259,7 @@ end
363
259
  return false if value.class == Float
364
260
  value.empty?
365
261
  end
366
-
262
+
367
263
  # returns all values in this column as an array
368
264
  # column numbers are 1,2,3,... like in the spreadsheet
369
265
  #--
@@ -379,7 +275,7 @@ end
379
275
  result << cell(row,columnnumber,sheet)
380
276
  end
381
277
  result
382
- end
278
+ end
383
279
 
384
280
  # sets the cell to the content of 'value'
385
281
  # a formula can be set in the form of '=SUM(...)'
@@ -407,7 +303,7 @@ end
407
303
  return @last_row[sheet]
408
304
  end
409
305
 
410
- # returns the first non-empty column in a sheet
306
+ # returns the first non-empty column in a sheet
411
307
  def first_column(sheet=nil)
412
308
  sheet = @default_sheet unless sheet
413
309
  unless @first_column[sheet]
@@ -417,7 +313,7 @@ end
417
313
  return @first_column[sheet]
418
314
  end
419
315
 
420
- # returns the last non-empty column in a sheet
316
+ # returns the last non-empty column in a sheet
421
317
  def last_column(sheet=nil)
422
318
  sheet = @default_sheet unless sheet
423
319
  unless @last_column[sheet]
@@ -441,8 +337,8 @@ end
441
337
  end
442
338
  true
443
339
  end
444
-
445
-
340
+
341
+
446
342
  # find a row either by row number or a condition
447
343
  # Caution: this works only within the default sheet -> set default_sheet before you call this method
448
344
  # (experimental. see examples in the test_roo.rb file)
@@ -479,11 +375,11 @@ end
479
375
  x = key
480
376
  end
481
377
  }
482
- tmp[x] = cell(rownum,j)
483
- }
378
+ tmp[x] = cell(rownum,j)
379
+ }
484
380
  result = [ tmp ] # row(rownum)
485
381
  #-- :all
486
- elsif args[0] == :all
382
+ elsif args[0] == :all
487
383
  if args[1].class == Hash
488
384
  args[1].each {|key,val|
489
385
  if key == :conditions
@@ -512,8 +408,8 @@ end
512
408
  x = key
513
409
  end
514
410
  }
515
- tmp[x] = cell(i,j)
516
- }
411
+ tmp[x] = cell(i,j)
412
+ }
517
413
  if result_array
518
414
  result << self.row(i)
519
415
  else
@@ -529,38 +425,9 @@ end
529
425
  end
530
426
  private
531
427
 
532
- # def read_cells_old(sheet=nil) #TODO:
533
- # sheet = @default_sheet unless sheet
534
- # sheet_found = true # TODO:
535
- # #TODO: raise ArgumentError falls sheet nicht existiert - siehe openoffice
536
- # #TODO: boundaries !!!
537
- # 1.upto(25) { |y|
538
- # 1.upto(20) { |x|
539
- # key = "#{y},#{x}"
540
- # @cell[sheet] = {} unless @cell[sheet]
541
- # value = cell(y,x,sheet)
542
- # @cell[sheet][key] = value unless value == "" or value == nil
543
- # }
544
- # }
545
- # if !sheet_found
546
- # raise RangeErrror, "invalid sheet name"
547
- # end
548
- # @cells_read[sheet] = true
549
- # end
550
-
551
- # read all cells in a sheet
428
+ # read all cells in a sheet
552
429
  def read_cells(sheet=nil)
553
430
  sheet = @default_sheet unless sheet
554
- # sheet_no = sheets.index(sheet) + 1
555
- # @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] = @gs.oben_unten_links_rechts(sheet_no)
556
- #@first_row[sheet].upto(@last_row[sheet]) { |y|
557
- # @first_column[sheet].upto(@last_column[sheet]) { |x|
558
- # key = "#{y},#{x}"
559
- # @cell[sheet] = {} unless @cell[sheet]
560
- # value = cell(y,x,sheet)
561
- # @cell[sheet][key] = value unless value == "" or value == nil
562
- # }
563
- #}
564
431
  sheet_no = sheets.index(sheet)+1
565
432
  doc = @gs.fulldoc(sheet_no)
566
433
  (doc/"gs:cell").each {|item|
@@ -568,29 +435,23 @@ end
568
435
  col = item['col']
569
436
  value = item['inputvalue']
570
437
  numericvalue = item['numericvalue']
571
- # puts numericvalue
572
- # puts value
573
- # puts value[0,1]
574
438
  if value[0,1] == '='
575
439
  formula = value
576
- # $log.debug("formula: <#{formula}>")
577
- # puts "Formel gefunden"
440
+ # $log.debug("formula: <#{formula}>")
578
441
  else
579
442
  formula = nil
580
443
  end
581
- # puts formula
582
- #--
583
444
  @cell_type[sheet] = {} unless @cell_type[sheet]
584
- if formula
445
+ if formula
585
446
  ty = :formula
586
- if numeric?(numericvalue)
587
- value = numericvalue.to_f
588
- else
589
- value = numericvalue
590
- end
447
+ if numeric?(numericvalue)
448
+ value = numericvalue.to_f
449
+ else
450
+ value = numericvalue
451
+ end
591
452
  elsif Google.date?(value)
592
453
  ty = :date
593
- elsif numeric?(value) # or o.class ???
454
+ elsif numeric?(value) # or o.class ???
594
455
  ty = :float
595
456
  value = value.to_f
596
457
  else
@@ -600,13 +461,13 @@ end
600
461
  @cell[sheet] = {} unless @cell[sheet]
601
462
  if ty == :date
602
463
  dd,mm,yyyy = value.split('/')
603
- @cell[sheet][key] = sprintf("%04d-%02d-%02d",yyyy.to_i,mm.to_i,dd.to_i)
464
+ @cell[sheet][key] = sprintf("%04d-%02d-%02d",yyyy.to_i,mm.to_i,dd.to_i)
604
465
  else
605
466
  @cell[sheet][key] = value unless value == "" or value == nil
606
467
  end
607
468
  @cell_type[sheet][key] = ty # Openoffice.oo_type_2_roo_type(vt)
608
469
  @formula[sheet] = {} unless @formula[sheet]
609
- # $log.debug("formula vor belegen @formula: <#{formula}>") if formula
470
+ # $log.debug("formula vor belegen @formula: <#{formula}>") if formula
610
471
  @formula[sheet][key] = formula if formula
611
472
  # $log.debug("@formula[#{sheet}][#{key}] = #{formula}") if formula
612
473
  # $log.debug("#{@formula[sheet][key]}") if formula
@@ -616,12 +477,12 @@ end
616
477
  @cells_read[sheet] = true
617
478
  end
618
479
 
619
- # Checks if the default_sheet exists. Otherwise a RangeError exception is
480
+ # Checks if the default_sheet exists. Otherwise a RangeError exception is
620
481
  # raised
621
482
  def check_default_sheet
622
483
  sheet_found = false
623
484
  raise ArgumentError, "Error: default_sheet not set" if @default_sheet == nil
624
- if sheets.index(@default_sheet)
485
+ if sheets.index(@default_sheet)
625
486
  sheet_found = true
626
487
  end
627
488
  if ! sheet_found
@@ -662,10 +523,10 @@ end
662
523
  #TODO: refactor to Generic....
663
524
  def one_cell_output(onecelltype,onecell,empty)
664
525
  str = ""
665
- if empty
526
+ if empty
666
527
  str += ''
667
528
  else
668
- case onecelltype
529
+ case onecelltype
669
530
  when :string
670
531
  if onecell == ""
671
532
  str << ''
@@ -37,13 +37,13 @@ class Openoffice < GenericSpreadsheet
37
37
  @@nr += 1
38
38
  @file_nr = @@nr
39
39
  extract_content
40
- file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_content.xml"))
40
+ file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_content.xml"))
41
41
  @doc = REXML::Document.new file
42
42
  file.close
43
43
  #if ENV["roo_local"] != "thomas-p"
44
44
  FileUtils::rm_r(@tmpdir)
45
45
  #end
46
- @default_sheet = nil
46
+ @default_sheet = nil
47
47
  # no need to set default_sheet if there is only one sheet in the document
48
48
  if self.sheets.size == 1
49
49
  @default_sheet = self.sheets.first
@@ -122,12 +122,12 @@ class Openoffice < GenericSpreadsheet
122
122
  set_type(row,col,:string,sheet)
123
123
  else
124
124
  raise ArgumentError, "Type for "+value.to_s+" not set"
125
- end
125
+ end
126
126
  end
127
127
 
128
128
  # returns the type of a cell:
129
- # * :float
130
- # * :string,
129
+ # * :float
130
+ # * :string,
131
131
  # * :date
132
132
  # * :percentage
133
133
  def celltype(row,col,sheet=nil)
@@ -179,7 +179,7 @@ class Openoffice < GenericSpreadsheet
179
179
 
180
180
  alias set_default_sheet default_sheet=
181
181
 
182
- # version of the openoffice document
182
+ # version of the openoffice document
183
183
  # at 2007 this is always "1.0"
184
184
  def officeversion
185
185
  # read_cells(false) unless @cells_read
@@ -216,7 +216,7 @@ class Openoffice < GenericSpreadsheet
216
216
  end
217
217
  result
218
218
  end
219
-
219
+
220
220
  # returns all values in this column as an array
221
221
  # column numbers are 1,2,3,... like in the spreadsheet
222
222
  def column(columnnumber,sheet=nil)
@@ -230,14 +230,14 @@ class Openoffice < GenericSpreadsheet
230
230
  result << cell(row,columnnumber,sheet)
231
231
  end
232
232
  result
233
- end
233
+ end
234
234
 
235
235
  # save spreadsheet
236
236
  def save #:nodoc:
237
237
  42
238
238
  end
239
239
 
240
- # evaluate the formula at this cell
240
+ # evaluate the formula at this cell
241
241
  # experimental: DO NOT USE THIS!
242
242
  def solve(row,col) #:nodoc:
243
243
  parser = SpreadsheetParser.new
@@ -264,12 +264,12 @@ class Openoffice < GenericSpreadsheet
264
264
  theformulas << f
265
265
  end
266
266
  }
267
- }
267
+ }
268
268
  theformulas
269
269
  end
270
-
270
+
271
271
  # write the current spreadsheet to stdout or into a file
272
- #TODO: refactoring --> GenericSpreadsheet
272
+ #TODO: refactoring --> GenericSpreadsheet
273
273
 
274
274
  def to_csv(filename=nil,sheet=nil)
275
275
  sheet = @default_sheet unless sheet
@@ -313,11 +313,11 @@ class Openoffice < GenericSpreadsheet
313
313
  x = key
314
314
  end
315
315
  }
316
- tmp[x] = cell(rownum,j)
317
- }
316
+ tmp[x] = cell(rownum,j)
317
+ }
318
318
  result = [ tmp ] # row(rownum)
319
319
  #-- :all
320
- elsif args[0] == :all
320
+ elsif args[0] == :all
321
321
  if args[1].class == Hash
322
322
  args[1].each {|key,val|
323
323
  if key == :conditions
@@ -346,8 +346,8 @@ class Openoffice < GenericSpreadsheet
346
346
  x = key
347
347
  end
348
348
  }
349
- tmp[x] = cell(i,j)
350
- }
349
+ tmp[x] = cell(i,j)
350
+ }
351
351
  if result_array
352
352
  result << self.row(i)
353
353
  else
@@ -362,7 +362,7 @@ class Openoffice < GenericSpreadsheet
362
362
  result
363
363
  end
364
364
 
365
-
365
+
366
366
  private
367
367
 
368
368
  # read the version of the OO-Version
@@ -377,22 +377,22 @@ class Openoffice < GenericSpreadsheet
377
377
  def set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v)
378
378
  key = "#{y},#{x+i}"
379
379
  @cell_type[sheet] = {} unless @cell_type[sheet]
380
- @cell_type[sheet][key] = Openoffice.oo_type_2_roo_type(vt)
380
+ @cell_type[sheet][key] = Openoffice.oo_type_2_roo_type(vt)
381
381
  @formula[sheet] = {} unless @formula[sheet]
382
382
  @formula[sheet][key] = formula if formula
383
383
  @cell[sheet] = {} unless @cell[sheet]
384
- case @cell_type[sheet][key]
384
+ case @cell_type[sheet][key]
385
385
  when :float
386
- @cell[sheet][key] = v.to_f
386
+ @cell[sheet][key] = v.to_f
387
387
  when :string
388
- @cell[sheet][key] = str_v
388
+ @cell[sheet][key] = str_v
389
389
  when :date
390
- @cell[sheet][key] = tr.attributes['date-value']
390
+ @cell[sheet][key] = tr.attributes['date-value']
391
391
  when :percentage
392
- @cell[sheet][key] = v.to_f
392
+ @cell[sheet][key] = v.to_f
393
393
  else
394
- @cell[sheet][key] = v
395
- end
394
+ @cell[sheet][key] = v
395
+ end
396
396
  end
397
397
 
398
398
  # read all cells in the selected sheet
@@ -425,7 +425,7 @@ class Openoffice < GenericSpreadsheet
425
425
  rep = te.attributes["number-columns-repeated"]
426
426
  elsif te.name == "table-row"
427
427
  if te.attributes['number-rows-repeated']
428
- skip_y = te.attributes['number-rows-repeated'].to_i
428
+ skip_y = te.attributes['number-rows-repeated'].to_i
429
429
  y = y + skip_y - 1 # minus 1 because this line will be counted as a line element
430
430
  end
431
431
  te.each_element do |tr|
@@ -472,7 +472,7 @@ class Openoffice < GenericSpreadsheet
472
472
  x = 1
473
473
  end
474
474
  end
475
- end # sheet
475
+ end # sheet
476
476
  end
477
477
  end
478
478
  end
@@ -480,13 +480,13 @@ class Openoffice < GenericSpreadsheet
480
480
  end
481
481
  end
482
482
  end
483
- if !sheet_found
484
- raise RangeError
483
+ if !sheet_found
484
+ raise RangeError
485
485
  end
486
486
  @cells_read[sheet] = true
487
487
  end
488
488
 
489
- # Checks if the default_sheet exists. If not an RangeError exception is
489
+ # Checks if the default_sheet exists. If not an RangeError exception is
490
490
  # raised
491
491
  def check_default_sheet
492
492
  sheet_found = false
@@ -502,7 +502,7 @@ class Openoffice < GenericSpreadsheet
502
502
  if se.name == "table"
503
503
  if se.attributes['name'] == @default_sheet
504
504
  sheet_found = true
505
- end # sheet
505
+ end # sheet
506
506
  end
507
507
  end
508
508
  end
@@ -519,17 +519,17 @@ class Openoffice < GenericSpreadsheet
519
519
  if zip.file.file? path
520
520
  if path == "content.xml"
521
521
  open(@tmpdir+'/'+@file_nr.to_s+'_roo_content.xml','wb') {|f|
522
- f << zip.read(path)
522
+ f << zip.read(path)
523
523
  }
524
- end
524
+ end
525
525
  else
526
526
  unless path.empty?
527
- path += '/'
528
- end
527
+ path += '/'
528
+ end
529
529
  zip.dir.foreach(path) do |filename|
530
530
  process_zipfile(zip, path+filename)
531
- end
532
- end
531
+ end
532
+ end
533
533
  end
534
534
 
535
535
  def extract_content
@@ -559,7 +559,7 @@ class Openoffice < GenericSpreadsheet
559
559
  return A_ROO_TYPE[ootype]
560
560
  end
561
561
 
562
-
562
+
563
563
  #TODO: refactoring to GenericSpreadsheet?
564
564
  def write_csv_content(file=nil,sheet=nil)
565
565
  file = STDOUT unless file
@@ -576,13 +576,13 @@ class Openoffice < GenericSpreadsheet
576
576
  end
577
577
  end
578
578
 
579
- #TODO: refactor to Generic...
579
+ #TODO: refactor to Generic...
580
580
  def one_cell_output(onecelltype,onecell,empty)
581
581
  str = ""
582
- if empty
582
+ if empty
583
583
  str += ''
584
584
  else
585
- case onecelltype
585
+ case onecelltype
586
586
  when :string
587
587
  if onecell == ""
588
588
  str << ''
@@ -623,7 +623,7 @@ class Openoffice < GenericSpreadsheet
623
623
  str
624
624
  end
625
625
 
626
- # helper method to convert compressed spaces and other elements within
626
+ # helper method to convert compressed spaces and other elements within
627
627
  # an text into a string
628
628
  def children_to_string(children)
629
629
  result = ''
data/lib/roo/version.rb CHANGED
@@ -2,7 +2,7 @@ module Roo #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 8
5
- TINY = 0
5
+ TINY = 1
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
Binary file
data/test/bbu.ods ADDED
Binary file
data/test/bbu.xls ADDED
Binary file
Binary file
Binary file
data/test/test_roo.rb CHANGED
@@ -20,13 +20,14 @@ def local_only
20
20
  end
21
21
 
22
22
  DISPLAY_LOG = false
23
- DB_LOG = true
23
+ DB_LOG = false
24
24
 
25
25
  if DB_LOG
26
26
  # gem 'activerecord', '< 2.0.0'
27
27
  # require 'activerecord'
28
- require_gem 'activerecord', '< 2.0.0'
29
- #require 'activerecord'
28
+ # require_gem 'activerecord', '< 2.0.0'
29
+ gem 'activerecord', '< 2.0.0'
30
+ require 'activerecord'
30
31
  end
31
32
 
32
33
  include FileUtils
@@ -125,7 +126,7 @@ class TestRoo < Test::Unit::TestCase
125
126
  GOOGLE = true # do Google-Spreadsheet Tests?
126
127
 
127
128
  OPENOFFICEWRITE = false # experimental: write access with OO-Documents
128
- ONLINE = false
129
+ ONLINE = true
129
130
  LONG_RUN = false
130
131
  GLOBAL_TIMEOUT = 2*12*60 # seconds
131
132
 
@@ -2416,4 +2417,80 @@ end
2416
2417
  assert_equal "hello from the tests", oo.cell(1,1)
2417
2418
  end
2418
2419
  end
2420
+
2421
+ def test_bug_bbu_openoffice
2422
+ oo = Openoffice.new(File.join('test','bbu.ods'))
2423
+ assert_nothing_raised() {
2424
+ assert_equal "File: test/bbu.ods
2425
+ Number of sheets: 3
2426
+ Sheets: 2007_12, Tabelle2, Tabelle3
2427
+ Sheet 1:
2428
+ First row: 1
2429
+ Last row: 4
2430
+ First column: A
2431
+ Last column: F
2432
+ Sheet 2:
2433
+ - empty -
2434
+ Sheet 3:
2435
+ - empty -", oo.info
2436
+ }
2437
+
2438
+ oo.default_sheet = oo.sheets[1] # empty sheet
2439
+ assert_nil oo.first_row
2440
+ assert_nil oo.last_row
2441
+ assert_nil oo.first_column
2442
+ assert_nil oo.last_column
2443
+ end
2444
+
2445
+ def test_bug_bbu_excel
2446
+ oo = Excel.new(File.join('test','bbu.xls'))
2447
+ assert_nothing_raised() {
2448
+ assert_equal "File: test/bbu.xls
2449
+ Number of sheets: 3
2450
+ Sheets: 2007_12, Tabelle2, Tabelle3
2451
+ Sheet 1:
2452
+ First row: 1
2453
+ Last row: 4
2454
+ First column: A
2455
+ Last column: F
2456
+ Sheet 2:
2457
+ - empty -
2458
+ Sheet 3:
2459
+ - empty -", oo.info
2460
+ }
2461
+
2462
+ oo.default_sheet = oo.sheets[1] # empty sheet
2463
+ assert_nil oo.first_row
2464
+ assert_nil oo.last_row
2465
+ assert_nil oo.first_column
2466
+ assert_nil oo.last_column
2467
+ end
2468
+
2469
+ if false
2470
+ # there is no google spreadsheet for this test
2471
+ def test_bug_bbu_google
2472
+ oo = Excel.new(key_of('bbu'))
2473
+ assert_nothing_raised() {
2474
+ assert_equal "File: test/bbu.xls
2475
+ Number of sheets: 3
2476
+ Sheets: 2007_12, Tabelle2, Tabelle3
2477
+ Sheet 1:
2478
+ First row: 1
2479
+ Last row: 4
2480
+ First column: A
2481
+ Last column: F
2482
+ Sheet 2:
2483
+ - empty -
2484
+ Sheet 3:
2485
+ - empty -", oo.info
2486
+ }
2487
+
2488
+ oo.default_sheet = oo.sheets[1] # empty sheet
2489
+ assert_nil oo.first_row
2490
+ assert_nil oo.last_row
2491
+ assert_nil oo.first_column
2492
+ assert_nil oo.last_column
2493
+ end
2494
+ end # false
2495
+
2419
2496
  end # class
data/website/index.html CHANGED
@@ -33,7 +33,7 @@
33
33
  <h1>roo</h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/roo"; return false'>
35
35
  Get Version
36
- <a href="http://rubyforge.org/projects/roo" class="numbers">0.8.0</a>
36
+ <a href="http://rubyforge.org/projects/roo" class="numbers">0.8.1</a>
37
37
  </div>
38
38
  <h2>What</h2>
39
39
 
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
5
- platform: ""
4
+ version: 0.8.1
5
+ platform: ruby
6
6
  authors:
7
7
  - Thomas Preymesser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2007-12-16 00:00:00 +01:00
12
+ date: 2007-12-22 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -78,6 +78,13 @@ files:
78
78
  - lib/roo/google.rb
79
79
  - scripts/txt2html
80
80
  - setup.rb
81
+ - test/false_encoding.xls
82
+ - test/Bibelbund1.ods
83
+ - test/bbu.xls
84
+ - test/bbu.ods
85
+ - test/simple_spreadsheet.ods
86
+ - test/simple_spreadsheet_from_italo.ods
87
+ - test/simple_spreadsheet_from_italo.xls
81
88
  - test/test_helper.rb
82
89
  - test/test_roo.rb
83
90
  - test/numbers1.ods
@@ -119,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
126
  requirements: []
120
127
 
121
128
  rubyforge_project: roo
122
- rubygems_version: 0.9.5
129
+ rubygems_version: 1.0.1
123
130
  signing_key:
124
131
  specification_version: 2
125
132
  summary: roo can access the contents of OpenOffice-, Excel- or Google-Spreadsheets