使用RubyparsingXLS和XLSX(MS Excel)文件?

有没有任何gem能够parsingXLS和XLSX文件? 我发现电子表格和ParseExcel,但他们都不明白XLSX格式:(任何想法?

谢谢。

刚刚findroo ,那可能会做这个工作 – 按我的要求工作,阅读一个基本的电子表格。

roo gem非常适用于Excel(.xls和.xlsx),并且正在积极开发。

我同意语法不是很好,也不像ruby-like。 但是,这可以通过以下方式轻松实现:

 class Spreadsheet def initialize(file_path) @xls = Roo::Spreadsheet.open(file_path) end def each_sheet @xls.sheets.each do |sheet| @xls.default_sheet = sheet yield sheet end end def each_row 0.upto(@xls.last_row) do |index| yield @xls.row(index) end end def each_column 0.upto(@xls.last_column) do |index| yield @xls.column(index) end end end 

我最近需要用Rubyparsing一些Excel文件。 图书馆和选项丰富,结果令人困惑,所以我写了一篇关于它的博客文章 。

这是一个不同Ruby库的表格,它们支持什么:

在这里输入图像说明

如果你关心性能,下面是xlsx库的比较: 在这里输入图像说明

我有示例代码来读取每个支持的库在这里 xlsx文件

以下是一些读取具有不同库的xlsx文件的示例:

rubyXL

 require 'rubyXL' workbook = RubyXL::Parser.parse './sample_excel_files/xlsx_500_rows.xlsx' worksheets = workbook.worksheets puts "Found #{worksheets.count} worksheets" worksheets.each do |worksheet| puts "Reading: #{worksheet.sheet_name}" num_rows = 0 worksheet.each do |row| row_cells = row.cells.map{ |cell| cell.value } num_rows += 1 end puts "Read #{num_rows} rows" end 

袋鼠

 require 'roo' workbook = Roo::Spreadsheet.open './sample_excel_files/xlsx_500_rows.xlsx' worksheets = workbook.sheets puts "Found #{worksheets.count} worksheets" worksheets.each do |worksheet| puts "Reading: #{worksheet}" num_rows = 0 workbook.sheet(worksheet).each_row_streaming do |row| row_cells = row.map { |cell| cell.value } num_rows += 1 end puts "Read #{num_rows} rows" end 

 require 'creek' workbook = Creek::Book.new './sample_excel_files/xlsx_500_rows.xlsx' worksheets = workbook.sheets puts "Found #{worksheets.count} worksheets" worksheets.each do |worksheet| puts "Reading: #{worksheet.name}" num_rows = 0 worksheet.rows.each do |row| row_cells = row.values num_rows += 1 end puts "Read #{num_rows} rows" end 

simple_xlsx_reader

 require 'simple_xlsx_reader' workbook = SimpleXlsxReader.open './sample_excel_files/xlsx_500000_rows.xlsx' worksheets = workbook.sheets puts "Found #{worksheets.count} worksheets" worksheets.each do |worksheet| puts "Reading: #{worksheet.name}" num_rows = 0 worksheet.rows.each do |row| row_cells = row num_rows += 1 end puts "Read #{num_rows} rows" end 

以下是使用spreadsheet库读取传统xls文件的示例:

电子表格

 require 'spreadsheet' # Note: spreadsheet only supports .xls files (not .xlsx) workbook = Spreadsheet.open './sample_excel_files/xls_500_rows.xls' worksheets = workbook.worksheets puts "Found #{worksheets.count} worksheets" worksheets.each do |worksheet| puts "Reading: #{worksheet.name}" num_rows = 0 worksheet.rows.each do |row| row_cells = row.to_a.map{ |v| v.methods.include?(:value) ? v.value : v } num_rows += 1 end puts "Read #{num_rows} rows" end 

我正在使用nokogiri的小溪。 它很快。 在我的Macbook Air的21×11250 xlsx表上使用了8.3秒。 得到它在Ruby 1.9.3+上工作。 每行的输出格式是行和列名到单元格内容的散列:{“A1”=>“一个单元格”,“B1”=>“另一个单元格”}哈希不保证键将在原来的列顺序。 https://github.com/pythonicrubyist/creek

杜拉德是另一个使用nokogiri的伟大的人。 这是超快速的。 在我的Macbook Air的21×11250 xlsx表上使用了6.7秒。 得到它在Ruby 2.0.0+的工作。 每行的输出格式是一个数组:[“一个单元格”,“另一个单元格”] https://github.com/thirtyseven/dullard

已经提到的simple_xlsx_reader很棒,有点慢。 在我的Macbook Air上的21×11250 xlsx表上使用了91秒。 得到它在Ruby 1.9.3+上工作。 每行的输出格式是一个数组:[“一个单元格”,“另一个单元格”] https://github.com/woahdae/simple_xlsx_reader

另一个有趣的是oxcelix。 它使用ox的SAXparsing器,它比nokogiri的DOM和SAXparsing器都快。 它应该输出一个matrix。 我无法得到它的工作。 另外,rubyzip也存在一些依赖性问题。 不会推荐它。

总之,如果使用低于2.0.0的ruby版本,请使用creek。 如果使用ruby 2.0.0以上版本,请使用dullard,因为它速度更快,并保留表列顺序。

如果您正在寻找更现代化的图书馆,请参阅Spreadsheet: http : //spreadsheet.rubyforge.org/GUIDE_txt.html 。 我不知道它是否支持XLSX文件,但考虑到它是积极开发的,我猜测它确实(我不在Windows上,或与Office,所以我不能testing)。

在这一点上,看起来roo是一个不错的select。 它支持XLSX,通过使用访问单元格的times允许(某些)迭代。 我承认,虽然不是很好。

另外,RubyXL现在可以使用extract_data方法为您提供一种迭代,该方法为您提供了一个二维数据数组,可以很容易地进行迭代。

或者,如果您想在Windows上使用XLSX文件,则可以使用Ruby的Win32OLE库,使您可以与OLE对象(如Word和Excel提供的对象)进行交互。 不过 ,正如@PanagiotisKanavos在评论中提到的那样,这有几个主要的缺点:

  • Excel必须安装
  • 为每个文档启动一个新的Excel实例
  • 内存和其他资源的消耗远远超过简单的XLSX文档操作所需要的。

但是,如果您select使用它,您可以select不显示Excel,加载您的XLSX文件,并通过它来访问它。 我不确定它是否支持迭代,但是,我不认为这将是很难构build所提供的方法,因为它是Excel的完整的Microsoft OLE API。 这里是文档: http : //support.microsoft.com/kb/222101这是gem: http : //www.ruby-doc.org/stdlib-1.9.3/libdoc/win32ole/rdoc/WIN32OLE.html

再次,选项看起来不太好,但恐怕没有其他的东西了。 很难parsing黑盒子的文件格式。 而那些设法打破它的人并没有那样做。 Google Docs是封闭源代码,LibreOffice是数千行哈利C ++。

rubyXL gem精美地parsingXLSX文件。

过去两周我一直在使用Spreadsheet和rubyXL,我必须说这两个都是很棒的工具。 然而,两个领域都遭受的是缺乏实际有用的实例。 目前我正在构build一个爬虫,并使用rubyXLparsingxlsx文件和Spreadsheet任何xls。 我希望下面的代码可以作为一个有用的例子,并展示这些工具的有效性。

 require 'find' require 'rubyXL' count = 0 Find.find('/Users/Anconia/crawler/') do |file| # begin iteration of each file of a specified directory if file =~ /\b.xlsx$\b/ # check if file is xlsx format workbook = RubyXL::Parser.parse(file).worksheets # creates an object containing all worksheets of an excel workbook workbook.each do |worksheet| # begin iteration over each worksheet data = worksheet.extract_data.to_s # extract data of a given worksheet - must be converted to a string in order to match a regex if data =~ /regex/ puts file count += 1 end end end end puts "#{count} files were found" 

 require 'find' require 'spreadsheet' Spreadsheet.client_encoding = 'UTF-8' count = 0 Find.find('/Users/Anconia/crawler/') do |file| # begin iteration of each file of a specified directory if file =~ /\b.xls$\b/ # check if a given file is xls format workbook = Spreadsheet.open(file).worksheets # creates an object containing all worksheets of an excel workbook workbook.each do |worksheet| # begin iteration over each worksheet worksheet.each do |row| # begin iteration over each row of a worksheet if row.to_s =~ /regex/ # rows must be converted to strings in order to match the regex puts file count += 1 end end end end end puts "#{count} files were found" 

我找不到一个令人满意的xlsxparsing器。 RubyXL不会进行datetypes转换,Roo试图将一个数字作为date进行转换,而且在api和代码中都是一团糟。

所以,我写了simple_xlsx_reader 。 但是,你不得不为xls使用其他的东西,所以也许这不是你想要的完整答案。

大多数在线示例(包括作者的Spreadsheet gem网站)都演示了将Excel文件的全部内容读入RAM中。 如果电子表格很小,那很好。

 xls = Spreadsheet.open(file_path) 

对于使用大文件的人来说,更好的方法是stream式读取文件的内容。 电子表格gem支持这一点 – 虽然目前还没有很好的logging(大约3/2015)。

 Spreadsheet.open(file_path).worksheets.first.rows do |row| # do something with the array of CSV data end 

CITE: https : //github.com/zdavatz/spreadsheet

RemoteTable库在内部使用roo 。 它可以很容易地读取不同格式的电子表格(XLS,XLSX,CSV等,可能是远程的,可能存储在一个zip,gz等):

 require 'remote_table' r = RemoteTable.new 'http://www.fueleconomy.gov/FEG/epadata/02data.zip', :filename => 'guide_jan28.xls' r.each do |row| puts row.inspect end 

输出:

 {"Class"=>"TWO SEATERS", "Manufacturer"=>"ACURA", "carline name"=>"NSX", "displ"=>"3.0", "cyl"=>"6.0", "trans"=>"Auto(S4)", "drv"=>"R", "bidx"=>"60.0", "cty"=>"17.0", "hwy"=>"24.0", "cmb"=>"20.0", "ucty"=>"19.1342", "uhwy"=>"30.2", "ucmb"=>"22.9121", "fl"=>"P", "G"=>"", "T"=>"", "S"=>"", "2pv"=>"", "2lv"=>"", "4pv"=>"", "4lv"=>"", "hpv"=>"", "hlv"=>"", "fcost"=>"1238.0", "eng dscr"=>"DOHC-VTEC", "trans dscr"=>"2MODE", "vpc"=>"4.0", "cls"=>"1.0"} {"Class"=>"TWO SEATERS", "Manufacturer"=>"ACURA", "carline name"=>"NSX", "displ"=>"3.2", "cyl"=>"6.0", "trans"=>"Manual(M6)", "drv"=>"R", "bidx"=>"65.0", "cty"=>"17.0", "hwy"=>"24.0", "cmb"=>"19.0", "ucty"=>"18.7", "uhwy"=>"30.4", "ucmb"=>"22.6171", "fl"=>"P", "G"=>"", "T"=>"", "S"=>"", "2pv"=>"", "2lv"=>"", "4pv"=>"", "4lv"=>"", "hpv"=>"", "hlv"=>"", "fcost"=>"1302.0", "eng dscr"=>"DOHC-VTEC", "trans dscr"=>"", "vpc"=>"4.0", "cls"=>"1.0"} {"Class"=>"TWO SEATERS", "Manufacturer"=>"ASTON MARTIN", "carline name"=>"ASTON MARTIN VANQUISH", "displ"=>"5.9", "cyl"=>"12.0", "trans"=>"Auto(S6)", "drv"=>"R", "bidx"=>"1.0", "cty"=>"12.0", "hwy"=>"19.0", "cmb"=>"14.0", "ucty"=>"13.55", "uhwy"=>"24.7", "ucmb"=>"17.015", "fl"=>"P", "G"=>"G", "T"=>"", "S"=>"", "2pv"=>"", "2lv"=>"", "4pv"=>"", "4lv"=>"", "hpv"=>"", "hlv"=>"", "fcost"=>"1651.0", "eng dscr"=>"GUZZLER", "trans dscr"=>"CLKUP", "vpc"=>"4.0", "cls"=>"1.0"}