메모리 문제 해결을 위해 전역 callvalue[][] 는 제거 하고
SheetDirty 이벤트에서 row 와 변경전 데이터만 가지고 처리
마지막에 비교시 현재 cellvalue 값을 가지고 비교하여 처리
row 값만 가지고 나중에 데이터를 가져와서 처리 하는게 좋음
아래 코드 이용해서 처리
int rowIndex = 1;
var rowValues = new List<CellValue>();
for (int col = 0; col < sheet.NumCols; col++)
{
rowValues.Add(sheet.Cells.GetCellValue(rowIndex, col));
}
rowValues.ToArray();
SheetDirty확인
private async Task OnDynamicBinding()
{
sheet.SheetDirty -= Sheet_Sheetdirty;
sheet.Commands.PauseHistory(); // 히스토리 저장 중지
sheet.BatchUpdates(); // 배치 업데이트 시작
try
{
// 1. 동적 쿼리 실행
var products = await DbConnection.QueryAsync("SELECT * FROM Products");
var productsList = products.ToList();
if (!productsList.Any()) return; // 데이터가 없으면 중지
// 2. 첫 번째 행에서 컬럼 이름 추출
var firstRow = (IDictionary<string, object>)productsList.First();
var columnNames = firstRow.Keys.ToList();
// 3. 시트 크기 설정 (행 개수, 컬럼 개수)
sheet = new Sheet(productsList.Count, columnNames.Count);
// 4. 컬럼 헤더 설정
sheet.Columns.HeadingHeight = 30;
for (int i = 0; i < columnNames.Count; i++)
{
sheet.Columns.SetHeadings(i, i, columnNames[i]);
}
// 5. 데이터 변환 및 시트에 적용
var dataValues = productsList
.Select(row => ((IDictionary<string, object>)row)
.Values
.Select(value => ConvertToCellValue(value)) // 데이터 변환
.ToArray())
.ToArray();
// 6. 셀에 데이터 설정
sheet.Cells.SetValues(0, 0, dataValues);
// 7. Select (Combo) 설정
// 콤보에 사용될 데이터
var names = new SourceValidator(new List<string> { "Laptop", "Keyboard", "Mouse"}, false);
// 첫 번째 컬럼의 모든 셀을 "select" 타입으로 변경
sheet.Cells.SetType(new ColumnRegion(1), "select");
// 해당 컬럼에 SourceValidator 추가
sheet.Validators.Add(new ColumnRegion(1), names);
// cell 설정
var numberList = Enumerable.Range(1, 50).Select(n => n).ToList();
var quantitys = new NumberSourceValidator(numberList, false);
sheet.Cells[0, 3].Type = "select"; // sheet.Cells.SetType(0,0, "select");
sheet.Validators.Add(0, 3, quantitys);
}
finally
{
// 7. 업데이트 종료 및 UI 갱신
sheet.EndBatchUpdates();
sheet.Commands.ResumeHistory();
sheet.ScreenUpdating = true;
sheet.SheetDirty += Sheet_Sheetdirty;
}
}
편집이 끝났을때 이벤트 확인 필요