Windows Form (C #) - экспортировать большой файл Excel в таблицу данных - PullRequest
0 голосов
/ 21 мая 2018

У меня проблема с загруженным большим файлом Excel в datatable.Я пробовал много сторонних программ, таких как NPOI и Epplus, но не могу решить мою проблему.После многих поисков я обнаружил, что для загрузки части файла используется Stream.Но эта статья просто говорит о концепции, и я понятия не имею, как читать часть файла одновременно, объединять части файла и собирать их.

Я знаю, что для выполнения этой задачи существует множество сторонних программ.Но я действительно хочу знать самый простой способ.Может кто-нибудь дать мне несколько примеров?

Ответы [ 3 ]

0 голосов
/ 21 мая 2018
  1. Установите последнюю версию NPOI из менеджера пакетов NUGET .
  2. Используйте метод ниже, чтобы прочитать поток Excel в таблицу.это хорошо проверенный и рабочий код.Передайте поток Excel, имя таблицы и количество листов для чтения
  public void ReadFromExcel(Stream excelFileStream, DataTable dt, int sheetsToRead, out string processingError)                    
        {

               XSSFWorkbook workbook = new XSSFWorkbook(excelFileStream); // write data in workbook from xls document.               
                    XSSFSheet sheet = (XSSFSheet)workbook.GetSheetAt(0); // read the current table data                
                    XSSFRow headerRow = (XSSFRow)sheet.GetRow(0); // read the current row data
                    // LastCellNum is the number of cells of current rows
                    int cellCount = headerRow.LastCellNum;
                    bool isBlanKRow = false;
                    processingError = "";
                    try
                    {
                        if (dt.Rows.Count == 0)
                        {
                           //Reading First Row as Header for Excel Sheet;
                            try
                            {
                                for (int j = headerRow.FirstCellNum; j < cellCount; j++)
                                {
                                    // get data as the column header of DataTable
                                    DataColumn column = new DataColumn(headerRow.GetCell(j).StringCellValue);
                                    dt.Columns.Add(column);
                                }
                            }
                            catch (Exception Ex)
                            {
                                logger.Error("Error", Ex);
                                processingError = Ex.Message;
                                throw;
                            }
                        }

                       // Number of Sheets to Read  
                        for (int sheetindex = 0; sheetindex < sheetsToRead; sheetindex++)
                        {
                            sheet = (XSSFSheet)workbook.GetSheetAt(sheetindex);
                            if (null != sheet)
                            {

                                // LastRowNum to get the number of rows of current table
                                int rowCount = sheet.LastRowNum + 1;
                                // Reading Rows and Copying it to Data Table;
                                try
                                {
                                    for (int i = (sheet.FirstRowNum + 1); i < rowCount; i++)
                                    {
                                        XSSFRow row = (XSSFRow)sheet.GetRow(i);
                                        DataRow dataRow = dt.NewRow();
                                        isBlanKRow = true;
                                        try
                                        {
                                            for (int j = row.FirstCellNum; j < cellCount; j++)
                                            {
                                                if (null != row.GetCell(j) && !string.IsNullOrEmpty(row.GetCell(j).ToString()) && !string.IsNullOrWhiteSpace(row.GetCell(j).ToString()))
                                                {
                                                    dataRow[j] = row.GetCell(j).ToString();
                                                    isBlanKRow = false;
                                                }
                                            }
                                        }
                                        catch (Exception Ex)
                                        {                                    
                                            processingError = Ex.Message;
                                            throw;
                                        }
                                        if (!isBlanKRow)
                                        {
                                            dt.Rows.Add(dataRow);
                                        }
                                    }
                                }
                                catch (Exception Ex)
                                {                           
                                    processingError = Ex.Message;
                                    throw;
                                }
                            }
                        }
                    }
                    catch (Exception Ex)
                    {               
                        processingError = Ex.Message;
                        throw;
                    }
                    finally
                    {
                        workbook.UnlockStructure();
                        workbook.UnlockRevision();
                        workbook.UnlockWindows();
                        workbook = null;
                        sheet = null;
                    }
                }
0 голосов
/ 20 декабря 2018

У меня есть способ решить проблему нехватки памяти.Мой код может решить 100K-200K строк или 25MB файл Excel.

      SpreadsheetDocument doc = SpreadsheetDocument.Open(fullFilePath, false) //read file
        WorkbookPart x = doc.WorkbookPart;
        OpenXmlReader reader = OpenXmlReader.Create(workbookPart.WorksheetParts.First());
        int totalRow = 0;
        while (reader.Read())//read excel file every tag
        {
            if (reader.ElementType == typeof(Row))//start to deal with data when meet row tag
            {
                if (totalRow == 0)//i want to skip header row
                {
                    totalRow++;
                    reader.ReadFirstChild();//start reading the child element of row tag
                    do
                    {
                        if (reader.ElementType == typeof(Cell))//start to deal with the data in cell
                        {


                         Cell cell = (Cell)reader.LoadCurrentElement();//load into the element
                         //you can get data if you need header info
                            }
                        } while (reader.ReadNextSibling());//read another sibling cell tag. it will stop until the last sibling cell.
                    }
                    else
                {

                    reader.ReadFirstChild();
                    do
                    {
                        if (reader.ElementType == typeof(Cell))
                        {
                           Cell cell = (Cell)reader.LoadCurrentElement();
                           var container = GetValue(x, cell);// because not every data will directly store in cell tag. I have to deal with some situation in the GetValue function.
                        }
                    }while (reader.ReadNextSibling());
                }
            }
        }
        private string GetValue(WorkbookPart workbookPart, Cell cell)
        {
            var cellValue = cell.CellValue;

            string value = (cellValue == null) ? cell.InnerText : cellValue.InnerText;//get info in cell tag
            if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)//when info store in sharedstringtable you have to get info in there
            {
                return workbookPart.SharedStringTablePart.SharedStringTable.ChildElements.GetItem(int.Parse(value)).InnerText;
            }
            return value;
        }

Форма Excel в формате XML, как показано ниже.Вы можете просмотреть XML-форму Excel, тогда вы узнаете, как работать с большим Excel больше.

xml form

Ссылка: Образец (чтениеочень большой файл Excel) SAX подход

0 голосов
/ 21 мая 2018

Если у вас есть документ large excel, то вам лучше использовать Open XML SDK, а для файлов меньшего размера, я думаю, EPPLUS лучше подходит.

ДляEPPLUS

Вы можете использовать следующий код:

public DataTable GetDataTableFromExcel(string path)
{    
     var tbl = new DataTable();
     using (var pck = new OfficeOpenXml.ExcelPackage())
    {
   //reading the excel file using the stream
    using (var stream = File.OpenRead(path))
    {
      pck.Load(stream);
    }

    //Reading the data from the 1st sheet, you can add the code to read other sheets
    var ws = pck.Workbook.Worksheets.First();        
    //now adding the columns to the table and assuming the first row of the sheet is contaning columns if not change the we.Cells property
    foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column])
    {
       tbl.Columns.Add(firstRowCell.Text);
    }
                   //adding data to datatable
    for (int rowNum = 1; rowNum < ws.Dimension.End.Row; rowNum++)
    {
       var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column];
       DataRow row = tbl.Rows.Add();
       foreach (var cell in wsRow)
       {
          cell.Calculate();
          row[cell.Start.Column - 1] = cell.Value;
        }
    }
        return tbl;
}

Для OPEN XML SDK

вы можете использоватьследующий код:

public DataTable GetDataTableFromExcel(string path)
    {
        var dataTable = new DataTable();
        using (SpreadsheetDocument doc = SpreadsheetDocument.Open(path, false))
        {
            //to read data from the 1st sheet
            Worksheet worksheet = SpreedsheetHelper.GetWorksheetPart(doc.WorkbookPart, "myFirstSheetname").Worksheet;
            SheetData sheetData = worksheet.GetFirstChild<SheetData>();
            IEnumerable<Row> rows = sheetData.Descendants<Row>();
            var cells = SpreedsheetHelper.GetRowCells(rows.ElementAt(0));
            //creating the columns
            foreach (Cell cell in cells)
            {
                var colname = SpreedsheetHelper.TryGetCellValue(doc, cell);
                colname = colname == null ? "" : colname;
                dataTable.Columns.Add(colname, SpreedsheetHelper.GetCellDatatype(cell));
            }               

           //adding data to datatable         
            foreach (Row row in rows)
            {
                DataRow dataRow = dataTable.NewRow();
                var rowcells = SpreedsheetHelper.GetRowCells(row);
                var cellindex = 0;
                foreach (Cell cell in rowcells)
                {
                    var value = SpreedsheetHelper.TryGetCellValue(doc, cell);
                    value = value == null ? "" : value;
                    dataRow[cellindex] = value;
                    cellindex++;
                }                    
                dataTable.Rows.Add(dataRow);
            }

        }
        //to handle the blank row added at the top of datatable
        dataTable.Rows.RemoveAt(0);

        return dataTable;
    }

Надеюсь, это поможет.

...