require 'rubygems' require 'csv' require 'time' # The Csv class can read csv files (must be separated with commas) which then # can be handled like spreadsheets. This means you can access cells like A5 # within these files. # The Csv class provides only string objects. If you want conversions to other # types you have to do it yourself. class Roo::Csv < Roo::GenericSpreadsheet def initialize(filename, packed=nil, file_warning=:error, tmpdir=nil) @filename = filename @cell = Hash.new @cell_type = Hash.new @cells_read = Hash.new @first_row = Hash.new @last_row = Hash.new @first_column = Hash.new @last_column = Hash.new end # Returns an array with the names of the sheets. In Csv class there is only # one dummy sheet, because a csv file cannot have more than one sheet. def sheets ['default'] end def cell(row, col, sheet=nil) sheet ||= @default_sheet read_cells(sheet) unless @cells_read[sheet] row,col = normalize(row,col) @cell[[row,col]] end def celltype(row, col, sheet=nil) sheet ||= @default_sheet read_cells(sheet) unless @cells_read[sheet] row,col = normalize(row,col) @cell_type[[row,col]] end def cell_postprocessing(row,col,value) value end private TYPE_MAP = { String => :string, Float => :float, Date => :date, DateTime => :datetime, } def celltype_class(value) TYPE_MAP[value.class] end def read_cells(sheet=nil) sheet ||= @default_sheet @cell_type = {} unless @cell_type @cell = {} unless @cell @first_row[sheet] = 1 @last_row[sheet] = 0 @first_column[sheet] = 1 @last_column[sheet] = 1 rownum = 1 CSV.foreach(@filename) do |row| row.each_with_index do |elem,i| @cell[[rownum,i+1]] = cell_postprocessing rownum,i+1, elem @cell_type[[rownum,i+1]] = celltype_class @cell[[rownum,i+1]] if i+1 > @last_column[sheet] @last_column[sheet] += 1 end end rownum += 1 @last_row[sheet] += 1 end @cells_read[sheet] = true #-- adjust @first_row if neccessary loop do if !row(@first_row[sheet]).any? and @first_row[sheet] < @last_row[sheet] @first_row[sheet] += 1 else break end end #-- adjust @last_row if neccessary loop do if !row(@last_row[sheet]).any? and @last_row[sheet] and @last_row[sheet] > @first_row[sheet] @last_row[sheet] -= 1 else break end end #-- adjust @first_column if neccessary loop do if !column(@first_column[sheet]).any? and @first_column[sheet] and @first_column[sheet] < @last_column[sheet] @first_column[sheet] += 1 else break end end #-- adjust @last_column if neccessary loop do if !column(@last_column[sheet]).any? and @last_column[sheet] and @last_column[sheet] > @first_column[sheet] @last_column[sheet] -= 1 else break end end end end # class Csv