How To Parse Excel Spreadsheets in Rails
Parsing Excel spreadsheets in Rails is a quite simple task with the gem called Roo. Let’s do it step by step.
First off, you must include Roo gem in your Gemfile and install it:
gem 'roo', '~> 1.13.2'
bundle install
Opening an Excel spreadsheet is deadly simple:
file = Roo::Excel.new(file_path)
#or
file = Roo::Excelx.new(file_path)
This file instance has rows in itself. You can access them with row numbers:
file.row(1) # Gives first row
file.row(2) # Gives second row
Also you can access row numbers for the first and last:
file.first_row # Gives first row’s number, usually it’s 1
file.last_row # Gives last row’s number
Each row is an array, so you can access with index, like:
file.row(1)[0] # Gives the first value in the first row
file.row(1)[1] # Gives the second value in the first row
Now I would like to show a real life example with model relations. Let’s suppose we have a list which has many nodes. We are going to parse values from Excel spreadsheet and create nodes with these values which belongs to a list. Let’s take a look at models:
class List < ActiveRecord::Base
has_many :nodes
end
class Node < ActiveRecord::Base
belongs_to :list
end
Now we must add a method to List model in order to parse our spreadsheet:
class List < ActiveRecord::Base
has_many :nodes
def parse(file_path)
file = Roo::Excel.new(file_path)
(1..file.last_row).each do |i|
row = file.row(i)
node = self.nodes.new(attribute1: row[0], attribute2: row[1]) # Depends on your needs
node.save! if node.valid? # Make sure to use validations
end
end
end
You can also use Paperclip attachment to get file, like self.attachment. And it’s better if you use opening handler to support different types of Excel spreadsheets.
def open_file(file)
case File.extname(file.original_filename)
when '.xls' then Roo::Excel.new(file.path)
when '.xlsx' then Roo::Excelx.new(file.path)
else raise "Unknown file type: #{file.original_filename}"
end
end
Now use it in the parser method:
def parse(file_path)
file = open_file(file_path)
...
...
end
Last of all you might want to put open_file method under private. Now it’s up to you when to use parser method. You can use it in basic model callbacks or observers.
comments powered by Disqus