Быстрый парсинг Excel - C#

Узнай цену своей работы

Формулировка задачи:

Господа, прошу помощи. Суть: есть (и раз в неделю добавляется) сотня файлов *.xls. Содержимое - 1 лист примерно 500 строк на 60 столбцов. Нужно: слить все файлы в один xls, минуя 1 строчку. В дальнейшем, с выборкой некоторых столбцов, сейчас нужно слить все столбцы. Да, я знаю, существуют надстройки в экселе, но, видимо, предстоит довольно большая работа с подключением отчетов в c# проекты. Сделал забор из всех файлов в DataTable значений ячеек (фактически, сохранил в структуру). В случае работы ранее с текстовыми отчетами и логами, такой парсинг пролетал за несколько секунд для объема в десяток тысяч строк. А вот сейчас так же попробовал забрать данные из сотни эксель-таблиц и... 2.5 часа парсинга для суммарно 1млн ячеек (30к х35 листов). Работаю со стандартным модулем Interop.Excel, по принципу - взять файл, создать application, открыть книгу, увидеть фигу открыть лист, определить крайнюю ячеку и считать ячейки в DataTable 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();
Ну и далее просто копирование построчно (со второй строки) данных из ячеек в в DataRow, ничего примечательного:
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);
                }
После чего закрываю эксель книгу и процесс и перехожу к следущему XLS. Процесс наполнения DT тормозит эту схему чуть меньше чем совсем никак. Проблема именно в поячеечном считывании экселя. Может нужно открывать файлы только для чтения или еще какие то параметры я пропустил? По идее, при обращении к lastCell.Row, я обращаюсь к уже инициализированному объекту, а не к методу, поэтому это тоже не должно сильно тормозить. Грешу на параметры открытия файла или на саму встроенную функцию обращения к ячейкам. Может есть какой-то простой и незатратный способ забрать что-то типа query в DT? потому что 12часовое слияние 100 500строчных экселей - это бред какой-то. В любой адекватной БД на подобные запросы ушло бы от силы минуты 2, наверно. И еще пара дополнительных вопросов, если позволите: Запустить ли парсинг в пуле потоков (List потоков подготовили и по списку сделали .Run), ускорит ли? процесс поклеточного сохранения данных из DT также слишком долгий. ЧЯДНТ?

Решение задачи: «Быстрый парсинг 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;
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

10   голосов , оценка 4 из 5