rubyxl roo read rails ruby excel

roo - ¿Analizar archivos XLS y XLSX(MS Excel) con Ruby?



ruby excel (10)

Acabo de encontrar a roo , eso podría hacer el trabajo, funciona para mis requisitos, leyendo una hoja de cálculo básica.

¿Hay gemas capaces de analizar archivos XLS y XLSX? He encontrado Spreadsheet y ParseExcel, pero ambos no entienden el formato XLSX :( ¿Alguna idea?

Gracias.


Estoy usando Creek que usa nokogiri. Es rápido. Usé 8.3 segundos en una mesa 21x11250 xlsx en mi Macbook Air. Lo tengo para trabajar en ruby ​​1.9.3+. El formato de salida para cada fila es un hash de fila y nombre de columna para el contenido de la celda: {"A1" => "una celda", "B1" => "otra celda"} El hash no garantiza que las claves estarán en el orden original de la columna. https://github.com/pythonicrubyist/creek

dullard es otra muy buena que usa nokogiri. Es súper rápido Usé 6.7 segundos en una mesa 21x11250 xlsx en mi Macbook Air. Lo tengo para trabajar en ruby ​​2.0.0+. El formato de salida para cada fila es una matriz: ["una celda", "otra celda"] https://github.com/thirtyseven/dullard

simple_xlsx_reader que se ha mencionado es genial, un poco lento. Usé 91 segundos en una mesa 21x11250 xlsx en mi Macbook Air. Lo tengo para trabajar en ruby ​​1.9.3+. El formato de salida para cada fila es una matriz: ["una celda", "otra celda"] https://github.com/woahdae/simple_xlsx_reader

Otra interesante es oxcelix. Utiliza el analizador SAX de ox que supuestamente es más rápido que el analizador DOM y SAX de ambos nokogiri. Supuestamente produce una Matriz. No pude arreglarlo. Además, hubo algunos problemas de dependencia con rubyzip. No lo recomendaría

En conclusión, si usa una versión de rubí inferior a 2.0.0, use Creek. Si usa ruby ​​2.0.0+, use el término "aburrido" porque es más rápido y conserva el orden de columnas de la tabla.


He trabajado mucho con Spreadsheet y rubyXL en las últimas dos semanas y debo decir que ambas son excelentes herramientas. Sin embargo, un área que ambos sufren es la falta de ejemplos sobre cómo implementar realmente algo útil. Actualmente estoy construyendo un rastreador y usando rubyXL para analizar archivos xlsx y hojas de cálculo para todo lo que sea xls. Espero que el siguiente código pueda servir como un ejemplo útil y mostrar cuán efectivas pueden ser estas herramientas.

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"


La biblioteca RemoteTable utiliza roo internamente. Facilita la lectura de hojas de cálculo de diferentes formatos (XLS, XLSX, CSV, etc. posiblemente remotas, posiblemente almacenadas dentro de un zip, gz, etc.):

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

Salida:

{"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"}


La gema rubyXL analiza los archivos XLSX maravillosamente.


La gema roo funciona muy bien para Excel (.xls y .xlsx) y está siendo desarrollada activamente.

Estoy de acuerdo en que la sintaxis no es buena ni de color rubí. Pero eso se puede lograr fácilmente con algo como:

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


La mayoría de los ejemplos en línea, incluido el sitio web del autor para la gema de hoja de cálculo, demuestran que se lee todo el contenido de un archivo de Excel en la memoria RAM. Eso está bien si tu hoja de cálculo es pequeña.

xls = Spreadsheet.open(file_path)

Para cualquier persona que trabaje con archivos muy grandes, una mejor manera es leer en secuencia el contenido del archivo. La gema de hoja de cálculo lo admite, aunque no está bien documentada en este momento (alrededor del 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


No pude encontrar un analizador xlsx satisfactorio. RubyXL no da fecha a la conversión de tipos, Roo intentó encasillar un número como una fecha, y ambos son un desastre tanto en la API como en el código.

Entonces, escribí rubygems.org/gems/simple_xlsx_reader . Sin embargo, tendrías que usar algo más para xls, así que tal vez no sea la respuesta completa que estás buscando.


Recientemente necesité analizar algunos archivos de Excel con Ruby. La abundancia de bibliotecas y opciones resultó ser confusa, así que escribí una publicación en el blog sobre eso.

Aquí hay una tabla de diferentes bibliotecas de Ruby y lo que admiten:

Si le importa el rendimiento, aquí es cómo se comparan las bibliotecas xlsx :

Tengo un código de muestra para leer archivos xlsx con cada biblioteca compatible here

Estos son algunos ejemplos para leer archivos xlsx con algunas bibliotecas diferentes:

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

roo

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

Arroyo

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

Aquí hay un ejemplo de xls leer un archivo xls heredado usando la biblioteca de spreadsheet :

hoja de cálculo

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


Si busca bibliotecas más modernas, consulte la Hoja de cálculo: http://spreadsheet.rubyforge.org/GUIDE_txt.html . No puedo decir si es compatible con archivos XLSX, pero considerando que está desarrollado activamente, supongo que sí (no estoy en Windows ni en Office, así que no puedo probar).

En este punto, parece que roo es una buena opción nuevamente. Es compatible con XLSX, permite (algunas) iteraciones simplemente usando times con acceso a la celda. Lo admito, aunque no es bonito.

Además, RubyXL ahora puede darle una especie de iteración usando su método extract_data , que le proporciona una matriz de datos en 2d, que se puede repetir fácilmente.

Alternativamente, si está tratando de trabajar con archivos XLSX en Windows, puede usar la biblioteca Win32OLE de Ruby que le permite interactuar con objetos OLE, como los proporcionados por Word y Excel. Sin embargo , como @PanagiotisKanavos se menciona en los comentarios, esto tiene algunos inconvenientes principales:

  • Excel debe estar instalado
  • Se inicia una nueva instancia de Excel para cada documento
  • La memoria y el consumo de otros recursos es mucho más de lo necesario para una simple manipulación de documentos XLSX.

Pero si elige usarlo, puede optar por no mostrar Excel, cargar su archivo XLSX y acceder a través de él. No estoy seguro de si es compatible con la iteración, sin embargo, no creo que sea demasiado difícil construir en torno a los métodos proporcionados, ya que es la API Microsoft OLE completa para Excel. Aquí está la documentación: http://support.microsoft.com/kb/222101 Aquí está la gema: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/win32ole/rdoc/WIN32OLE.html

De nuevo, las opciones no se ven mucho mejor, pero me temo que no hay mucho más. es difícil analizar un formato de archivo que es una caja negra. Y esos pocos que lograron romperlo no lo hicieron visiblemente. Google Docs es de código cerrado, y LibreOffice tiene miles de líneas de harry C ++.