[code] reading a CSV file

[code] reading a CSV file

Postby Dan Rathbun » Wed Jul 28, 2010 2:20 am

Here's an example by Jim Foltz (he posted in GoogleGroups - Sketchup Developers),
but modified, module and method wrapped.

I (Dan) also added:
  • flexibility for a header row
  • setting a value delimiter in the method call.

Returning CSV data as an Array of record Arrays

Feel free to change the methodname to suit your taste.
Code: Select all
module MyTopLevelNamespace  #<--- you change this
  module MyPlugin           #<--- you change this also
    class<<self

      def read_csv_to_array(file,
                            relapath='.',
                            basepath=Dir.getwd,
                            delim=',',
                            header=false)
        firstline=true
        data=[]
        IO.foreach("#{File.join(basepath,relapath,file)}") do |line|
          if header && firstline
            headrec = line.split(delim)
            firstline=false
          else
            record = line.split(delim)
            data << record
          end
        end # foreach
        #
        return ( header ? [headrec,data] : data )
        #
      end # def

    end # class self

    begin
      dirNow = Dir.getwd # save current dir
      subpath = 'relative/path/to/data'
      Dir.chdir(ENV['USER']+'/somesubdir')
      records = read_csv_to_array('filename.csv',subpath)
      Dir.chdir(dirNow) # restore the dir
      #
      # do stuff with array of record arrays
      #
    end

  end # module
end # module

If you set header=true, then the returned array will have 2 elements:
  • the 1st will be the header row array (1 record),
  • the 2nd will be an multi-record array (an array of record arrays.)
Otherwise with the default (header=false,)
  • the method would return just an array of record arrays.


EDIT: updated

Reordered arguments to method, all but file with defaults:
relapath (defaults to current dir ['.'])
basepath (defaults to current working dir. [Dir.getwd])
delim (defaults to comma. [','])
header (defaults to false.)


COMMUNITY CONTENT - Public Domain - Author claims no copyright.
Moderators may edit post / correct code snippet(s) at will.
0
Last edited by Dan Rathbun on Wed Jul 28, 2010 8:55 pm, edited 4 times in total.
    I'm not here much anymore. But a PM will fire email notifications.
    User avatar
    Dan Rathbun 
    PluginStore Author
    PluginStore Author
     

    Re: [code] reading a CSV file

    Postby Dan Rathbun » Wed Jul 28, 2010 5:47 pm

    Returning CSV data as an Array of record Hashes

    Feel free to change the methodname to suit your taste.
    Code: Select all
    module MyTopLevelNamespace  #<--- you change this
      module MyPlugin           #<--- you change this also
        class<<self

          def read_csv_to_hash_array(file,
                                     relapath='.',
                                     basepath=Dir.getwd,
                                     delim=',',
                                     header=nil)
            firstline=true
            data=[]
            headrec=[]
            IO.foreach("#{File.join(basepath,relapath,file)}") do |line|
              if header.nil? && firstline
                headrec = line.split(delim)
                firstline=false
              else
                record = line.split(delim)
                data << record
              end
            end # foreach
            # use custom hash keys passed in header Array
            headrec = header unless header.nil?
            hasheddata=[]
            data.each do |rec|
              rechash={}
              headrec.each_with_index {|h,i| rechash[h.to_s]=rec[i] }
              hasheddata << rechash.dup
            end # each rec
            #
            return hasheddata
            #
          end # def

        end # class self

        begin
          dirNow = Dir.getwd # save current dir
          subpath = 'relative/path/to/data'
          Dir.chdir(ENV['USER']+'/somesubdir')
          records = read_csv_to_hash_array('filename.csv',subpath)
          Dir.chdir(dirNow) # restore the dir
          #
          # do stuff with array of record hashes
          #
        end

      end # module
    end # module



    EDIT: updated
    header argument
    nil (Use firstrow from CSV file as Hash keys.)
    ['key1','key2',...] (Use Array strings as Hash keys.)

    Reordered arguments to method, all but file with defaults:
    relapath (defaults to current dir ['.'])
    basepath (defaults to current working dir. [Dir.getwd])
    delim (defaults to comma. [','])
    header (defaults to nil.)


    COMMUNITY CONTENT - Public Domain - Author claims no copyright.
    Moderators may edit post / correct code snippet(s) at will.
    0
    Last edited by Dan Rathbun on Wed Jul 28, 2010 8:52 pm, edited 1 time in total.
      I'm not here much anymore. But a PM will fire email notifications.
      User avatar
      Dan Rathbun 
      PluginStore Author
      PluginStore Author
       

      Re: [code] reading a CSV file : FAQ

      Postby Dan Rathbun » Wed Jul 28, 2010 8:19 pm

      [code] reading a CSV file : FAQ

      Fequently Asked Questions

      1. What if I have string data that has embeded commas ??
        • Export your CSV from your spreadsheet using a delimiter other than comma. '||' or '$$' etc.
        • pass your custom delimiter to the method as the delim argument.
      2. How do I import from a TAB delimited datafile ??
          Call the method and specify 9.chr for the delim argument.



      COMMUNITY CONTENT - Public Domain - Author claims no copyright.
      Moderators may edit post / correct code snippet(s) at will.
      0
      Last edited by Dan Rathbun on Tue Aug 03, 2010 1:00 pm, edited 1 time in total.
        I'm not here much anymore. But a PM will fire email notifications.
        User avatar
        Dan Rathbun 
        PluginStore Author
        PluginStore Author
         

        Re: [code] reading a CSV file

        Postby zps222 » Tue Aug 03, 2010 10:44 am

        Hi, Dan, I simply paste "module MyTopLevelNamespace" in to Ruby console window of SU, but the error comes.
        Error: #<SyntaxError: (eval):978: compile error
        (eval):978: syntax error

        So why?

        By the way, can I use eclipse to run your code?

        Thank you.
        0

        zps222 
         

        Re: [code] reading a CSV file

        Postby Dan Rathbun » Tue Mar 29, 2011 9:31 pm

        zps222 wrote: Hi, Dan, I simply paste "module MyTopLevelNamespace" in to Ruby console window of SU, but the error comes. So why?

        A module definition is a block statement. It's meant to be read by the interpreter.

        The console is a line evaluation function.
        You CAN make a module at the console by putting it all on 1 line, like:
        module Zps222; def say_hello(); puts "Hello!"; end; end

        YOU are supposed to choose YOUR OWN identifier for a toplevel module name (namespace.)
        Replace "MyTopLevelNamespace" with a unique name that YOU decide. (You can use Zps222, or whatever you want, as long as it is unique for YOU, and noone else will use it.)

        Also "MyPlugin", you change it to whatever name you want your plugin to be.

        zps222 wrote:By the way, can I use eclipse to run your code?

        Yes. This code is not Sketchup specific. It's just plain old standard Ruby.
        0


        Last bumped by Dan Rathbun on Tue Mar 29, 2011 9:31 pm.
          I'm not here much anymore. But a PM will fire email notifications.
          User avatar
          Dan Rathbun 
          PluginStore Author
          PluginStore Author
           

          SketchUcation One-Liner Adverts

          by Ad Machine » 5 minutes ago



          Ad Machine 
          Robot
           



           

          Return to Developers' Forum

          Who is online

          Users browsing this forum: No registered users and 15 guests