Эффективно конвертировать 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
Если вы можете опубликовать одну из ваших электронных таблиц, для анализа которой требуется много времени, это может помочь вам в этом. Только не забудьте удалить любые конфиденциальные данные.