lib/roo/excel.rb in roo-0.8.0 vs lib/roo/excel.rb in roo-0.8.1

- old
+ new

@@ -2,22 +2,22 @@ gem 'parseexcel', '>= 0.5.2' require 'parseexcel' CHARGUESS=false require 'charguess' if CHARGUESS -module Spreadsheet +module Spreadsheet # :nodoc module ParseExcel class Worksheet include Enumerable attr_reader :min_row, :max_row, :min_col, :max_col end end end +# Class for handling Excel-Spreadsheets +class Excel < GenericSpreadsheet -class Excel < GenericSpreadsheet #Openoffice - EXCEL_NO_FORMULAS = 'formulas are not supported for excel spreadsheets' # Creates a new Excel spreadsheet object. # Parameter packed: :zip - File is a zip-file def initialize(filename, packed = nil) @@ -49,10 +49,11 @@ @first_column = Hash.new @last_column = Hash.new @cells_read = Hash.new end + # returns an array of sheet names in the spreadsheet def sheets result = [] 0.upto(@workbook.sheet_count - 1) do |i| # TODO: is there a better way to do conversion? if CHARGUESS @@ -62,13 +63,21 @@ result << Iconv.new('utf-8',encoding).iconv( @workbook.worksheet(i).name ) else - result << Iconv.new('utf-8','unicode').iconv( - @workbook.worksheet(i).name - ) + result << platform_specific_iconv(@workbook.worksheet(i).name) + #case RUBY_PLATFORM.downcase + #when /darwin/ + # result << Iconv.new('utf-8','utf-8').iconv( + # @workbook.worksheet(i).name + # ) + #else + # result << Iconv.new('utf-8','unicode').iconv( + # @workbook.worksheet(i).name + # ) + #end # case end end return result end @@ -103,11 +112,11 @@ return nil unless cell case cell.type when :numeric then return cell.to_f when :text then return cell.to_s('utf-8') when :date then return cell.date - else + else return nil # cell.to_s('utf-8') end end line += 1 } @@ -126,17 +135,17 @@ if line == row return nil unless row_par cell = row_par.at(col-1) return nil unless cell case cell.type - when :numeric + when :numeric return :float - when :text + when :text return :string - when :date + when :date return :date - else + else return cell.type.to_sym end end line += 1 } @@ -146,11 +155,11 @@ # row numbers are 1,2,3,... like in the spreadsheet def row(rownumber,sheet=nil) sheet = @default_sheet unless sheet default_sheet_check worksheet = @workbook.worksheet(sheet_no(sheet)) - #therow = worksheet.row(rownumber-1) + #therow = worksheet.row(rownumber-1) result = [] worksheet.row(rownumber-1).each {|cell| if cell case cell.type when :numeric then result << cell.to_i @@ -193,11 +202,11 @@ result << nil end else result << nil end - } + } result end # returns the first non empty column def first_column(sheet=nil) @@ -228,21 +237,21 @@ sheet = @default_sheet unless sheet return @last_row[sheet] if @last_row[sheet] fr, lr, fc, lc = get_firsts_lasts(sheet) lr end - + # returns NO formula in excel spreadsheets def formula(row,col,sheet=nil) raise EXCEL_NO_FORMULAS end # raises an exception because formulas are not supported for excel files def formula?(row,col,sheet=nil) raise EXCEL_NO_FORMULAS end - + # returns NO formulas in excel spreadsheets def formulas(sheet=nil) raise EXCEL_NO_FORMULAS end @@ -255,23 +264,41 @@ # determine the first and last boundaries def get_firsts_lasts(sheet=nil) sheet = @default_sheet unless sheet fr = fc = 999_999 - lr = lc = -999_999 + lr = lc = -999_999 worksheet = @workbook.worksheet(sheet_no(sheet)) - fr = worksheet.min_row + 1 - lr = worksheet.max_row + 1 - fc = worksheet.min_col + 1 - lc = worksheet.max_col + 1 - # 2007-11-05 BEGIN - # parsexcel liefert (mir unverstaendlich) eine Zeile als letzte Zeile - # zurueck, die aber leer ist. Deshalb Korrekturfunktion, die wirklich - # die letzte nicht leere Zeile liefert. - while empty_row? row(lr,sheet) - lr -= 1 + unless worksheet.min_row + fr = nil + else + fr = worksheet.min_row + 1 end + unless worksheet.max_row + lr = nil + else + lr = worksheet.max_row + 1 + end + unless worksheet.min_col + fc = nil + else + fc = worksheet.min_col + 1 + end + unless worksheet.max_col + lc = nil + else + lc = worksheet.max_col + 1 + end + if lr + # 2007-11-05 BEGIN + # parsexcel liefert (mir unverstaendlich) eine Zeile als letzte Zeile + # zurueck, die aber leer ist. Deshalb Korrekturfunktion, die wirklich + # die letzte nicht leere Zeile liefert. + while empty_row? row(lr,sheet) + lr -= 1 + end + end # 2007-11-05 END @first_row[sheet] = fr @last_row[sheet] = lr @first_column[sheet] = fc @last_column[sheet] = lc @@ -281,13 +308,15 @@ # converts name of a sheet to index (0,1,2,..) def sheet_no(name) return name-1 if name.kind_of?(Fixnum) 0.upto(@workbook.sheet_count - 1) do |i| # TODO: is there a better way to do conversion? - return i if name == Iconv.new('utf-8','unicode').iconv( - @workbook.worksheet(i).name - ) + return i if name == platform_specific_iconv( + @workbook.worksheet(i).name) +#Iconv.new('utf-8','unicode').iconv( +# @workbook.worksheet(i).name +# ) end raise StandardError, "sheet '#{name}' not found" end # writes csv output to stdout or file @@ -302,25 +331,25 @@ cell = row_par.at(col-1) unless cell empty = true else case cell.type - when :numeric + when :numeric onecelltype = :float onecell = cell.to_f - when :text + when :text onecelltype = :string onecell = cell.to_s('utf-8') - when :date + when :date onecelltype = :date onecell = cell.date else onecelltype = nil - onecell = nil + onecell = nil end - end - file.print one_cell_output(onecelltype,onecell,empty) + end + file.print one_cell_output(onecelltype,onecell,empty) } file.print("\n") } end @@ -329,10 +358,22 @@ row.each {|elem| if elem != '' #if elem.class == String and elem.size > 0 content = true end - } + } ! content end + +def platform_specific_iconv(value) + case RUBY_PLATFORM.downcase + when /darwin/ + result = Iconv.new('utf-8','utf-8').iconv(value) + when /mswin32/ + result = Iconv.new('utf-8','iso-8859-1').iconv(value) + else + result = Iconv.new('utf-8','unicode').iconv(value) + end # case + result +end end