programing

최적의 Excel 파일 읽기 방법(.xls/.xlsx)

newstyles 2023. 4. 24. 22:58

최적의 Excel 파일 읽기 방법(.xls/.xlsx)

Excel 파일을 읽는 방법에는 여러 가지가 있습니다.

  • Iterop
  • Oledb
  • Open Xml SDK

프로그램은 제어된 환경에서 실행되므로 호환성은 문제가 되지 않습니다.

요건:
파일 읽기DataTable/CUstom Entities(객체에 동적 속성/필드를 만드는 방법을 모릅니다[열 이름은 Excel 파일에서 변합니다]).

사용하다DataTable/Custom Entities데이터를 사용하여 일부 작업을 수행합니다.

갱신하다DataTable수술 결과와 함께

회신처excel file.

어느 쪽이 더 쉬울까요?

또한 가능하면 커스텀엔티티에 대한 조언(프로퍼티/필드를 오브젝트에 동적으로 추가)

Linq-to-Excel을 보세요.꽤 깔끔하네요.

var book = new LinqToExcel.ExcelQueryFactory(@"File.xlsx");

var query =
    from row in book.Worksheet("Stock Entry")
    let item = new
    {
        Code = row["Code"].Cast<string>(),
        Supplier = row["Supplier"].Cast<string>(),
        Ref = row["Ref"].Cast<string>(),
    }
    where item.Supplier == "Walmart"
    select item;

또한 강력한 유형의 행 액세스도 허용합니다.

이 질문은 7년 가까이 전에 했던 질문이지만, 여전히 C#에서의 엑셀 데이터 Import에 관한 특정 키워드의 구글 검색 결과 상위이기 때문에, 최근의 기술 발전을 바탕으로 대안을 제시하고자 합니다.

Excel 데이터의 Import는 일상 업무에 있어서 매우 일반적인 작업이 되어, 프로세스를 합리화하고, 그 방법을 블로그에 기록하고 있습니다.c#에서 Excel 파일을 읽는 가장 좋은 방법입니다.

Microsoft Office를 설치하지 않아도 Excel 파일을 읽고 쓸 수 있고 COM+나 인터옵션을 사용하지 않기 때문에 NPOI를 사용합니다.그것은 클라우드에서도 작동할 수 있다는 것을 의미합니다!

그러나 진정한 마법은 Donny Tian의 NPOI Mapper와 짝을 이루는 것입니다. 왜냐하면 코드를 작성하지 않고도 Excel 열을 C# 클래스의 속성에 매핑할 수 있기 때문입니다.아름답군요.

기본적인 생각은 다음과 같습니다.

관심 있는 Excel 열에 일치하거나 매핑하는 .net 클래스를 만듭니다.

        class CustomExcelFormat
        {
            [Column("District")]
            public int District { get; set; }

            [Column("DM")]
            public string FullName { get; set; }

            [Column("Email Address")]
            public string EmailAddress { get; set; }

            [Column("Username")]
            public string Username { get; set; }

            public string FirstName
            {
                get
                {
                    return Username.Split('.')[0];
                }
            }

            public string LastName
            {
                get
                {
                    return Username.Split('.')[1];
                }
            }
        }

원하는 경우 열 이름을 기준으로 매핑할 수 있습니다.

그리고 엑셀 파일을 처리할 때 필요한 것은 다음과 같습니다.

        public void Execute(string localPath, int sheetIndex)
        {
            IWorkbook workbook;
            using (FileStream file = new FileStream(localPath, FileMode.Open, FileAccess.Read))
            {
                workbook = WorkbookFactory.Create(file);
            }

            var importer = new Mapper(workbook);
            var items = importer.Take<CustomExcelFormat>(sheetIndex);
            foreach(var item in items)
            {
                var row = item.Value;
                if (string.IsNullOrEmpty(row.EmailAddress))
                    continue;

                UpdateUser(row);
            }

            DataContext.SaveChanges();
        }

물론, 제 코드는 엑셀 파일 자체를 수정하지 않습니다.대신 Entity Framework를 사용하여 데이터를 데이터베이스에 저장합니다(이 때문에 예에서는 "UpdateUser" 및 "SaveChanges"가 표시됩니다).그러나 NPOI를 사용하여 파일을 저장/수정하는 방법에 대해서는 SO에 대한 논의가 이미 진행 중입니다.

OLE 쿼리를 사용하면 매우 간단합니다(예: sheetName은 Sheet1).

DataTable LoadWorksheetInDataTable(string fileName, string sheetName)
{           
    DataTable sheetData = new DataTable();
    using (OleDbConnection conn = this.returnConnection(fileName))
    {
       conn.Open();
       // retrieve the data using data adapter
       OleDbDataAdapter sheetAdapter = new OleDbDataAdapter("select * from [" + sheetName + "$]", conn);
       sheetAdapter.Fill(sheetData);
       conn.Close();
    }                        
    return sheetData;
}

private OleDbConnection returnConnection(string fileName)
{
    return new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fileName + "; Jet OLEDB:Engine Type=5;Extended Properties=\"Excel 8.0;\"");
}

새로운 Excel 버전의 경우:

return new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties=Excel 12.0;");

또한 CodePlex에서 Excel Data Reader 오픈 소스 프로젝트를 사용할 수도 있습니다.Excel 시트에서 데이터를 내보내는 것이 매우 효과적입니다.

지정된 링크에 지정된 샘플코드:

FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read);

//1. Reading from a binary Excel file ('97-2003 format; *.xls)
IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);
//...
//2. Reading from a OpenXml Excel file (2007 format; *.xlsx)
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
//...
//3. DataSet - The result of each spreadsheet will be created in the result.Tables
DataSet result = excelReader.AsDataSet();
//...
//4. DataSet - Create column names from first row
excelReader.IsFirstRowAsColumnNames = true;
DataSet result = excelReader.AsDataSet();

//5. Data Reader methods
while (excelReader.Read())
{
//excelReader.GetInt32(0);
}

//6. Free resources (IExcelDataReader is IDisposable)
excelReader.Close();

레퍼런스:Microsoft를 사용하여 Excel에서 DataSet으로 Import하는 방법Office.Interop.엑셀?

https://freenetexcel.codeplex.com 에서 무료로 이용하실 수 있습니다.

 Workbook workbook = new Workbook();

 workbook.LoadFromFile(@"..\..\parts.xls",ExcelVersion.Version97to2003);
 //Initialize worksheet
 Worksheet sheet = workbook.Worksheets[0];

 DataTable dataTable = sheet.ExportDataTable();

(Open Office XML 형식) *.xlsx 파일로만 제한할 수 있다면 가장 일반적인 라이브러리는 EPPLus가 될 것입니다.

보너스는 다른 의존관계가 없다는 것입니다.nuget을 사용하여 설치하기만 하면 됩니다.

Install-Package EPPlus

Aspose.cells 라이브러리를 사용해 보십시오(무료는 아니지만 평가판만 읽어도 충분합니다). 매우 좋습니다.

Install-package Aspose.cells

샘플 코드는 다음과 같습니다.

using Aspose.Cells;
using System;

namespace ExcelReader
{
    class Program
    {
        static void Main(string[] args)
        {
            // Replace path for your file
            readXLS(@"C:\MyExcelFile.xls"); // or "*.xlsx"
            Console.ReadKey();
        }

        public static void readXLS(string PathToMyExcel)
        {
            //Open your template file.
            Workbook wb = new Workbook(PathToMyExcel);

            //Get the first worksheet.
            Worksheet worksheet = wb.Worksheets[0];

            //Get cells
            Cells cells = worksheet.Cells;

            // Get row and column count
            int rowCount = cells.MaxDataRow;
            int columnCount = cells.MaxDataColumn;

            // Current cell value
            string strCell = "";

            Console.WriteLine(String.Format("rowCount={0}, columnCount={1}", rowCount, columnCount));

            for (int row = 0; row <= rowCount; row++) // Numeration starts from 0 to MaxDataRow
            {
                for (int column = 0; column <= columnCount; column++)  // Numeration starts from 0 to MaxDataColumn
                {
                    strCell = "";
                    strCell = Convert.ToString(cells[row, column].Value);
                    if (String.IsNullOrEmpty(strCell))
                    {
                        continue;
                    }
                    else
                    {
                        // Do your staff here
                        Console.WriteLine(strCell);
                    }
                }
            }
        }
    }
}

Excel에서 읽기, 수정 및 쓰기

 /// <summary>
/// /Reads an excel file and converts it into dataset with each sheet as each table of the dataset
/// </summary>
/// <param name="filename"></param>
/// <param name="headers">If set to true the first row will be considered as headers</param>
/// <returns></returns>
public DataSet Import(string filename, bool headers = true)
{
    var _xl = new Excel.Application();
    var wb = _xl.Workbooks.Open(filename);
    var sheets = wb.Sheets;
    DataSet dataSet = null;
    if (sheets != null && sheets.Count != 0)
    {
        dataSet = new DataSet();
        foreach (var item in sheets)
        {
            var sheet = (Excel.Worksheet)item;
            DataTable dt = null;
            if (sheet != null)
            {
                dt = new DataTable();
                var ColumnCount = ((Excel.Range)sheet.UsedRange.Rows[1, Type.Missing]).Columns.Count;
                var rowCount = ((Excel.Range)sheet.UsedRange.Columns[1, Type.Missing]).Rows.Count;

                for (int j = 0; j < ColumnCount; j++)
                {
                    var cell = (Excel.Range)sheet.Cells[1, j + 1];
                    var column = new DataColumn(headers ? cell.Value : string.Empty);
                    dt.Columns.Add(column);
                }

                for (int i = 0; i < rowCount; i++)
                {
                    var r = dt.NewRow();
                    for (int j = 0; j < ColumnCount; j++)
                    {
                        var cell = (Excel.Range)sheet.Cells[i + 1 + (headers ? 1 : 0), j + 1];
                        r[j] = cell.Value;
                    }
                    dt.Rows.Add(r);
                }

            }
            dataSet.Tables.Add(dt);
        }
    }
    _xl.Quit();
    return dataSet;
}



 public string Export(DataTable dt, bool headers = false)
    {
        var wb = _xl.Workbooks.Add();
        var sheet = (Excel.Worksheet)wb.ActiveSheet;
        //process columns
        for (int i = 0; i < dt.Columns.Count; i++)
        {
            var col = dt.Columns[i];
            //added columns to the top of sheet
            var currentCell = (Excel.Range)sheet.Cells[1, i + 1];
            currentCell.Value = col.ToString();
            currentCell.Font.Bold = true;
            //process rows
            for (int j = 0; j < dt.Rows.Count; j++)
            {
                var row = dt.Rows[j];
                //added rows to sheet
                var cell = (Excel.Range)sheet.Cells[j + 1 + 1, i + 1];
                cell.Value = row[i];
            }
            currentCell.EntireColumn.AutoFit();
        }
        var fileName="{somepath/somefile.xlsx}";
        wb.SaveCopyAs(fileName);
        _xl.Quit();
        return fileName;
    }

Office의 NuGet 패키지를 사용했습니다.Document Format.OpenXml을 사용하여 해당 컴포넌트의 문서 사이트에서 코드를 결합합니다.

아래 도우미 코드에서는 그 프로젝트의 다른 CSV 파일 형식 구문 분석과 복잡성이 비슷했습니다.

public static async Task ImportXLSX(Stream stream, string sheetName) {
{
    // This was necessary for my Blazor project, which used a BrowserFileStream object
    MemoryStream ms = new MemoryStream();
    await stream.CopyToAsync(ms);

    using (var document = SpreadsheetDocument.Open(ms, false))
    {
        // Retrieve a reference to the workbook part.
        WorkbookPart wbPart = document.WorkbookPart;

        // Find the sheet with the supplied name, and then use that 
        // Sheet object to retrieve a reference to the first worksheet.
        Sheet theSheet = wbPart?.Workbook.Descendants<Sheet>().Where(s => s?.Name == sheetName).FirstOrDefault();

        // Throw an exception if there is no sheet.
        if (theSheet == null)
        {
            throw new ArgumentException("sheetName");
        }

        WorksheetPart wsPart = (WorksheetPart)(wbPart.GetPartById(theSheet.Id));
        // For shared strings, look up the value in the
        // shared strings table.
        var stringTable = 
            wbPart.GetPartsOfType<SharedStringTablePart>()
            .FirstOrDefault();

        // I needed to grab 4 cells from each row
        // Starting at row 11, until the cell in column A is blank
        int row = 11;

        while (true) {
                var accountNameCell = GetCell(wsPart, "A" + row.ToString());
                var accountName = GetValue(accountNameCell, stringTable);
                if (string.IsNullOrEmpty(accountName)) {
                    break;
                }
                var investmentNameCell = GetCell(wsPart, "B" + row.ToString());
                var investmentName = GetValue(investmentNameCell, stringTable);
                var symbolCell = GetCell(wsPart, "D" + row.ToString());
                var symbol = GetValue(symbolCell, stringTable);
                var marketValue = GetCell(wsPart, "J" + row.ToString()).InnerText;
                
                // DO STUFF with data

                row++;
        }
    }
}

private static string? GetValue(Cell cell, SharedStringTablePart stringTable) {
    try {
        return stringTable.SharedStringTable.ElementAt(int.Parse(cell.InnerText)).InnerText;
    } catch (Exception) {
        return null;
    }
}
private static Cell GetCell(WorksheetPart wsPart, string cellReference) {
    return wsPart.Worksheet.Descendants<Cell>().Where(c => c.CellReference.Value == cellReference)?.FirstOrDefault();
}

언급URL : https://stackoverflow.com/questions/12996234/optimal-way-to-read-an-excel-file-xls-xlsx