Быстрый парсинг Excel - C#
Формулировка задачи:
Господа, прошу помощи.
Суть: есть (и раз в неделю добавляется) сотня файлов *.xls. Содержимое - 1 лист примерно 500 строк на 60 столбцов.
Нужно: слить все файлы в один xls, минуя 1 строчку. В дальнейшем, с выборкой некоторых столбцов, сейчас нужно слить все столбцы.
Да, я знаю, существуют надстройки в экселе, но, видимо, предстоит довольно большая работа с подключением отчетов в c# проекты.
Сделал забор из всех файлов в DataTable значений ячеек (фактически, сохранил в структуру).
В случае работы ранее с текстовыми отчетами и логами, такой парсинг пролетал за несколько секунд для объема в десяток тысяч строк. А вот сейчас так же попробовал забрать данные из сотни эксель-таблиц и... 2.5 часа парсинга для суммарно 1млн ячеек (30к х35 листов).
Работаю со стандартным модулем Interop.Excel, по принципу - взять файл, создать application, открыть книгу, увидеть фигу открыть лист, определить крайнюю ячеку и считать ячейки в DataTable DT:
Ну и далее просто копирование построчно (со второй строки) данных из ячеек в в DataRow, ничего примечательного:
После чего закрываю эксель книгу и процесс и перехожу к следущему XLS.
Процесс наполнения DT тормозит эту схему чуть меньше чем совсем никак. Проблема именно в поячеечном считывании экселя. Может нужно открывать файлы только для чтения или еще какие то параметры я пропустил?
По идее, при обращении к lastCell.Row, я обращаюсь к уже инициализированному объекту, а не к методу, поэтому это тоже не должно сильно тормозить. Грешу на параметры открытия файла или на саму встроенную функцию обращения к ячейкам. Может есть какой-то простой и незатратный способ забрать что-то типа query в DT? потому что 12часовое слияние 100 500строчных экселей - это бред какой-то. В любой адекватной БД на подобные запросы ушло бы от силы минуты 2, наверно.
И еще пара дополнительных вопросов, если позволите:
Запустить ли парсинг в пуле потоков (List потоков подготовили и по списку сделали .Run), ускорит ли?
процесс поклеточного сохранения данных из DT также слишком долгий. ЧЯДНТ?
var openXls = new Microsoft.Office.Interop.Excel.Application(); var openXlsWb = openXls.Workbooks.Open(somestring_xls, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); Excel.Worksheet openXlsWs = (Excel.Worksheet)openXlsWb.Sheets[1]; var lastCell = openXlsWs.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell); for (int comNum = 0; comNum < lastCell.Column; comNum++) { DT.Columns.Add(comNum.ToString()); } DataRow stringData = DT.NewRow();
for (int i = 1; i < lastCell.Row; i++) { stringData = DT.NewRow(); for (int j = 0; j < lastCell.Column; j++) { stringData[j] = openXlsWs.Cells[i+1, j + 1].Text.ToString(); } DT.Rows.Add(stringData); }
Решение задачи: «Быстрый парсинг Excel»
textual
Листинг программы
static void CopyRange(Range Source, Range Destination) { Destination.Cells[1, 1] .Resize(Source.Rows.Count, Source.Columns.Count) .Value = Source.Value; } static void Main() { var app = new Application(); var inbook = app.Workbooks.Open(@"p:\Книга1.xlsx"); var outbook = app.Workbooks.Add(); // скопирует прямоугольный регион A1:C2 из inbook // в B2:D3 из outbook CopyRange( inbook.Sheets[1].Range["A1", "C2"], outbook.Sheets[1].Range["B2", "B2"]); inbook.Close(); app.Visible = true; }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д