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

- old
+ new

@@ -1,52 +1,51 @@ require 'csv' require 'time' -# The Csv class can read csv files (must be separated with commas) which then +# 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 +# The CSV class provides only string objects. If you want conversions to other # types you have to do it yourself. +# +# You can pass options to the underlying CSV parse operation, via the +# :csv_options option. +# -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 +class Roo::CSV < Roo::Base + def initialize(filename, options = {}) + super end attr_reader :filename - # Returns an array with the names of the sheets. In Csv class there is only + # 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]] + read_cells(sheet) + @cell[normalize(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]] + read_cells(sheet) + @cell_type[normalize(row,col)] end def cell_postprocessing(row,col,value) value end + def csv_options + @options[:csv_options] || {} + end + private TYPE_MAP = { String => :string, Float => :float, @@ -56,31 +55,30 @@ def celltype_class(value) TYPE_MAP[value.class] end - def data - @data ||= + def each_row(options, &block) + if uri?(filename) make_tmpdir do |tmpdir| - File.open( - uri?(filename) ? - open_from_uri(filename, tmpdir) : - filename - ) { |f| f.read } + filename = download_uri(filename, tmpdir) + CSV.foreach(filename, options, &block) end + else + CSV.foreach(filename, options, &block) + end end def read_cells(sheet=nil) sheet ||= @default_sheet - @cell_type = {} unless @cell_type - @cell = {} unless @cell + return if @cells_read[sheet] @first_row[sheet] = 1 @last_row[sheet] = 0 @first_column[sheet] = 1 @last_column[sheet] = 1 rownum = 1 - CSV.parse data do |row| + each_row csv_options 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 @@ -110,6 +108,6 @@ @last_column[sheet] and @last_column[sheet] > @first_column[sheet] @last_column[sheet] -= 1 end end -end # class Csv +end