Распарсить таблицу excel через C#

223
30 декабря 2021, 00:20

У меня есть файл, из которого необходимо заполнить базу данных. Структура файла сложная(например, значение ячейки С6 зависит от Company name1, Type1, Section1). Как его распарсить чтобы заполнить бд данными? Для работы с excel я использую npoi.

Answer 1

получаем лист и файл и передаем функции по обработке эксель

private void SelectTableFromExcel(int year)
    {
        var openFile = OpenFile();
        var excelWorksheets = GetExcelWorksheet(openFile);
        TableFromExcel(excelWorksheets, "номер последней колонки");
    }

выбираем и открываем файл

private OpenFileDialog OpenFile()
    {
        var openFile = new OpenFileDialog
        {
            Title = @"Выберите файл",
            Filter = @"Файлы Excel|*.xls;*.xlsx",
            FilterIndex = 1,
            RestoreDirectory = true
        };
        return openFile.ShowDialog() != true ? null : openFile;
    }

получаем первый лист из выбранного файла

private ExcelWorksheet GetExcelWorksheet(OpenFileDialog openFile)
    {
        var package = new ExcelPackage(new FileInfo(openFile.FileName));
        var excelWorksheets = package.Workbook.Worksheets[1];
        return excelWorksheets;
    }

основная функция для работы с эксель

private void TableFromExcel(ExcelWorksheet excelWorksheet, string numberCol)
    {
        var rangeExcel = GetRangeExcel(excelWorksheet);
        var lastColRange = GetLastColumnExcel(excelWorksheet, numberCol);
        var nullsRowFromExcel = GetNullRowFromExcel(excelWorksheet, rangeExcel);
        LoadDataFromExcel(excelWorksheet, rangeExcel, nullsRowFromExcel, lastColRange);
    }

получаем ячейку, откуда начинают идти данные

private ExcelCellAddress GetRangeExcel(ExcelWorksheet excelWorksheets)
    {
        return excelWorksheets.Cells[1, 1, excelWorksheets.Dimension.Rows, excelWorksheets.Dimension.Columns]
            .First(c => c.Value != null && c.Value?.ToString().Length != 0 && c.Value.ToString().Contains("Company name1"))
            ?.Start;
    }

получаем ячейку по последнему столбцу

private ExcelCellAddress GetLastColumnExcel(ExcelWorksheet excelWorksheet, string numberColumn)
    {
        return excelWorksheet.Cells[1, 1, excelWorksheet.Dimension.Rows, excelWorksheet.Dimension.Columns]
            .First(c => c.Value != null && c.Value?.ToString().Length != 0 && c.Value.ToString().Contains(numberColumn))
            ?.Start;
    }

получаем нулевые строки, чтобы дальше их пропускать

private List<int> GetNullRowFromExcel(ExcelWorksheet excelWorksheet, ExcelCellAddress rangeExcel)
    {
        var nullRowFromExcel = new List<int>();
        for (var i = rangeExcel.Row; i <= excelWorksheet.Dimension.Rows; i++)
            if (excelWorksheet.Cells[i, rangeExcel.Column - 1].Value == null)
                nullRowFromExcel.Add(i);
        return nullRowFromExcel;
    }

считываем данные из эксель

private void LoadDataFromExcel(ExcelWorksheet excelWorksheet, ExcelCellAddress rangeExcel, List<int> nullsRowFromExcel, ExcelCellAddress lastColRange)
    {
        var rowWithAllCollumn = new List<string>();
        for (var i = rangeExcel.Row; i <= excelWorksheet.Dimension.Rows; i++)
        {
            rowWithAllCollumn.Clear();
            for (var j = rangeExcel.Column - 2; j <= lastColRange.Column; j++)
            {
                if (j == rangeExcel.Column - 1 || j > rangeExcel.Column)
                {
                    rowWithAllCollumn.Add(excelWorksheet.Cells[i, j].Value == null ? "0" : excelWorksheet.Cells[i, j].Value.ToString());
                }
                else
                {
                    rowWithAllCollumn.Add(null);
                }
            }
            if (nullsRowFromExcel.Contains(i)) continue;
             //_plansEntities это dataContext в entity framework, LoadPlanMZTemps моя таблица,куда надо грузить данные
            _plansEntities.LoadPlanMZTemps.Add(ChangesListToModel(rowWithAllCollumn, lastColRange.Column));
            _plansEntities.SaveChanges();
        }
    }

тут уже вставляем в таблицу данные

private LoadPlanMZTemp ChangesListToModel(List<string> rowWithAllCollumn, int lastColumn)
    {
//моя модель из ef
        var objPlan = new LoadPlanMZTemp();
        var descr = TypeDescriptor.GetProperties(objPlan);
        var index = 0;
        foreach (PropertyDescriptor property in descr)
        {
            if (index < lastColumn)
            {
                switch (property.Name)
                {
                    case "id":
                        continue;
                    default:
                        property.SetValue(objPlan, System.Convert.ToDecimal(rowWithAllCollumn[index]));
                        break;
                }
                index++;
            }
            else break;
        }
        return objPlan;
    }
Answer 2

Я для работы с Excel использую EpPlus, но я уверен, что принцип работы один и тот же.

Как я понимаю, формат вам заранее известен => идете как по двумерному массиву и постепенно заполняете DataTable:

  1. Прочитали заголовок и создали соответствующее кол-во колонок с названиями
  2. Далее итеративно спускаетесь вниз и генерите DataRow'ы
  3. В конце просто пуляете этот DataTable в БД и все.
READ ALSO
Что означает интструкция ret(il код)

Что означает интструкция ret(il код)

Имеется такая строчка в методе на il: "IL_0007: ret"Что это значит ? (Понятно, что это связано с окончанием метода, но как конкретно)

230
обработка всех строк в DataGridView

обработка всех строк в DataGridView

Пытаюсь по нажатию кнопки обработать все строки в гридеВ моем случае есть грид с сообщениями

240
Не срабатывает таймер

Не срабатывает таймер

Имеется сервис, который собирает данные и отправляет в другой сервисСервис работает в докер-контейнере

180