lib/roo/openoffice.rb in roo-1.11.2 vs lib/roo/openoffice.rb in roo-1.12.0

- old
+ new

@@ -1,12 +1,10 @@ -require 'fileutils' require 'date' require 'nokogiri' require 'cgi' -require 'pp' #TODO -class Roo::Openoffice < Roo::GenericSpreadsheet +class Roo::OpenOffice < Roo::Base class << self def extract_content(tmpdir, filename) Zip::ZipFile.open(filename) do |zip| process_zipfile(tmpdir, zip) end @@ -30,38 +28,39 @@ end end # initialization and opening of a spreadsheet file # values for packed: :zip - def initialize(filename, packed=nil, file_warning=:error, tmpdir_root=nil) - file_type_check(filename,'.ods','an Roo::Openoffice', file_warning, packed) + def initialize(filename, options={}, deprecated_file_warning=:error, deprecated_tmpdir_root=nil) + if Hash === options + packed = options[:packed] + file_warning = options[:file_warning] || :error + tmpdir_root = options[:tmpdir_root] + else + warn 'Supplying `packed`, `file_warning`, or `tmpdir_root` as separate arguments to `Roo::OpenOffice.new` is deprected. Use an options hash instead.' + packed = options + file_warning = deprecated_file_warning + tmpdir_root = deprecated_tmpdir_root + end + + file_type_check(filename,'.ods','an Roo::OpenOffice', file_warning, packed) make_tmpdir(tmpdir_root) do |tmpdir| - filename = open_from_uri(filename, tmpdir) if uri?(filename) + filename = download_uri(filename, tmpdir) if uri?(filename) filename = unzip(filename, tmpdir) if packed == :zip - @cells_read = Hash.new #TODO: @cells_read[:default] = false @filename = filename unless File.file?(@filename) raise IOError, "file #{@filename} does not exist" end self.class.extract_content(tmpdir, @filename) - @doc = File.open(File.join(tmpdir, "roo_content.xml")) do |file| - Nokogiri::XML(file) - end + @doc = load_xml(File.join(tmpdir, "roo_content.xml")) end - @default_sheet = self.sheets.first - @cell = Hash.new - @cell_type = Hash.new + super(filename, options) @formula = Hash.new - @first_row = Hash.new - @last_row = Hash.new - @first_column = Hash.new - @last_column = Hash.new @style = Hash.new @style_defaults = Hash.new { |h,k| h[k] = [] } @style_definitions = Hash.new - @header_line = 1 @comment = Hash.new @comments_read = Hash.new end def method_missing(m,*args) @@ -80,11 +79,11 @@ # (1,1) is the upper left corner. # (1,1), (1,'A'), ('A',1), ('a',1) all refers to the # cell at the first line and first row. def cell(row, col, sheet=nil) sheet ||= @default_sheet - read_cells(sheet) unless @cells_read[sheet] + read_cells(sheet) row,col = normalize(row,col) if celltype(row,col,sheet) == :date yyyy,mm,dd = @cell[sheet][[row,col]].to_s.split('-') return Date.new(yyyy.to_i,mm.to_i,dd.to_i) end @@ -94,40 +93,21 @@ # Returns the formula at (row,col). # Returns nil if there is no formula. # The method #formula? checks if there is a formula. def formula(row,col,sheet=nil) sheet ||= @default_sheet - read_cells(sheet) unless @cells_read[sheet] + read_cells(sheet) row,col = normalize(row,col) - if @formula[sheet][[row,col]] == nil - return nil - else - # return @formula[sheet][[row,col]]["oooc:".length..-1] - # TODO: - #str = @formula[sheet][[row,col]] - #if str.include? ':' - #return str[str.index(':')+1..-1] - #else - #return str - #end - @formula[sheet][[row,col]] - end + @formula[sheet][[row,col]] end + alias_method :formula?, :formula - # true, if there is a formula - def formula?(row,col,sheet=nil) - sheet ||= @default_sheet - read_cells(sheet) unless @cells_read[sheet] - row,col = normalize(row,col) - formula(row,col) != nil - end - # returns each formula in the selected sheet as an array of elements # [row, col, formula] def formulas(sheet=nil) sheet ||= @default_sheet - read_cells(sheet) unless @cells_read[sheet] + read_cells(sheet) if @formula[sheet] @formula[sheet].each.collect do |elem| [elem[0][0], elem[0][1], elem[1]] end else @@ -152,11 +132,11 @@ end # Given a cell, return the cell's style def font(row, col, sheet=nil) sheet ||= @default_sheet - read_cells(sheet) unless @cells_read[sheet] + read_cells(sheet) row,col = normalize(row,col) style_name = @style[sheet][[row,col]] || @style_defaults[sheet][col - 1] || 'Default' @style_definitions[style_name] end @@ -168,39 +148,37 @@ # * :formula # * :time # * :datetime def celltype(row,col,sheet=nil) sheet ||= @default_sheet - read_cells(sheet) unless @cells_read[sheet] + read_cells(sheet) row,col = normalize(row,col) if @formula[sheet][[row,col]] return :formula else @cell_type[sheet][[row,col]] end end def sheets - return_sheets = [] - @doc.xpath("//*[local-name()='table']").each do |sheet| - return_sheets << sheet.attributes["name"].value + @doc.xpath("//*[local-name()='table']").map do |sheet| + sheet.attributes["name"].value end - return_sheets end - # version of the Roo::Openoffice document + # version of the Roo::OpenOffice document # at 2007 this is always "1.0" def officeversion oo_version @officeversion end # shows the internal representation of all cells # mainly for debugging purposes def to_s(sheet=nil) sheet ||= @default_sheet - read_cells(sheet) unless @cells_read[sheet] + read_cells(sheet) @cell[sheet].inspect end # returns the row,col values of the labelled cell # (nil,nil) if label is not defined @@ -209,11 +187,11 @@ unless @label.size > 0 return nil,nil,nil end if @label.has_key? labelname return @label[labelname][1].to_i, - Roo::GenericSpreadsheet.letter_to_number(@label[labelname][2]), + Roo::Base.letter_to_number(@label[labelname][2]), @label[labelname][0] else return nil,nil,nil end end @@ -223,30 +201,30 @@ def labels(sheet=nil) read_labels @label.map do |label| [ label[0], # name [ label[1][1].to_i, # row - Roo::GenericSpreadsheet.letter_to_number(label[1][2]), # column + Roo::Base.letter_to_number(label[1][2]), # column label[1][0], # sheet ] ] end end # returns the comment at (row/col) # nil if there is no comment def comment(row,col,sheet=nil) sheet ||= @default_sheet - read_cells(sheet) unless @cells_read[sheet] + read_cells(sheet) row,col = normalize(row,col) return nil unless @comment[sheet] @comment[sheet][[row,col]] end # true, if there is a comment def comment?(row,col,sheet=nil) sheet ||= @default_sheet - read_cells(sheet) unless @cells_read[sheet] + read_cells(sheet) row,col = normalize(row,col) comment(row,col) != nil end @@ -275,11 +253,11 @@ # helper function to set the internal representation of cells def set_cell_values(sheet,x,y,i,v,value_type,formula,table_cell,str_v,style_name) key = [y,x+i] @cell_type[sheet] = {} unless @cell_type[sheet] - @cell_type[sheet][key] = Roo::Openoffice.oo_type_2_roo_type(value_type) + @cell_type[sheet][key] = Roo::OpenOffice.oo_type_2_roo_type(value_type) @formula[sheet] = {} unless @formula[sheet] if formula ['of:', 'oooc:'].each do |prefix| if formula[0,prefix.length] == prefix formula = formula[prefix.length..-1] @@ -321,12 +299,13 @@ # some content <text:s text:c="3"/> #++ def read_cells(sheet=nil) sheet ||= @default_sheet validate_sheet!(sheet) - sheet_found = false + return if @cells_read[sheet] + sheet_found = false @doc.xpath("//*[local-name()='table']").each do |ws| if sheet == attr(ws,'name') sheet_found = true col = 1 row = 1 @@ -434,12 +413,12 @@ end @cells_read[sheet] = true @comments_read[sheet] = true end - # Only calls read_cells because Roo::GenericSpreadsheet calls read_comments - # whereas the reading of comments is done in read_cells for Roo::Openoffice-objects + # Only calls read_cells because Roo::Base calls read_comments + # whereas the reading of comments is done in read_cells for Roo::OpenOffice-objects def read_comments(sheet=nil) read_cells(sheet) end def read_labels @@ -454,16 +433,16 @@ [name, [sheetname,row,col]] end] end def read_styles(style_elements) - @style_definitions['Default'] = Roo::Openoffice::Font.new + @style_definitions['Default'] = Roo::OpenOffice::Font.new style_elements.each do |style| next unless style.name == 'style' style_name = attr(style,'name') style.each do |properties| - font = Roo::Openoffice::Font.new + font = Roo::OpenOffice::Font.new font.bold = attr(properties,'font-weight') font.italic = attr(properties,'font-style') font.underline = attr(properties,'text-underline-style') @style_definitions[style_name] = font end @@ -503,18 +482,15 @@ end } result end - - private def attr(node, attr_name) if node.attributes[attr_name] node.attributes[attr_name].value end end - end # class -# Libreoffice is just an alias for Roo::Openoffice class -class Roo::Libreoffice < Roo::Openoffice +# LibreOffice is just an alias for Roo::OpenOffice class +class Roo::LibreOffice < Roo::OpenOffice end