본문 바로가기

C#

C# 엑셀 파일 불러오기(xls, xlsx)

반응형

엑셀 파일 불러오기

  • 필요한 NuGet 패키지
    • NPOI
    • Serilog.AspNetCore(Log.Information, Log.Error 호출시 사용 Console.WriteLine으로 대체 가능)
  • Exception 날 때가 있음 보톤 엑셀이 열려 있어서 그런 것이니 열린 엑셀 파일 종료 후 실행
using NPOI.SS.UserModel; // Excel 파일을 다루는 주요 인터페이스와 클래스
using NPOI.XSSF.UserModel; // .xlsx 형식
using NPOI.HSSF.UserModel; // .xls 형식
using Serilog; // Log 사용 안하면 Console.WriteLine 대체 가능

public static class ExcelHelper
{
    public static (ErrorCode, List<Dictionary<string, object>>) ExcelFileRead(string filePath)
    {
        ErrorCode error = ErrorCode.Ok;
        List<Dictionary<string, object>> ack = new List<Dictionary<string, object>>();

        // 파일 존재 여부 확인
        if (!File.Exists(filePath))
        {
            error = ErrorCode.FileExistsNot;
            Log.Error($"ExcelFileRead, File.Exists, filePath: {filePath}, error: {error}");
            return (error, ack);
        }

        // Excel 파일 데이터를 저장할 리스트
        var workbookData = new List<Dictionary<string, object>>();

        // Excel 파일 열기
        using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            // 워크북 인스턴스 생성
            IWorkbook workbook;
            if (filePath.EndsWith(".xls"))
            {
                workbook = new HSSFWorkbook(file);
            }
            else if (filePath.EndsWith(".xlsx"))
            {
                workbook = new XSSFWorkbook(file);
            }
            else
            {
                error = ErrorCode.ExcelNot;
                Log.Error($"ExcelFileRead, workbook == null, filePath: {filePath}, error: {error}");
                return (error, ack);
            }

            // 워크북에 시트가 없는 경우
            if (workbook.NumberOfSheets == 0)
            {
                error = ErrorCode.ExcelSheetNot;
                Log.Error($"ExcelFileRead, workbook.NumberOfSheets == 0, filePath: {filePath}, error: {error}");
                return (error, ack);
            }

            // 모든 시트 반복 처리
            for (int sheetIndex = 0; sheetIndex < workbook.NumberOfSheets; sheetIndex++)
            {
                ISheet sheet = workbook.GetSheetAt(sheetIndex);

                // 각 시트의 데이터를 저장할 딕셔너리
                var sheetData = new Dictionary<string, object>();

                // 행 데이터를 저장할 리스트
                var rowData = new List<Dictionary<string, object>>();

                // 첫 번째 행(헤더) 읽기
                IRow headerRow = sheet.GetRow(0);
                if (headerRow == null)
                {
                    error = ErrorCode.ExcelSheetHeaderNot;
                    Log.Error($"ExcelFileRead, headerRow == null, filePath: {filePath}, error: {error}");
                    return (error, ack);
                }

                int cellCount = headerRow.LastCellNum;

                // 데이터 행 읽기
                for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++)
                {
                    IRow row = sheet.GetRow(i);
                    if (row == null) 
                        continue;

                    // 각 셀의 데이터를 저장할 딕셔너리
                    var cellData = new Dictionary<string, object>();

                    for (int j = row.FirstCellNum; j < cellCount; j++)
                    {
                        // 셀이 null이 아닌 경우에만 처리
                        if (row.GetCell(j) != null)
                            cellData[headerRow.GetCell(j).ToString()] = row.GetCell(j).ToString();
                    }

                    rowData.Add(cellData);
                }

                // 시트 이름으로 시트 데이터 저장
                sheetData[sheet.SheetName] = rowData;
                workbookData.Add(sheetData);
            }
        }

        ack = workbookData;

        LogExcelFileRead(ack);

        return (error, ack);
    }

    public static void LogExcelFileRead(List<Dictionary<string, object>> workbookData)
    {
        foreach (var workbookDatas in workbookData)
        {
            foreach (var sheetData in workbookDatas)
            {
                Log.Information("Sheet: " + sheetData.Key);

                var rows = sheetData.Value as List<Dictionary<string, object>>;
                if (rows != null)
                {
                    foreach (var row in rows)
                    {
                        foreach (var cell in row)
                        {
                            Log.Information(cell.Key + ": " + cell.Value);
                        }
                        Log.Information("------------");
                    }
                }
            }
        }
    }
}

 

public enum ErrorCode
{ 
    Ok = 0,
    IsNullOrEmpty = 1, // 비었음
    FileExistsNot = 2, // 파일을 찾을 수 없음
    ExcelNot = 3, // 엑셀 형식을 찾을 수 없음
    ExcelSheetNot = 4, // 엑셀의 시트를 찾을 수 없음
    ExcelSheetHeaderNot = 5, // 엑셀 시트의 헤더를 찾을 수 없음
}

 

데이터

 

불러온 결과

반응형