roo 1.9.6 → 1.9.7

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,4 +1,10 @@
1
+ == 1.9.7 2011-08-27
2
+
3
+ * 1 bugfix
4
+ * Openoffice: Better way for extracting formula strings, some characters were deleted at the formula string under some circumstances.
5
+
1
6
  == 1.9.6 2011-08-03
7
+
2
8
  * 1 enhancement
3
9
  * new class Libreoffice (Libreoffice should do exactly the same as the Openoffice
4
10
  class. It's just another name. Technically, Libreoffice is inherited from
data/bin/roo CHANGED
@@ -26,7 +26,8 @@ Choice.options do
26
26
  long '--info <spreadsheetfile>'
27
27
  desc 'Show information about a spreadsheet file'
28
28
  action do
29
- puts '#'
29
+ p Choice.choices
30
+ puts 'Filename: '+Choice.choices['info']
30
31
  end
31
32
  end
32
33
  end
data/lib/roo.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Roo
4
4
 
5
5
  # :stopdoc:
6
- VERSION = '1.9.6'
6
+ VERSION = '1.9.7'
7
7
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
8
8
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
9
9
  # :startdoc:
data/lib/roo/excel.rb CHANGED
@@ -100,8 +100,7 @@ class Excel < GenericSpreadsheet
100
100
  def initialize(filename, packed = nil, file_warning = :error)
101
101
  super()
102
102
  @file_warning = file_warning
103
- file_type_check(filename,'.xls','an Excel',packed)
104
- # @tmpdir = "oo_"+$$.to_s
103
+ file_type_check(filename,'.xls','an Excel',packed)
105
104
  @tmpdir = GenericSpreadsheet.next_tmpdir
106
105
  @tmpdir = File.join(ENV['ROO_TMP'], @tmpdir) if ENV['ROO_TMP']
107
106
  unless File.exists?(@tmpdir)
@@ -110,36 +109,19 @@ class Excel < GenericSpreadsheet
110
109
  filename = open_from_uri(filename) if filename[0,7] == "http://"
111
110
  filename = open_from_stream(filename[7..-1]) if filename[0,7] == "stream:"
112
111
  filename = unzip(filename) if packed and packed == :zip
113
- #begin
114
- #begin
115
- # file_type_check(filename,'.xls','an Excel')
116
- #rescue TypeError
117
- # #FileUtils::rm_r @tmpdir
118
- # raise
119
- #end
120
- @filename = filename
121
- unless File.file?(@filename)
122
- FileUtils::rm_r(@tmpdir)
123
- raise IOError, "file #{@filename} does not exist"
124
- end
125
- begin
126
- @workbook = Spreadsheet.open(filename)
127
- rescue Ole::Storage::FormatError
128
- FileUtils::rm_r(@tmpdir)
129
- raise # nach aussen weiterhin sichtbar
130
- end
131
- @default_sheet = self.sheets.first
132
- #ensure
133
- #if ENV["roo_local"] != "thomas-p"
134
- # ich glaube ich darf hier noch nicht die temporaere
135
- # Datei loeschen, weil
136
- #to do
137
- #"Loeschen temp. Directory anpassen"
138
- #end
139
- #end
140
- #if fremdrechner?
112
+ @filename = filename
113
+ unless File.file?(@filename)
114
+ FileUtils::rm_r(@tmpdir)
115
+ raise IOError, "file #{@filename} does not exist"
116
+ end
117
+ begin
118
+ @workbook = Spreadsheet.open(filename)
119
+ rescue Ole::Storage::FormatError
141
120
  FileUtils::rm_r(@tmpdir)
142
- #end
121
+ raise # nach aussen weiterhin sichtbar
122
+ end
123
+ @default_sheet = self.sheets.first
124
+ FileUtils::rm_r(@tmpdir)
143
125
  @cell = Hash.new
144
126
  @cell_type = Hash.new
145
127
  @formula = Hash.new
@@ -154,11 +136,7 @@ class Excel < GenericSpreadsheet
154
136
 
155
137
  # returns an array of sheet names in the spreadsheet
156
138
  def sheets
157
- result = []
158
- @workbook.worksheets.each do |worksheet|
159
- result << normalize_string(worksheet.name)
160
- end
161
- return result
139
+ @workbook.worksheets.collect {|worksheet| normalize_string(worksheet.name)}
162
140
  end
163
141
 
164
142
  # returns the content of a cell. The upper left corner is (1,1) or ('A',1)
@@ -175,7 +153,6 @@ class Excel < GenericSpreadsheet
175
153
  if celltype(row,col,sheet) == :string
176
154
  return platform_specific_iconv(@cell[sheet][[row,col]])
177
155
  else
178
- #return @cell[sheet][[row,col]]
179
156
  if @cell[sheet] and @cell[sheet][[row,col]]
180
157
  return @cell[sheet][[row,col]]
181
158
  else
@@ -200,7 +177,6 @@ class Excel < GenericSpreadsheet
200
177
  if @formula[sheet] and @formula[sheet][[row,col]]
201
178
  return :formula
202
179
  else
203
- # @cell_type[sheet][[row,col]]
204
180
  if @cell_type[sheet] and @cell_type[sheet][[row,col]]
205
181
  return @cell_type[sheet][[row,col]]
206
182
  else
@@ -354,7 +330,7 @@ class Excel < GenericSpreadsheet
354
330
  @fonts[sheet] = {} unless @fonts[sheet]
355
331
  @fonts[sheet][key] = font
356
332
 
357
- case vt # @cell_type[sheet][key]
333
+ case vt
358
334
  when :float
359
335
  @cell[sheet][key] = v.to_f
360
336
  when :string
@@ -388,7 +364,7 @@ class Excel < GenericSpreadsheet
388
364
  (0..row.size).each do |cell_index|
389
365
  cell = row.at(cell_index)
390
366
  next if cell.nil? #skip empty cells
391
- next if cell.class == Spreadsheet::Formula && cell.value.nil? # skip empty formla cells
367
+ next if cell.class == Spreadsheet::Formula && cell.value.nil? # skip empty formula cells
392
368
  if date_or_time?(row, cell_index)
393
369
  vt, v = read_cell_date_or_time(row, cell_index)
394
370
  else
@@ -484,18 +460,4 @@ class Excel < GenericSpreadsheet
484
460
  end
485
461
  private :read_cell
486
462
 
487
- #TODO: testing only
488
- # def inject_null_characters(str)
489
- # if str.class != String
490
- # return str
491
- # end
492
- # new_str=''
493
- # 0.upto(str.size-1) do |i|
494
- # new_str += str[i,1]
495
- # new_str += "\000"
496
- # end
497
- # new_str
498
- # end
499
- #
500
-
501
463
  end
data/lib/roo/excelx.rb CHANGED
@@ -1,4 +1,3 @@
1
- #TODO: require 'xml'
2
1
  require 'fileutils'
3
2
  require 'zip/zipfilesystem'
4
3
  require 'date'
@@ -87,8 +86,7 @@ class Excelx < GenericSpreadsheet
87
86
  def initialize(filename, packed=nil, file_warning = :error) #, create = false)
88
87
  super()
89
88
  @file_warning = file_warning
90
- file_type_check(filename,'.xlsx','an Excel-xlsx',packed)
91
- #@tmpdir = "oo_"+$$.to_s
89
+ file_type_check(filename,'.xlsx','an Excel-xlsx',packed)
92
90
  @tmpdir = GenericSpreadsheet.next_tmpdir
93
91
  @tmpdir = File.join(ENV['ROO_TMP'], @tmpdir) if ENV['ROO_TMP']
94
92
  unless File.exists?(@tmpdir)
@@ -96,52 +94,39 @@ class Excelx < GenericSpreadsheet
96
94
  end
97
95
  filename = open_from_uri(filename) if filename[0,7] == "http://"
98
96
  filename = unzip(filename) if packed and packed == :zip
99
- #begin
100
- #file_type_check(filename,'.xlsx','an Excel-xlsx')
101
- @cells_read = Hash.new
102
- @filename = filename
103
- unless File.file?(@filename)
104
- FileUtils::rm_r(@tmpdir)
105
- raise IOError, "file #{@filename} does not exist"
106
- end
107
- @@nr += 1
108
- @file_nr = @@nr
109
- extract_content(@filename)
110
- file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_workbook.xml"))
111
- # TODO: @workbook_doc = XML::Parser.io(file).parse
112
- @workbook_doc = Nokogiri::XML(file)
113
-
114
-
97
+ @cells_read = Hash.new
98
+ @filename = filename
99
+ unless File.file?(@filename)
100
+ FileUtils::rm_r(@tmpdir)
101
+ raise IOError, "file #{@filename} does not exist"
102
+ end
103
+ @@nr += 1
104
+ @file_nr = @@nr
105
+ extract_content(@filename)
106
+ file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_workbook.xml"))
107
+ @workbook_doc = Nokogiri::XML(file)
108
+ file.close
109
+ @shared_table = []
110
+ if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
111
+ file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
112
+ @sharedstring_doc = Nokogiri::XML(file)
115
113
  file.close
116
- @shared_table = []
117
- if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
118
- file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_sharedStrings.xml'))
119
- #TODO: @sharedstring_doc = XML::Parser.io(file).parse
120
- @sharedstring_doc = Nokogiri::XML(file)
121
- file.close
122
- read_shared_strings(@sharedstring_doc)
123
- end
124
- @styles_table = []
125
- @style_definitions = Array.new # TODO: ??? { |h,k| h[k] = {} }
126
- if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
127
- file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
128
- #TODO: @styles_doc = XML::Parser.io(file).parse
129
- @styles_doc = Nokogiri::XML(file)
130
- file.close
131
- read_styles(@styles_doc)
132
- end
133
- @sheet_doc = []
134
- @sheet_files.each_with_index do |item, i|
135
- file = File.new(item)
136
- #TODO: @sheet_doc[i] = XML::Parser.io(file).parse
137
- @sheet_doc[i] = Nokogiri::XML(file)
138
- file.close
139
- end
140
- #ensure
141
- #if ENV["roo_local"] != "thomas-p"
142
- #FileUtils::rm_r(@tmpdir)
143
- #end
144
- #end
114
+ read_shared_strings(@sharedstring_doc)
115
+ end
116
+ @styles_table = []
117
+ @style_definitions = Array.new # TODO: ??? { |h,k| h[k] = {} }
118
+ if File.exist?(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
119
+ file = File.new(File.join(@tmpdir, @file_nr.to_s+'_roo_styles.xml'))
120
+ @styles_doc = Nokogiri::XML(file)
121
+ file.close
122
+ read_styles(@styles_doc)
123
+ end
124
+ @sheet_doc = []
125
+ @sheet_files.each_with_index do |item, i|
126
+ file = File.new(item)
127
+ @sheet_doc[i] = Nokogiri::XML(file)
128
+ file.close
129
+ end
145
130
  FileUtils::rm_r(@tmpdir)
146
131
  @default_sheet = self.sheets.first
147
132
  @cell = Hash.new
@@ -296,13 +281,12 @@ class Excelx < GenericSpreadsheet
296
281
  # returns an array of sheet names in the spreadsheet
297
282
  def sheets
298
283
  return_sheets = []
299
- #TODO: @workbook_doc.find("//*[local-name()='sheet']").each do |sheet|
300
284
  @workbook_doc.xpath("//*[local-name()='sheet']").each do |sheet|
301
- #TODO: return_sheets << sheet.attributes.to_h['name']
302
285
  return_sheets << sheet['name']
303
286
  end
304
287
  return_sheets
305
288
  end
289
+
306
290
  # shows the internal representation of all cells
307
291
  # for debugging purposes
308
292
  def to_s(sheet=nil)
@@ -315,9 +299,9 @@ class Excelx < GenericSpreadsheet
315
299
 
316
300
  # helper function to set the internal representation of cells
317
301
  def set_cell_values(sheet,x,y,i,v,vt,formula,tr,str_v,
318
- excelx_type=nil,
319
- excelx_value=nil,
320
- s_attribute=nil)
302
+ excelx_type=nil,
303
+ excelx_value=nil,
304
+ s_attribute=nil)
321
305
  key = [y,x+i]
322
306
  @cell_type[sheet] = {} unless @cell_type[sheet]
323
307
  @cell_type[sheet][key] = vt
@@ -390,18 +374,13 @@ class Excelx < GenericSpreadsheet
390
374
  raise ArgumentError, "Error: sheet '#{sheet||'nil'}' not valid" if @default_sheet == nil and sheet==nil
391
375
  raise RangeError unless self.sheets.include? sheet
392
376
  n = self.sheets.index(sheet)
393
- #TODO: @sheet_doc[n].find("//*[local-name()='c']").each do |c|
394
377
  @sheet_doc[n].xpath("//*[local-name()='c']").each do |c|
395
- #TODO: s_attribute = c.attributes.to_h['s'].to_i # should be here
396
378
  s_attribute = c['s'].to_i # should be here
397
- #TODO: if (c.attributes.to_h['t'] == 's')
398
379
  # c: <c r="A5" s="2">
399
380
  # <v>22606</v>
400
381
  # </c>, format: , tmp_type: float
401
-
402
382
  if c['t'] == 's'
403
383
  tmp_type = :shared
404
- #TODO: elsif (c.attributes.to_h['t'] == 'b')
405
384
  elsif c['t'] == 'b'
406
385
  tmp_type = :boolean
407
386
  # 2011-02-25 BEGIN
@@ -409,19 +388,15 @@ class Excelx < GenericSpreadsheet
409
388
  tmp_type = :string
410
389
  # 2011-02-25 END
411
390
  else
412
- #s_attribute = c.attributes.to_h['s'].to_i # was here
413
- s_attribute = c['s'].to_i # was here
391
+ s_attribute = c['s'].to_i
414
392
  format = attribute2format(s_attribute)
415
393
  tmp_type = format2type(format)
416
394
  end
417
395
  formula = nil
418
- #TODO: c.each_element do |cell|
419
396
  c.children.each do |cell|
420
- #TODO: if cell.name == 'f'
421
397
  if cell.name == 'f'
422
398
  formula = cell.content
423
399
  end
424
- #TODO: if cell.name == 'v'
425
400
  if cell.name == 'v'
426
401
  if tmp_type == :time or tmp_type == :datetime
427
402
  if cell.content.to_f >= 1.0
@@ -464,8 +439,6 @@ class Excelx < GenericSpreadsheet
464
439
  vt = :float
465
440
  v = cell.content
466
441
  end
467
- #puts "vt: #{vt}" if cell.text.include? "22606.5120"
468
- #TODO: x,y = split_coordinate(c.attributes.to_h['r'])
469
442
  x,y = split_coordinate(c['r'])
470
443
  tr=nil #TODO: ???s
471
444
  set_cell_values(sheet,x,y,0,v,vt,formula,tr,str_v,excelx_type,excelx_value,s_attribute)
@@ -546,13 +519,10 @@ class Excelx < GenericSpreadsheet
546
519
 
547
520
  # read the shared strings xml document
548
521
  def read_shared_strings(doc)
549
- #TODO: doc.find("//*[local-name()='si']").each do |si|
550
522
  doc.xpath("//*[local-name()='si']").each do |si|
551
523
  shared_table_entry = ''
552
- #TODO: si.each_element do |elem|
553
524
  si.children.each do |elem|
554
525
  if elem.name == 'r' and elem.children
555
- # elem.each_element do |r_elem|
556
526
  elem.children.each do |r_elem|
557
527
  if r_elem.name == 't'
558
528
  shared_table_entry << r_elem.content
@@ -573,19 +543,13 @@ class Excelx < GenericSpreadsheet
573
543
  @cellXfs = []
574
544
  fonts = []
575
545
 
576
- #TODO: doc.find("//*[local-name()='numFmt']").each do |numFmt|
577
546
  doc.xpath("//*[local-name()='numFmt']").each do |numFmt|
578
- # TODO: numFmtId = numFmt.attributes.to_h['numFmtId']
579
547
  numFmtId = numFmt.attributes['numFmtId']
580
- #TODO: formatCode = numFmt.attributes.to_h['formatCode']
581
548
  formatCode = numFmt.attributes['formatCode']
582
549
  @numFmts << [numFmtId, formatCode]
583
550
  end
584
- #TODO: doc.find("//*[local-name()='fonts']").each do |fonts_el|
585
551
  doc.xpath("//*[local-name()='fonts']").each do |fonts_el|
586
- #TODO: fonts_el.each_element do |font_el|
587
552
  fonts_el.children.each do |font_el|
588
- #TODO: if font_el.name == 'font'
589
553
  if font_el == 'font'
590
554
  font = Excelx::Font.new
591
555
  font_el.each_element do |font_sub_el|
@@ -603,13 +567,10 @@ class Excelx < GenericSpreadsheet
603
567
  end
604
568
  end
605
569
 
606
- #TODO: doc.find("//*[local-name()='cellXfs']").each do |xfs|
607
570
  doc.xpath("//*[local-name()='cellXfs']").each do |xfs|
608
571
  xfs.children.each do |xf|
609
- #TODO: numFmtId = xf.attributes.to_h['numFmtId']
610
572
  numFmtId = xf['numFmtId']
611
573
  @cellXfs << [numFmtId]
612
- #TODO: fontId = xf.attributes.to_h['fontId'].to_i
613
574
  fontId = xf['fontId'].to_i
614
575
  @style_definitions << fonts[fontId]
615
576
  end
@@ -620,7 +581,6 @@ class Excelx < GenericSpreadsheet
620
581
  def attribute2format(s)
621
582
  result = nil
622
583
  @numFmts.each {|nf|
623
- #TODO: if nf.first == @cellXfs[s.to_i].first
624
584
  # to_s weil das eine Nokogiri::XML::Attr und das
625
585
  # andere ein String ist
626
586
  if nf.first.to_s == @cellXfs[s.to_i].first
@@ -6,8 +6,6 @@ class GenericSpreadsheet
6
6
 
7
7
  attr_reader :default_sheet
8
8
 
9
- @@class_counter = 0
10
-
11
9
  # sets the line with attribute names (default: 1)
12
10
  attr_accessor :header_line
13
11
 
@@ -30,11 +28,8 @@ class GenericSpreadsheet
30
28
  end
31
29
 
32
30
  def self.next_tmpdir
33
- @@class_counter += 1
34
- # tmpdir = "oo_"+$$.to_s+"_"+sprintf("%04d",@@class_counter)
35
- tmpdir = "oo_"+$$.to_s+"_"+sprintf("%010d",rand(10_000_000_000))
36
- # p "@tmpdir = #{tmpdir}"; sleep 5
37
- tmpdir
31
+ tmpdir = "oo_"+$$.to_s+"_"+sprintf("%010d",rand(10_000_000_000))
32
+ tmpdir
38
33
  end
39
34
 
40
35
 
@@ -333,9 +328,14 @@ class GenericSpreadsheet
333
328
  def reload
334
329
  # von Abfrage der Klasse direkt auf .to_s == '..' umgestellt
335
330
  ds = @default_sheet
336
- initialize(@filename) if self.class.to_s == 'Openoffice' or
337
- self.class.to_s == 'Excel'
338
- initialize(@spreadsheetkey,@user,@password) if self.class.to_s == 'Google'
331
+ if self.class.to_s == 'Google'
332
+ initialize(@spreadsheetkey,@user,@password)
333
+ else
334
+ initialize(@filename)
335
+ to do
336
+ 'was ist mit weiteren Parametern bei initialize'
337
+ end
338
+ end
339
339
  self.default_sheet = ds
340
340
  #@first_row = @last_row = @first_column = @last_column = nil
341
341
  end
@@ -354,13 +354,7 @@ class GenericSpreadsheet
354
354
  # recursively removes the current temporary directory
355
355
  # this is only needed if you work with zipped files or files via the web
356
356
  def remove_tmp
357
- #to do
358
- # "remove_tmp wieder aktivieren"
359
- #end
360
- #return
361
- #$log.debug("remove_tmp('#{@tmpdir}')")
362
357
  if File.exists?(@tmpdir)
363
- #$log.debug("#{@tmpdir} exists")
364
358
  FileUtils::rm_r(@tmpdir)
365
359
  end
366
360
  end
@@ -441,12 +435,11 @@ class GenericSpreadsheet
441
435
  sheet = @default_sheet unless sheet
442
436
  read_cells(sheet) unless @cells_read[sheet]
443
437
  return theformulas unless first_row(sheet) # if there is no first row then
444
- # there can't be formulas
438
+ # there can't be formulas
445
439
  first_row(sheet).upto(last_row(sheet)) {|row|
446
440
  first_column(sheet).upto(last_column(sheet)) {|col|
447
441
  if formula?(row,col,sheet)
448
- f = [row, col, formula(row,col,sheet)]
449
- theformulas << f
442
+ theformulas << [row, col, formula(row,col,sheet)]
450
443
  end
451
444
  }
452
445
  }
@@ -592,17 +585,12 @@ class GenericSpreadsheet
592
585
  if ! sheet_found
593
586
  raise RangeError, "sheet '#{@default_sheet}' not found"
594
587
  end
595
- #raise ArgumentError, "Error: default_sheet not set" if @default_sheet == nil
596
588
  end
597
589
 
598
590
  def process_zipfile_packed(zip, path='')
599
591
  ret=nil
600
592
  if zip.file.file? path
601
593
  # extract and return filename
602
- #2011-08-01 @tmpdir = "oo_"+$$.to_s
603
- #2011-08-01 unless File.exists?(@tmpdir)
604
- #2011-08-01 FileUtils::mkdir(@tmpdir)
605
- #2011-08-01end
606
594
  file = File.open(File.join(@tmpdir, path),"wb")
607
595
  file.write(zip.read(path))
608
596
  file.close
@@ -623,7 +611,6 @@ class GenericSpreadsheet
623
611
  def write_csv_content(file=nil,sheet=nil)
624
612
  file = STDOUT unless file
625
613
  if first_row(sheet) # sheet is not empty
626
- # first_row(sheet).upto(last_row(sheet)) do |row|
627
614
  1.upto(last_row(sheet)) do |row|
628
615
  1.upto(last_column(sheet)) do |col|
629
616
  file.print(",") if col > 1
@@ -644,16 +631,10 @@ class GenericSpreadsheet
644
631
  else
645
632
  case onecelltype
646
633
  when :string
647
- #if onecell == ""
648
- # str << ''
649
- #else
650
- # one = onecell.gsub(/"/,'""')
651
- # str << ('"'+one+'"')
652
- #end
653
- unless onecell.empty?
634
+ unless onecell.empty?
654
635
  one = onecell.gsub(/"/,'""')
655
636
  str << ('"'+one+'"')
656
- end
637
+ end
657
638
  when :float, :percentage
658
639
  if onecell == onecell.to_i
659
640
  str << onecell.to_i.to_s
@@ -662,16 +643,10 @@ class GenericSpreadsheet
662
643
  end
663
644
  when :formula
664
645
  if onecell.class == String
665
- # if onecell == ""
666
- # str << ''
667
- # else
668
- # one = onecell.gsub(/"/,'""')
669
- # str << '"'+one+'"'
670
- # end
671
- unless onecell.empty?
646
+ unless onecell.empty?
672
647
  one = onecell.gsub(/"/,'""')
673
648
  str << '"'+one+'"'
674
- end
649
+ end
675
650
  elsif onecell.class == Float
676
651
  if onecell == onecell.to_i
677
652
  str << onecell.to_i.to_s
@@ -686,10 +661,7 @@ class GenericSpreadsheet
686
661
  when :time
687
662
  str << GenericSpreadsheet.integer_to_timestring(onecell)
688
663
  when :datetime
689
- # date,rest = onecell.to_s.split('T')
690
- # time = rest.split('+').first
691
- # str << date + ' ' + time
692
- str << onecell.to_s
664
+ str << onecell.to_s
693
665
  else
694
666
  raise "unhandled celltype "+onecelltype.to_s
695
667
  end
data/lib/roo/google.rb CHANGED
@@ -249,19 +249,12 @@ class Google < GenericSpreadsheet
249
249
  @cell_type[sheet][key] = value_type
250
250
  @formula[sheet] = {} unless @formula[sheet]
251
251
  @formula[sheet][key] = string_value if value_type == :formula
252
- ############
253
- #$log.debug("key: #{key}")
254
- #$log.debug "#{ws[row,col].inspect}"
255
- #@cell[sheet][key] = ws[row,col]
256
- #$log.debug "@cell[sheet][key]: #{@cell[sheet][key]}"
257
- ############
258
252
  end
259
253
  end
260
254
  @cells_read[sheet] = true
261
255
  end
262
256
 
263
257
  def determine_datatype(val, numval=nil)
264
- # $log.debug "val: #{val} numval: #{numval}"
265
258
  if val.nil? || val[0,1] == '='
266
259
  ty = :formula
267
260
  if numeric?(numval)
@@ -284,7 +277,6 @@ class Google < GenericSpreadsheet
284
277
  ty = :string
285
278
  end
286
279
  end
287
- #$log.debug "val: #{val} ty: #{ty}" if ty == :date
288
280
  return val, ty
289
281
  end
290
282
 
@@ -2,7 +2,6 @@ require 'rubygems'
2
2
  require 'fileutils'
3
3
  require 'zip/zipfilesystem'
4
4
  require 'date'
5
- require 'base64'
6
5
  require 'nokogiri'
7
6
  require 'cgi'
8
7
 
@@ -12,7 +11,7 @@ class Openoffice < GenericSpreadsheet
12
11
 
13
12
  # initialization and opening of a spreadsheet file
14
13
  # values for packed: :zip
15
- def initialize(filename, packed=nil, file_warning=:error, tmpdir=nil) #, create = false)
14
+ def initialize(filename, packed=nil, file_warning=:error, tmpdir=nil)
16
15
  @file_warning = file_warning
17
16
  super()
18
17
  file_type_check(filename,'.ods','an openoffice', packed)
@@ -24,9 +23,6 @@ class Openoffice < GenericSpreadsheet
24
23
  end
25
24
  filename = open_from_uri(filename) if filename[0,7] == "http://"
26
25
  filename = unzip(filename) if packed and packed == :zip
27
- #if create and ! File.exists?(filename)
28
- # self.create_openoffice(filename)
29
- #end
30
26
  @cells_read = Hash.new
31
27
  #TODO: @cells_read[:default] = false
32
28
  @filename = filename
@@ -40,9 +36,7 @@ class Openoffice < GenericSpreadsheet
40
36
  file = File.new(File.join(@tmpdir, @file_nr.to_s+"_roo_content.xml"))
41
37
  @doc = Nokogiri::XML(file)
42
38
  file.close
43
- #unless Dir.glob(@tmpdir).empty?
44
- FileUtils::rm_r(@tmpdir)
45
- #end
39
+ FileUtils::rm_r(@tmpdir)
46
40
  @default_sheet = self.sheets.first
47
41
  @cell = Hash.new
48
42
  @cell_type = Hash.new
@@ -69,18 +63,6 @@ class Openoffice < GenericSpreadsheet
69
63
  end
70
64
  end
71
65
 
72
- # creates a new empty openoffice-spreadsheet file
73
- def create_openoffice(filename) #:nodoc:
74
- #TODO: a better way for creating the file contents
75
- # now you have to call mkbase64...rb to create an include file with all
76
- # the empty files in an openoffice zip-file
77
- load 'base64include.rb'
78
- # puts @@empty_spreadsheet
79
- f = File.open(filename,'wb')
80
- f.print(Base64.decode64(@@empty_spreadsheet))
81
- f.close
82
- end
83
-
84
66
  # Returns the content of a spreadsheet-cell.
85
67
  # (1,1) is the upper left corner.
86
68
  # (1,1), (1,'A'), ('A',1), ('a',1) all refers to the
@@ -90,7 +72,6 @@ class Openoffice < GenericSpreadsheet
90
72
  read_cells(sheet) unless @cells_read[sheet]
91
73
  row,col = normalize(row,col)
92
74
  if celltype(row,col,sheet) == :date
93
- #TODO: yyyy,mm,dd = @cell[sheet][[row,col]].split('-')
94
75
  yyyy,mm,dd = @cell[sheet][[row,col]].to_s.split('-')
95
76
  return Date.new(yyyy.to_i,mm.to_i,dd.to_i)
96
77
  end
@@ -107,7 +88,13 @@ class Openoffice < GenericSpreadsheet
107
88
  if @formula[sheet][[row,col]] == nil
108
89
  return nil
109
90
  else
110
- return @formula[sheet][[row,col]]["oooc:".length..-1]
91
+ # return @formula[sheet][[row,col]]["oooc:".length..-1]
92
+ str = @formula[sheet][[row,col]]
93
+ if str.include? ':'
94
+ return str[str.index(':')+1..-1]
95
+ else
96
+ return str
97
+ end
111
98
  end
112
99
  end
113
100
 
@@ -183,9 +170,7 @@ class Openoffice < GenericSpreadsheet
183
170
 
184
171
  def sheets
185
172
  return_sheets = []
186
- #TODO: @doc.find("//*[local-name()='table']").each do |sheet|
187
173
  @doc.xpath("//*[local-name()='table']").each do |sheet|
188
- #TODO: return_sheets << sheet.attributes['name']
189
174
  return_sheets << sheet['name']
190
175
  end
191
176
  return_sheets
@@ -206,11 +191,6 @@ class Openoffice < GenericSpreadsheet
206
191
  @cell[sheet].inspect
207
192
  end
208
193
 
209
- # save spreadsheet
210
- def save #:nodoc:
211
- 42
212
- end
213
-
214
194
  # returns the row,col values of the labelled cell
215
195
  # (nil,nil) if label is not defined
216
196
  # sheet parameter is not really needed because label names are global
@@ -231,7 +211,6 @@ class Openoffice < GenericSpreadsheet
231
211
 
232
212
  # read the version of the OO-Version
233
213
  def oo_version
234
- #TODO: @doc.find("//*[local-name()='document-content']").each do |office|
235
214
  @doc.xpath("//*[local-name()='document-content']").each do |office|
236
215
  @officeversion = office.attributes['version'].to_s
237
216
  end
@@ -300,41 +279,30 @@ class Openoffice < GenericSpreadsheet
300
279
  @labels[name] = [sheetname,row,col]
301
280
  end
302
281
 
303
- #TODO: @doc.find("//*[local-name()='table']").each do |ws|
304
282
  @doc.xpath("//*[local-name()='table']").each do |ws|
305
- #TODO: if sheet == ws.attributes['name']
306
283
  if sheet == ws['name']
307
284
  sheet_found = true
308
285
  col = 1
309
286
  row = 1
310
- #TODO: ws.each_element do |table_element|
311
287
  ws.children.each do |table_element|
312
288
  case table_element.name
313
289
  when 'table-column'
314
290
  @style_defaults[sheet] << table_element.attributes['default-cell-style-name']
315
291
  when 'table-row'
316
292
  if table_element.attributes['number-rows-repeated']
317
- #TODO: skip_row = table_element.attributes['number-rows-repeated'].to_i
318
293
  skip_row = table_element.attributes['number-rows-repeated'].to_s.to_i
319
294
  row = row + skip_row - 1
320
295
  end
321
- #TODO: table_element.each_element do |cell|
322
296
  table_element.children.each do |cell|
323
- #TODO: skip_col = cell.attributes['number-columns-repeated']
324
297
  skip_col = cell['number-columns-repeated']
325
- #TODO: formula = cell.attributes['formula']
326
298
  formula = cell['formula']
327
- #TODO: vt = cell.attributes['value-type']
328
299
  vt = cell['value-type']
329
- #TODO: v = cell.attributes['value']
330
300
  v = cell['value']
331
- #TODO: style_name = cell.attributes['style-name']
332
301
  style_name = cell['style-name']
333
302
  if vt == 'string'
334
303
  str_v = ''
335
304
  # insert \n if there is more than one paragraph
336
305
  para_count = 0
337
- #TODO: cell.each_element do |str|
338
306
  cell.children.each do |str|
339
307
  if str.name == 'p'
340
308
  v = str.content
@@ -352,7 +320,6 @@ class Openoffice < GenericSpreadsheet
352
320
  end # == 'p'
353
321
  end
354
322
  elsif vt == 'time'
355
- #TODO: cell.each_element do |str|
356
323
  cell.children.each do |str|
357
324
  if str.name == 'p'
358
325
  v = str.content
@@ -388,8 +355,6 @@ class Openoffice < GenericSpreadsheet
388
355
  end
389
356
  end
390
357
  end
391
-
392
- #TODO: @doc.find("//*[local-name()='automatic-styles']").each do |style|
393
358
  @doc.xpath("//*[local-name()='automatic-styles']").each do |style|
394
359
  read_styles(style)
395
360
  end
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ require 'roo'
3
+ require 'benchmark'
4
+
5
+ def process_all_cells(oo)
6
+ oo.default_sheet = oo.sheets.first
7
+ #oo.first_row.upto(oo.last_row) do |row|
8
+ # oo.first_column.upto(oo.last_column) do |col|
9
+ # result = oo.cell(row,col)
10
+ # end
11
+ #end
12
+ ret = []
13
+ oo.first_row.upto(oo.last_row) do |row|
14
+ ret << oo.row(row)
15
+ end
16
+ end
17
+ # 3735 Zeilen jeweils
18
+ def openoffice
19
+ oo = Openoffice.new('Bibelbund.ods')
20
+ process_all_cells(oo)
21
+ end
22
+ def excel
23
+ oo = Excel.new('Bibelbund.xls')
24
+ process_all_cells(oo)
25
+ end
26
+ def excelx
27
+ oo = Excelx.new('Bibelbund.xlsx')
28
+ process_all_cells(oo)
29
+ end
30
+
31
+ n = 1
32
+ Benchmark.bmbm(10) do |x|
33
+ x.report('openoffice:') { n.times do
34
+ openoffice
35
+ end }
36
+ x.report('excel:') { n.times do
37
+ excel
38
+ end }
39
+ x.report('excelx:') { n.times do
40
+ excelx
41
+ end }
42
+ end
43
+
Binary file
data/test/test_roo.rb CHANGED
@@ -34,7 +34,7 @@ $log = Logger.new(File.join(ENV['HOME'],"roo.log"))
34
34
  #$log.level = Logger::WARN
35
35
  $log.level = Logger::DEBUG
36
36
 
37
- DISPLAY_LOG = false
37
+ DISPLAY_LOG = true
38
38
  DB_LOG = false
39
39
  if DB_LOG
40
40
  require 'activerecord'
@@ -170,7 +170,7 @@ class TestRoo < Test::Unit::TestCase
170
170
  LIBREOFFICE = true # do Libreoffice tests? (.ods files)
171
171
 
172
172
  ONLINE = false
173
- LONG_RUN = false
173
+ LONG_RUN = true
174
174
  GLOBAL_TIMEOUT = 48.minutes
175
175
 
176
176
  def setup
@@ -2351,4 +2351,29 @@ where the expected result is
2351
2351
  assert_equal "", `diff test/so_datetime.csv datetime.csv`
2352
2352
  end
2353
2353
  end
2354
+
2355
+ # 2011-08-11
2356
+ def test_bug_openoffice_formula_missing_letters
2357
+ if OPENOFFICE
2358
+ # Dieses Dokument wurde mit LibreOffice angelegt.
2359
+ # Keine Ahnung, ob es damit zusammenhaengt, das diese
2360
+ # Formeln anders sind, als in der Datei formula.ods, welche
2361
+ # mit Openoffice angelegt wurde.
2362
+ # Bei den Openoffice-Dateien ist in diesem Feld in der XML-
2363
+ # Datei of: als Prefix enthalten, waehrend in dieser Datei
2364
+ # irgendetwas mit oooc: als Prefix verwendet wird.
2365
+ oo = Openoffice.new(File.join(TESTDIR,'dreimalvier.ods'))
2366
+ oo.default_sheet = oo.sheets.first
2367
+ assert_equal '=SUM([.A1:.D1])', oo.formula('e',1)
2368
+ assert_equal '=SUM([.A2:.D2])', oo.formula('e',2)
2369
+ assert_equal '=SUM([.A3:.D3])', oo.formula('e',3)
2370
+ assert_equal [
2371
+ [1,5,'=SUM([.A1:.D1])'],
2372
+ [2,5,'=SUM([.A2:.D2])'],
2373
+ [3,5,'=SUM([.A3:.D3])'],
2374
+ ], oo.formulas
2375
+
2376
+ end
2377
+ end
2378
+
2354
2379
  end # class
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.6
4
+ version: 1.9.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-08-03 00:00:00.000000000Z
12
+ date: 2011-08-27 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: spreadsheet
16
- requirement: &25564452 !ruby/object:Gem::Requirement
16
+ requirement: &25467852 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>'
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.6.4
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *25564452
24
+ version_requirements: *25467852
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: nokogiri
27
- requirement: &25564128 !ruby/object:Gem::Requirement
27
+ requirement: &25467564 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.5.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *25564128
35
+ version_requirements: *25467564
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: google-spreadsheet-ruby
38
- requirement: &25563816 !ruby/object:Gem::Requirement
38
+ requirement: &25467036 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.1.5
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *25563816
46
+ version_requirements: *25467036
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: choice
49
- requirement: &25563468 !ruby/object:Gem::Requirement
49
+ requirement: &25466676 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 0.1.4
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *25563468
57
+ version_requirements: *25466676
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: todonotes
60
- requirement: &25563144 !ruby/object:Gem::Requirement
60
+ requirement: &25466244 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,18 +65,18 @@ dependencies:
65
65
  version: 0.1.0
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *25563144
68
+ version_requirements: *25466244
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: bones
71
- requirement: &25562808 !ruby/object:Gem::Requirement
71
+ requirement: &25465872 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
75
75
  - !ruby/object:Gem::Version
76
- version: 3.7.0
76
+ version: 3.7.1
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *25562808
79
+ version_requirements: *25465872
80
80
  description: ! 'Roo can access the contents of various spreadsheet files. It can handle
81
81
 
82
82
  * Openoffice
@@ -96,8 +96,6 @@ extra_rdoc_files:
96
96
  - PostInstall.txt
97
97
  - README.txt
98
98
  - bin/roo
99
- - lib/.roo.rb.swp
100
- - lib/roo/.generic_spreadsheet.rb.swp
101
99
  - test/no_spreadsheet_file.txt
102
100
  files:
103
101
  - History.txt
@@ -110,9 +108,7 @@ files:
110
108
  - bin/roo
111
109
  - csv8532
112
110
  - datetime.csv
113
- - lib/.roo.rb.swp
114
111
  - lib/roo.rb
115
- - lib/roo/.generic_spreadsheet.rb.swp
116
112
  - lib/roo/excel.rb
117
113
  - lib/roo/excelx.rb
118
114
  - lib/roo/generic_spreadsheet.rb
@@ -131,6 +127,7 @@ files:
131
127
  - test/bbu.ods
132
128
  - test/bbu.xls
133
129
  - test/bbu.xlsx
130
+ - test/benchmark1.rb
134
131
  - test/bode-v1.ods.zip
135
132
  - test/bode-v1.xls.zip
136
133
  - test/boolean.ods
@@ -144,6 +141,7 @@ files:
144
141
  - test/datetime.xls
145
142
  - test/datetime.xlsx
146
143
  - test/datetime_floatconv.xls
144
+ - test/dreimalvier.ods
147
145
  - test/emptysheets.ods
148
146
  - test/emptysheets.xls
149
147
  - test/emptysheets.xlsx
@@ -215,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
215
213
  version: '0'
216
214
  requirements: []
217
215
  rubyforge_project: roo
218
- rubygems_version: 1.8.6
216
+ rubygems_version: 1.8.9
219
217
  signing_key:
220
218
  specification_version: 3
221
219
  summary: Roo can access the contents of various spreadsheet files.
data/lib/.roo.rb.swp DELETED
Binary file
Binary file