Common solution: send it to me as a csv file, I'll take care of it.
Why? Because a csv file is super easy to parse. Using the built-in ruby csv reader, every row comes back as an array as you traverse the file, so it's easy to process one row at a time:
CSV::Reader.parse(file).each do |row| #...save some model that this represents... end
The complication that often comes up is that your customers might not know what a csv file is. So you'll get xls, xlsx, ods, pretty much anything.
You could manually save each file as a csv (kinda frustrating).
You could also write a cludgy class that handles the interfaces for different libraries differently.
Or you could use this gist I'm about to provide you for all your parsing needs, taking the power of the "roo" gem, and the built in "csv" parser, and translating all your file types into the same iterate-able interface that you so love:
Now you can just write:
SpreadsheetParser.parse(file) do |row| #...pretend its a csv file, every row is just an array end