https://github.com/roo-rb/roo
Roo provides an interface to spreadsheets of several sorts.
https://github.com/roo-rb/roo
Keywords from Contributors
activerecord mvc activejob rubygems static-code-analysis rubocop code-formatter rspec ruby-gem crash-reporting
Last synced: about 11 hours ago
JSON representation
Repository metadata
Roo provides an interface to spreadsheets of several sorts.
- Host: GitHub
- URL: https://github.com/roo-rb/roo
- Owner: roo-rb
- License: mit
- Created: 2012-03-07T22:31:18.000Z (almost 14 years ago)
- Default Branch: master
- Last Pushed: 2025-10-01T09:43:45.000Z (5 months ago)
- Last Synced: 2026-02-25T16:55:43.747Z (6 days ago)
- Language: Ruby
- Homepage:
- Size: 6.65 MB
- Stars: 2,866
- Watchers: 62
- Forks: 504
- Open Issues: 121
- Releases: 6
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
README.md
Roo
Roo implements read access for all common spreadsheet types. It can handle:
- Excel 2007 - 2013 formats (xlsx, xlsm)
- LibreOffice / OpenOffice.org formats (ods)
- CSV
- Excel 97, Excel 2002 XML, and Excel 2003 XML formats when using the roo-xls gem (xls, xml)
- Google spreadsheets with read/write access when using roo-google
Important note about next major release
There a plan to make a new major release which will have better support for Ruby 3.x
Please leave your comments there - https://github.com/roo-rb/roo/issues/630
Installation
Install as a gem
$ gem install roo
Or add it to your Gemfile
gem "roo", "~> 3.0.0"
Usage
Opening a spreadsheet
You can use the Roo::Spreadsheet class so roo automatically detects which parser class to use for you.
require 'roo'
file_name = './new_prices.xlsx'
xlsx = Roo::Spreadsheet.open(file_name)
xlsx.info
# => Returns basic info about the spreadsheet file
Roo::Spreadsheet.open can accept both string paths and File instances. Also, you can provide the extension of the file as an option:
require 'roo'
file_name = './rails_temp_upload'
xlsx = Roo::Spreadsheet.open(file_name, extension: :xlsx)
xlsx.info
# => Returns basic info about the spreadsheet file
On the other hand, if you know what the file extension is, you can use the specific parser class instead:
require 'roo'
xlsx = Roo::Excelx.new("./new_prices.xlsx")
xlsx.info
# => Returns basic info about the spreadsheet file
Working with sheets
ods.sheets
# => ['Info', 'Sheet 2', 'Sheet 3'] # an Array of sheet names in the workbook
ods.sheet('Info').row(1)
ods.sheet(0).row(1)
# Set the last sheet as the default sheet.
ods.default_sheet = ods.sheets.last
ods.default_sheet = ods.sheets[2]
ods.default_sheet = 'Sheet 3'
# Iterate through each sheet
ods.each_with_pagename do |name, sheet|
p sheet.row(1)
end
Accessing rows and columns
Roo uses Excel's numbering for rows, columns and cells, so 1 is the first index, not 0 as it is in an Array
sheet.row(1)
# returns the first row of the spreadsheet.
sheet.column(1)
# returns the first column of the spreadsheet.
Almost all methods have an optional argument sheet. If this parameter is omitted, the default_sheet will be used.
sheet.first_row(sheet.sheets[0])
# => 1 # the number of the first row
sheet.last_row
# => 42 # the number of the last row
sheet.first_column
# => 1 # the number of the first column
sheet.last_column
# => 10 # the number of the last column
Accessing cells
You can access the top-left cell in the following ways
sheet.cell(1,1)
sheet.cell('A',1)
sheet.cell(1,'A')
sheet.a1
# Access the second sheet's top-left cell.
sheet.cell(1,'A',sheet.sheets[1])
Querying a spreadsheet
Use each to iterate over each row.
If each is given a hash with the names of some columns, then each will generate a hash with the columns supplied for each row.
sheet.each(id: 'ID', name: 'FULL_NAME') do |hash|
puts hash.inspect
# => { id: 1, name: 'John Smith' }
end
Use sheet.parse to return an array of rows. Column names can be a String or a Regexp.
sheet.parse(id: /UPC|SKU/, qty: /ATS*\sATP\s*QTY\z/)
# => [{:id => 727880013358, :qty => 12}, ...]
Use the :headers option to include the header row in the parsed content.
sheet.parse(headers: true)
Use the :header_search option to locate the header row and assign the header names.
sheet.parse(header_search: [/UPC*SKU/,/ATS*\sATP\s*QTY\z/])
Use the :clean option to strip out control characters and surrounding white space.
sheet.parse(clean: true)
Options
When opening the file you can add a hash of options.
expand_merged_ranges
If you open a document with merged cells and do not want to end up with nil values for the rows after the first one.
xlsx = Roo::Excelx.new('./roo_error.xlsx', {:expand_merged_ranges => true})
Exporting spreadsheets
Roo has the ability to export sheets using the following formats. It
will only export the default_sheet.
sheet.to_csv
sheet.to_matrix
sheet.to_xml
sheet.to_yaml
Specify the file as default argument for #to_csv:
sheet.to_csv(File.new("/dev/null"))
specify the custom separator:
sheet.to_csv(separator: ":") # "," using by default
Excel (xlsx and xlsm) Support
Stream rows from an Excelx spreadsheet.
xlsx = Roo::Excelx.new("./test_data/test_small.xlsx")
xlsx.each_row_streaming do |row|
puts row.inspect # Array of Excelx::Cell objects
end
By default blank cells will be excluded from the array. To keep them, use the option pad_cells = true. (They will be set to nil in the array)
xlsx.each_row_streaming(pad_cells: true) do |row|
puts row.inspect # Array of Excelx::Cell objects
end
To stream only some of the rows, you can use the max_rows and offsetoptions.
xlsx.each_row_streaming(offset: 1) do |row| # Will exclude first (inevitably header) row
puts row.inspect # Array of Excelx::Cell objects
end
xlsx.each_row_streaming(max_rows: 3) do |row| # Will yield 4 rows (it's automatically incremented by 1) after the supplied offset.
puts row.inspect # Array of Excelx::Cell objects
end
Iterate over each row
xlsx.each_row do |row|
...
end
Roo::Excelx also provides these helpful methods.
xlsx.excelx_type(3, 'C')
# => :numeric_or_formula
xlsx.cell(3, 'C')
# => 600000383.0
xlsx.excelx_value(row,col)
# => '600000383'
xlsx.formatted_value(row,col)
# => '0600000383'
Roo::Excelx can access celltype, comments, font information, formulas, hyperlinks and labels.
xlsx.comment(1,1, ods.sheets[-1])
xlsx.font(1,1).bold?
xlsx.formula('A', 2)
OpenOffice / LibreOffice Support
Roo::OpenOffice has support for encrypted OpenOffice spreadsheets.
# Load an encrypted OpenOffice Spreadsheet
ods = Roo::OpenOffice.new("myspreadsheet.ods", password: "password")
Roo::OpenOffice can access celltype, comments, font information, formulas and labels.
ods.celltype
# => :percentage
ods.comment(1,1, ods.sheets[-1])
ods.font(1,1).italic?
# => false
ods.formula('A', 2)
CSV Support
# Load a CSV file
csv = Roo::CSV.new("mycsv.csv")
Because Roo uses the standard CSV library, you can use options available to that library to parse csv files. You can pass options using the csv_options key.
For instance, you can load tab-delimited files (.tsv), and you can use a particular encoding when opening the file.
# Load a tab-delimited csv
csv = Roo::CSV.new("mytsv.tsv", csv_options: {col_sep: "\t"})
# Load a csv with an explicit encoding
csv = Roo::CSV.new("mycsv.csv", csv_options: {encoding: Encoding::ISO_8859_1})
You can also open csv files through the Roo::Spreadsheet class (useful if you accept both CSV and Excel types from a user file upload, for example).
# Load a spreadsheet from a file path
# Roo figures out the right parser based on file extension
spreadsheet = Roo::Spreadsheet.open(csv_or_xlsx_file)
# Load a csv and auto-strip the BOM (byte order mark)
# csv files saved from MS Excel typically have the BOM marker at the beginning of the file
spreadsheet = Roo::Spreadsheet.open("mycsv.csv", { csv_options: { encoding: 'bom|utf-8' } })
Upgrading from Roo 1.13.x
If you use .xls or Google spreadsheets, you will need to install roo-xls or roo-google to continue using that functionality.
Roo's public methods have stayed relatively consistent between 1.13.x and 2.0.0, but please check the Changelog to better understand the changes made since 1.13.x.
Contributing
Features
- Fork it ( https://github.com/roo-rb/roo/fork )
- Install it (
bundle install --with local_development) - Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'My new feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
Testing
Roo uses Minitest and RSpec. The best of both worlds! Run bundle exec rake to
run the tests/examples.
You can run the tests/examples with Rspec like reporters by running
USE_REPORTERS=true bundle exec rake
Roo also has a few tests that take a long time (5+ seconds). To run these, use
LONG_RUN=true bundle exec rake
Issues
If you find an issue, please create a gist and refer to it in an issue (sample gist). Here are some instructions for creating such a gist.
- Create a gist with code that creates the error.
- Clone the gist repo locally, add a stripped down version of the offending spreadsheet to the gist repo, and push the gist's changes master.
- Paste the gist url here.
License
Owner metadata
- Name: roo-rb
- Login: roo-rb
- Email:
- Kind: organization
- Description:
- Website:
- Location:
- Twitter:
- Company:
- Icon url: https://avatars.githubusercontent.com/u/9793185?v=4
- Repositories: 3
- Last ynced at: 2024-03-25T21:16:10.227Z
- Profile URL: https://github.com/roo-rb
GitHub Events
Total
- Release event: 1
- Delete event: 1
- Pull request event: 20
- Fork event: 9
- Issues event: 7
- Watch event: 69
- Issue comment event: 24
- Push event: 21
- Pull request review comment event: 5
- Pull request review event: 6
- Create event: 4
Last Year
- Release event: 1
- Delete event: 1
- Pull request event: 6
- Fork event: 5
- Issues event: 4
- Watch event: 43
- Issue comment event: 14
- Push event: 13
- Pull request review event: 1
- Create event: 4
Committers metadata
Last synced: 7 days ago
Total Commits: 937
Total Committers: 155
Avg Commits per committer: 6.045
Development Distribution Score (DDS): 0.708
Commits in past year: 23
Committers in past year: 3
Avg Commits per committer in past year: 7.667
Development Distribution Score (DDS) in past year: 0.217
| Name | Commits | |
|---|---|---|
| Ben Woosley | b****y@g****m | 274 |
| Hugh McGowan | h****n@y****m | 112 |
| Steven Daniels | s****8@g****m | 105 |
| Alexander Simonov | a****x@s****e | 63 |
| chopraanmol1 | c****1@g****m | 30 |
| Randy Burkes | r****s@g****m | 27 |
| t.pickett66 | t****6@g****m | 22 |
| Pablo Herrero | p****o@g****m | 13 |
| David Welguisz | w****z@f****m | 10 |
| Patrick Kulling | k****t@p****e | 9 |
| Ben Hundley | b****y@g****m | 9 |
| Brad Midgley | b****y@s****m | 9 |
| taichi | t****0@g****m | 8 |
| Akira Matsuda | r****e@d****p | 7 |
| Aleksey Strizhak | a****k@g****m | 6 |
| Thomas Bradley | t****m@m****k | 6 |
| Mike Rose | m****n@g****m | 6 |
| Hermes Ojeda Ruiz | h****r@g****m | 6 |
| Graham Turner | t****m@g****m | 6 |
| Brian Fujito | b****o@g****m | 6 |
| Michael Witrant | m****l@o****r | 5 |
| Kevin Grigorenko | k****n@m****m | 5 |
| Mike Dalessio | m****o@b****m | 5 |
| Matthew Rudy Jacobs | m****s@g****m | 4 |
| Jeremy Aube | j****e@g****m | 4 |
| Torey Maerz | t****m@g****m | 4 |
| Tony Novak | t****y@a****m | 4 |
| Jeremy Ward | j****d@c****m | 4 |
| David J. Hamilton | d****h@h****m | 4 |
| Adam Rice | a****r@b****u | 4 |
| and 125 more... | ||
Committer domains:
- ouvrages-web.fr: 2
- benchmarksolutions.com: 2
- illuminatedcomputing.com: 1
- talbott.ws: 1
- bunnymatic.com: 1
- mikeshop.net: 1
- lazymalevolence.com: 1
- rautanen.info: 1
- hespul.org: 1
- benizi.com: 1
- onegoodcode.com: 1
- pgi.com: 1
- flatstack.com: 1
- kasi-net.org: 1
- prograils.com: 1
- sergeyp.me: 1
- rprojekt.org: 1
- bebanjo.com: 1
- cprussin.net: 1
- danmeakin.com: 1
- simonov.me: 1
- freescale.com: 1
- patrickkulling.de: 1
- spiff.com: 1
- dio.jp: 1
- m.onkey.co.uk: 1
- myplaceonline.com: 1
- amitree.com: 1
- crowdcompass.com: 1
- hjdivad.com: 1
- bioconcepts.com.au: 1
- zuzara.com: 1
- scpike.net: 1
- impactdata.com.au: 1
- fitmentgroup.com: 1
- termsync.com: 1
- mrhenry.be: 1
- sheetjs.com: 1
- oakfocus.net: 1
- cubesystems.lv: 1
- thecampus.cc: 1
- salsify.com: 1
- kubosch.no: 1
- tmh.cc: 1
- atg.auto: 1
- dylanmarkow.com: 1
- trux.info: 1
- pressedcode.com: 1
- airbladesoftware.com: 1
- renuo.ch: 1
- sher.pl: 1
- me.com: 1
- kunalashah.com: 1
- yahoo.co.in: 1
- webascender.com: 1
- josh.ch: 1
- patientway.com: 1
- trackernetworks.com: 1
- xaver.com.ar: 1
- blinkbox.com: 1
- carbonfive.com: 1
- fabriquartz.com: 1
- mckinsey.com: 1
- pivotallabs.com: 1
- joshsoftware.com: 1
- jibe.com: 1
- rodrigoramirez.com: 1
- ultimatesoftware.com: 1
- circuitllc.com: 1
- owenstephens.co.uk: 1
- niclasnilsson.se: 1
- sevenfifty.com: 1
- lutaaya.com: 1
- mac.com: 1
- genshin.org: 1
- mail.ru: 1
- aiming-inc.com: 1
Issue and Pull Request metadata
Last synced: about 1 month ago
Total issues: 72
Total pull requests: 85
Average time to close issues: over 1 year
Average time to close pull requests: about 1 year
Total issue authors: 69
Total pull request authors: 65
Average comments per issue: 1.93
Average comments per pull request: 2.33
Merged pull request: 36
Bot issues: 0
Bot pull requests: 2
Past year issues: 8
Past year pull requests: 9
Past year average time to close issues: about 2 months
Past year average time to close pull requests: 1 day
Past year issue authors: 8
Past year pull request authors: 6
Past year average comments per issue: 0.63
Past year average comments per pull request: 2.33
Past year merged pull request: 6
Past year bot issues: 0
Past year bot pull requests: 2
Top Issue Authors
- estani (3)
- Beartech (2)
- codescaptain (1)
- aclarembeau (1)
- jamesst20 (1)
- paddor (1)
- billy-whizz (1)
- cenxky (1)
- nikolai-b (1)
- r-kanai (1)
- leboshi (1)
- aluisioalves123 (1)
- mark-young-atg (1)
- AaronBui-gif (1)
- Shubhamgoel123 (1)
Top Pull Request Authors
- HashNotAdam (9)
- oTiMo (2)
- mark-young-atg (2)
- Xenofex (2)
- tagliala (2)
- patrickkulling (2)
- jukra (2)
- krishantaylor (2)
- github-actions[bot] (2)
- Mifrill (2)
- msharma-ml (2)
- viktorzimmermann (2)
- andyundso (2)
- rbclark (1)
- javierojeda94 (1)
Top Issue Labels
- bug (2)
- enhancement (1)
- documentation (1)
Top Pull Request Labels
- good first issue (2)
- autorelease: pending (2)
- enhancement (1)
- bug (1)
Package metadata
- Total packages: 15
-
Total downloads:
- rubygems: 205,582,567 total
- Total docker downloads: 880,784
- Total dependent packages: 183 (may contain duplicates)
- Total dependent repositories: 4,294 (may contain duplicates)
- Total versions: 244
- Total maintainers: 8
ubuntu-23.10: ruby-roo
- Homepage: https://github.com/roo-rb/roo
- Licenses: mit
- Latest release: 2.10.0-1 (published 18 days ago)
- Last Synced: 2026-02-13T18:31:37.448Z (18 days ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 0.214%
- Forks count: 0.347%
- Stargazers count: 0.51%
gem.coop: roo
Roo can access the contents of various spreadsheet files. It can handle * OpenOffice * Excelx * LibreOffice * CSV
- Homepage: https://github.com/roo-rb/roo
- Documentation: http://www.rubydoc.info/gems/roo/
- Licenses: MIT
- Latest release: 3.0.0 (published 5 months ago)
- Last Synced: 2026-03-01T11:03:56.800Z (2 days ago)
- Versions: 93
- Dependent Packages: 0
- Dependent Repositories: 0
- Downloads: 102,785,782 Total
- Docker Downloads: 440,392
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Downloads: 0.254%
- Average: 0.438%
- Docker downloads count: 1.499%
- Maintainers (6)
rubygems.org: roo
Roo can access the contents of various spreadsheet files. It can handle * OpenOffice * Excelx * LibreOffice * CSV
- Homepage: https://github.com/roo-rb/roo
- Documentation: http://www.rubydoc.info/gems/roo/
- Licenses: MIT
- Latest release: 3.0.0 (published 5 months ago)
- Last Synced: 2026-03-01T05:02:20.977Z (2 days ago)
- Versions: 93
- Dependent Packages: 182
- Dependent Repositories: 4,293
- Downloads: 102,782,869 Total
- Docker Downloads: 440,392
-
Rankings:
- Dependent packages count: 0.201%
- Downloads: 0.309%
- Dependent repos count: 0.478%
- Stargazers count: 0.697%
- Average: 0.877%
- Forks count: 1.215%
- Docker downloads count: 2.36%
- Maintainers (6)
proxy.golang.org: github.com/roo-rb/roo
- Homepage:
- Documentation: https://pkg.go.dev/github.com/roo-rb/roo#section-documentation
- Licenses: mit
- Latest release: v3.0.0+incompatible (published 5 months ago)
- Last Synced: 2026-02-25T22:02:33.898Z (6 days ago)
- Versions: 44
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent packages count: 6.497%
- Average: 6.716%
- Dependent repos count: 6.936%
rubygems.org: culturecode-roo
Roo can access the contents of various spreadsheet files. It can handle * OpenOffice * Excelx * LibreOffice * CSV
- Homepage: http://github.com/roo-rb/roo
- Documentation: http://www.rubydoc.info/gems/culturecode-roo/
- Licenses: MIT
- Latest release: 2.0.2 (published almost 11 years ago)
- Last Synced: 2026-02-25T22:02:32.242Z (6 days ago)
- Versions: 2
- Dependent Packages: 1
- Dependent Repositories: 1
- Downloads: 6,958 Total
-
Rankings:
- Stargazers count: 0.678%
- Forks count: 1.181%
- Dependent packages count: 7.656%
- Average: 18.479%
- Dependent repos count: 21.794%
- Downloads: 61.087%
- Maintainers (2)
gem.coop: culturecode-roo
Roo can access the contents of various spreadsheet files. It can handle * OpenOffice * Excelx * LibreOffice * CSV
- Homepage: http://github.com/roo-rb/roo
- Documentation: http://www.rubydoc.info/gems/culturecode-roo/
- Licenses: MIT
- Latest release: 2.0.2 (published almost 11 years ago)
- Last Synced: 2026-02-25T22:02:32.361Z (6 days ago)
- Versions: 2
- Dependent Packages: 0
- Dependent Repositories: 0
- Downloads: 6,958 Total
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 19.751%
- Downloads: 59.253%
- Maintainers (2)
debian-11: ruby-roo
- Homepage: https://github.com/roo-rb/roo
- Documentation: https://packages.debian.org/bullseye/ruby-roo
- Licenses:
- Latest release: 2.8.3-1 (published 20 days ago)
- Last Synced: 2026-02-13T08:24:26.028Z (18 days ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
debian-10: ruby-roo
- Homepage: https://github.com/roo-rb/roo
- Documentation: https://packages.debian.org/buster/ruby-roo
- Licenses: mit
- Latest release: 2.8.2-1 (published 20 days ago)
- Last Synced: 2026-02-13T04:25:18.011Z (18 days ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
debian-12: ruby-roo
- Homepage: https://github.com/roo-rb/roo
- Documentation: https://packages.debian.org/bookworm/ruby-roo
- Licenses:
- Latest release: 2.10.0-1 (published 18 days ago)
- Last Synced: 2026-02-12T23:39:52.644Z (18 days ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
debian-13: ruby-roo
- Homepage: https://github.com/roo-rb/roo
- Documentation: https://packages.debian.org/trixie/ruby-roo
- Licenses:
- Latest release: 2.10.0-2.1 (published 19 days ago)
- Last Synced: 2026-02-13T13:19:11.034Z (18 days ago)
- Versions: 1
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 100%
Dependencies
- activesupport < 5.1 development
- coveralls >= 0 development
- guard-bundler >= 0 development
- guard-minitest >= 0 development
- guard-rspec >= 4.3.1 development
- guard-rubocop >= 0 development
- minitest-reporters >= 0 development
- pry >= 0 development
- rb-readline >= 0 development
- rspec >= 3.0.0 development
- shoulda >= 0 development
- simplecov >= 0.9.0 development
- matrix >= 0 development
- minitest ~> 5.4, >= 5.4.3 development
- rack ~> 1.6, < 2.0.0 development
- rake >= 0 development
- nokogiri ~> 1
- rubyzip >= 1.3.0, < 3.0.0
- actions/checkout v2 composite
- amoniacou/changelog-enforcer v1.4.0 composite
- actions/checkout v2 composite
- ruby/setup-ruby v1 composite
Score: 32.19110544547555