lib/roo/openoffice.rb in roo-0.4.1 vs lib/roo/openoffice.rb in roo-0.5.0

- old
+ new

@@ -3,21 +3,28 @@ require 'rexml/document' require 'fileutils' require 'zip/zipfilesystem' require 'date' require 'llip' +require 'base64' #require 'lib/roo/spreadsheetparser' class Openoffice @@nr = 0 - def initialize(filename) + # initialization and opening of a spreasheet file + # file will be created if 'create' is true + # and the file does not exist + def initialize(filename, create = false) if filename[-4..-1] != ".ods" warn "are you sure, this is an openoffice file?" end + if create and ! File.exists?(filename) + self.create_openoffice(filename) + end @cells_read = false @filename = filename @tmpdir = "oo_"+$$.to_s unless File.exists?(@tmpdir) FileUtils::mkdir(@tmpdir) @@ -29,18 +36,33 @@ @doc = REXML::Document.new file file.close @cell = Hash.new @cell_type = Hash.new @formula = Hash.new -# if ENV["roo_local"] != "thomas-p" + if ENV["roo_local"] != "thomas-p" FileUtils::rm_r(@tmpdir) -# end - @default_sheet = nil + end + @default_sheet = nil @first_column = @last_column = nil @first_row = @last_row = nil + trap('INT') { + FileUtils::rm_r(@tmpdir) + } end + # creates a new empty openoffice-spreadsheet file + def create_openoffice(filename) + #TODO: a better way for creating the file contents + # now you have to call mkbase64...rb to create an include file with all + # the empty files in an openoffice zip-file + load 'base64include.rb' + # puts @@empty_spreadsheet + f = File.open(filename,'w') + f.print(Base64.decode64(@@empty_spreadsheet)) + f.close + end + # reopens and read a spreadsheet document if false def reload @cells_read = false @tmpdir = "oo_"+$$.to_s @@ -73,11 +95,11 @@ # (1,1), (1,'A'), ('A',1), ('a',1) all refers to the # cell at first line, first row def cell(row,col) read_cells unless @cells_read row,col = normalize(row,col) - if celltype(row,col) == "date" + if celltype(row,col) == :date yyyy,mm,dd = @cell["#{row},#{col}"].split('-') return Date.new(yyyy.to_i,mm.to_i,dd.to_i) end @cell["#{row},#{col}"] end @@ -102,10 +124,11 @@ end # set a cell to a certain value # (this will not be saved back to the spreadsheet file!) def set(row,col,value) + read_cells unless @cells_read row,col = normalize(row,col) set_value(row,col,value) if value.class == Fixnum set_type(row,col,:float) elsif value.class == String @@ -161,10 +184,12 @@ @cell = Hash.new @cell_type = Hash.new @formula = Hash.new end + alias set_default_sheet default_sheet= + # version of the openoffice document # at 2007 this is always "1.0" def officeversion read_cells(:ignore_default_sheet => true) unless @cells_read @officeversion @@ -282,20 +307,18 @@ # true if cell is empty def empty?(row, col) read_cells unless @cells_read return true unless cell(row, col) - return true if celltype(row, col) == "string" && cell(row, col).empty? + return true if celltype(row, col) == :string && cell(row, col).empty? false end -=begin # save spreadsheet def save 42 end -=end # evaluate the formula at this cell # experimental: DO NOT USE THIS! def solve(row,col) parser = SpreadsheetParser.new @@ -394,36 +417,36 @@ if skip if v == nil x += (skip.to_i - 1) else 0.upto(skip.to_i-1) do |i| - @cell_type["#{y},#{x+i}"] = vt + @cell_type["#{y},#{x+i}"] = Openoffice.oo_type_2_roo_type(vt) @formula["#{y},#{x+i}"] = formula if formula - if @cell_type["#{y},#{x+i}"] == 'float' + if @cell_type["#{y},#{x+i}"] == :float @cell["#{y},#{x+i}"] = v.to_f - elsif @cell_type["#{y},#{x+i}"] == 'string' + elsif @cell_type["#{y},#{x+i}"] == :string @cell["#{y},#{x+i}"] = v - elsif @cell_type["#{y},#{x+i}"] == 'date' + elsif @cell_type["#{y},#{x+i}"] == :date @cell["#{y},#{x+i}"] = tr.attributes['date-value'] else @cell["#{y},#{x+i}"] = v end end x += 1 end end # if skip @formula["#{y},#{x}"] = formula if formula - @cell_type["#{y},#{x}"] = vt - if @cell_type["#{y},#{x}"] == 'float' + @cell_type["#{y},#{x}"] = Openoffice.oo_type_2_roo_type(vt) + if @cell_type["#{y},#{x}"] == :float @cell["#{y},#{x}"] = v.to_f - elsif @cell_type["#{y},#{x}"] == 'string' + elsif @cell_type["#{y},#{x}"] == :string tr.each_element do |str| if str.name == 'p' @cell["#{y},#{x}"] = str.text end end - elsif @cell_type["#{y},#{x}"] == 'date' + elsif @cell_type["#{y},#{x}"] == :date @cell["#{y},#{x}"] = tr.attributes['date-value'] else @cell["#{y},#{x}"] = v end x += 1 @@ -443,10 +466,11 @@ end @cells_read = true end def process_zipfile(zip, path='') + #p path if zip.file.file? path if path == "content.xml" open(@tmpdir+'/'+@file_nr.to_s+'_roo_content.xml','w') {|f| f << zip.read(path) } @@ -474,11 +498,11 @@ if col.class == Fixnum # ('A',1): # ('B', 5) -> (5, 2) row, col = col, row else - raise FormatError + raise ArgumentError end end if col.class == String col = Openoffice.letter_to_number(col) end @@ -515,6 +539,16 @@ def set_type(row,col,type) @cell_type["#{row},#{col}"] = type end + A_ROO_TYPE = { + "float" => :float, + "string" => :string, + "date" => :date, + "percentage" => :percentage, + } + + def Openoffice.oo_type_2_roo_type(ootype) + return A_ROO_TYPE[ootype] + end end # class