• Login
sketchucation logo sketchucation
  • Login
⚠️ Libfredo 15.4b | Minor release with bugfixes and improvements Update

[code] reading a CSV file

Scheduled Pinned Locked Moved Developers' Forum
5 Posts 2 Posters 3.0k Views 2 Watching
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    Dan Rathbun
    last edited by Dan Rathbun 28 Jul 2010, 01:20

    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.

    
    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.

    I'm not here much anymore.

    1 Reply Last reply Reply Quote 0
    • D Offline
      Dan Rathbun
      last edited by 28 Jul 2010, 19:52

      Returning CSV data as an Array of record Hashes

      Feel free to change the methodname to suit your taste.

      
      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.

      I'm not here much anymore.

      1 Reply Last reply Reply Quote 0
      • Z Offline
        zps222
        last edited by 3 Aug 2010, 09:44

        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.

        1 Reply Last reply Reply Quote 0
        • D Offline
          Dan Rathbun
          last edited by 3 Aug 2010, 12:00

          [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.
          1. 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.

          I'm not here much anymore.

          1 Reply Last reply Reply Quote 0
          • D Offline
            Dan Rathbun
            last edited by 29 Mar 2011, 20:31

            @zps222 said:

            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 OWNidentifier 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 said:

            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.

            I'm not here much anymore.

            1 Reply Last reply Reply Quote 0
            • 1 / 1
            • First post
              Last post
            Buy SketchPlus
            Buy SUbD
            Buy WrapR
            Buy eBook
            Buy Modelur
            Buy Vertex Tools
            Buy SketchCuisine
            Buy FormFonts

            Advertisement