반응형
엑셀 파일 불러오기
- 필요한 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, // 엑셀 시트의 헤더를 찾을 수 없음
}
반응형
'C#' 카테고리의 다른 글
C# 윈폼(Windows Forms) 웹(Blazor + Ant Design) 메뉴 예쁘게 만들기 (0) | 2024.02.08 |
---|---|
C# 특정 폴더내에서 xlsx 확장자를 가진 파일 모두 찾기(GetFiles) (0) | 2024.01.09 |
C# 초기화 파일 생성 및 불러오기(json) (0) | 2024.01.08 |
C# 간편한 로그 라이브러리(Serilog) (0) | 2024.01.07 |
C# txt, json 파일 쓰기(File.WriteAllText), 파일 읽기(File.ReadAllText) (0) | 2024.01.07 |