Эффективно конвертировать Excel в CSV в ruby

Я использовал для этого таблицу. Это работает, но иногда может быть очень медленным. Я даже попробовал самоцвет Roo, но это не улучшило производительность. Есть ли лучший способ сделать эту работу? Странно то, что некоторые листы в том же Excel работают быстрее, а некоторые листы работают очень медленно, даже занимая до 1 часа.

Можем ли мы использовать открытый офис, чтобы открывать каждый лист (вкладку) в одном Excel и конвертировать их в CSV намного быстрее? Если да, как бы я сделал это в рубине?

Или есть еще лучшее решение?

Просто добавив небольшой пример, который я попробовал с Roo Gem

xls = Roo::Excel.new(source_excel_file)
xls.each_with_pagename do |name, sheet|
  # p sheet.to_csv(File.join(dest_csv_dir,name + ".csv"))
  #sheet.parse(:clean => true)#.to_csv(File.join(dest_csv_dir,name + ".csv"))
  puts name
  puts sheet.parse(:clean => true)
end

4 ответа

Трусливое предисловие: я СУПЕР новичок в ruby ​​и почти ничего не знаю о рельсах, но я раньше сталкивался с Excel. Я создал фиктивную книгу на своем локальном компьютере из 5 листов, каждый из которых содержал 10 столбцов и 1000 строк случайно сгенерированных чисел. Я преобразовал каждый лист в свой собственный CSV с этим:

require 'win32ole'
require 'csv'

# configure a workbook, turn off excel alarms
xl = WIN32OLE.new('excel.application')
book = xl.workbooks.open('C:\stack\my_workbook.xlsx')
xl.displayalerts = false

# loop through all worksheets in the excel file
book.worksheets.each do |sheet|
  last_row = sheet.cells.find(what: '*', searchorder: 1, searchdirection: 2).row
  last_col = sheet.cells.find(what: '*', searchorder: 2, searchdirection: 2).column
  export = File.new('C:\\stack\\' + sheet.name + '.csv', 'w+')
  csv_row = []

  # loop through each column in each row and write to CSV
  (1..last_row).each do |xlrow|
    (1..last_col).each do |xlcol|
      csv_row << sheet.cells(xlrow, xlcol).value
    end
    export << CSV.generate_line(csv_row)
    csv_row = []
  end
end

# clean up
book.close(savechanges: 'false')
xl.displayalerts = true
xl.quit

Тест для глазного яблока для этого сценария составлял ~30 секунд, при этом каждая попытка приходилась на несколько секунд выше или ниже.

xls_file = Roo::Excelx.new('test.xlsx')
CSV.open('test.csv') do |csv|
    (2..xls_file.last_row).each do |i| # if you do not need header otherwise (1..xls_file.last_row)
        csv << a.row(i)
    end
end

Я предполагаю, что мы говорим о старом формате Excel (xls), кажется, что гем электронных таблиц не может работать с xlsx в любом случае.

Я бы попробовал один из конвертеров электронных таблиц командной строки: либо xls2csv из пакета catdoc (действительно быстро, хотя не все файлы Excel обрабатываются успешно), либо ssconvert из пакета gnumeric (умеренная скорость и требует установки ent GNUmeric, который иногда не вариант для сервера, но действительно надежный).

NB. При синтаксическом анализе Excel roo просто требует электронную таблицу и упаковывает ее в собственный API, поэтому она никогда не может быть быстрее или надежнее, чем электронная таблица.

NB2: Если я правильно помню (хотя это было несколько лет назад), попытка автоматизировать OpenOffice из ruby ​​была а) очень сложной и б) очень медленной.

Убедитесь, что вы используете последнюю версию Roo (1.13.2).

Также убедитесь, что вы используете патч для пропуска конечных пустых строк:

https://github.com/Empact/roo/blob/master/lib/roo/worksheet.rb

Если вы можете опубликовать одну из ваших электронных таблиц, для анализа которой требуется много времени, это может помочь вам в этом. Только не забудьте удалить любые конфиденциальные данные.

Другие вопросы по тегам