using COP.Info; using DocumentFormat.OpenXml.EMMA; using DocumentFormat.OpenXml.Office2010.Excel; using DocumentFormat.OpenXml.Spreadsheet; using NPOI.HSSF.Util; using NPOI.SS.UserModel; using NPOI.SS.Util; using NPOI.XSSF.UserModel; using System; using System.ComponentModel; using BorderStyle = NPOI.SS.UserModel.BorderStyle; using HorizontalAlignment = NPOI.SS.UserModel.HorizontalAlignment; namespace COP { public partial class ExcelTable : Component { public ExcelTable() { InitializeComponent(); } public ExcelTable(IContainer container) { container.Add(this); InitializeComponent(); } public void GenerateDocument(ExcelTableInfo info) where T: class { if (string.IsNullOrEmpty(info.FilePath)) { throw new ArgumentException("File path is null or empty."); } if (string.IsNullOrEmpty(info.DocumentTitle)) { throw new ArgumentException("Document title is null or empty."); } if (info.Data == null || info.Data.Count == 0) { throw new ArgumentException("Data is null or empty."); } var workbook = new XSSFWorkbook(); var sheet = workbook.CreateSheet("Sheet1"); sheet.CreateRow(0).CreateCell(0).SetCellValue(info.DocumentTitle); int curRow = 1; int curCol = 0; List headers = new(); var dataCellStyle = GetDataCellStyle(workbook); var headerCellStyle = GetHeaderCellStyle(workbook); foreach (var header in info.Headers) { headers.Add(header.Key); var currentRow = sheet.CreateRow(curRow); var curCell = currentRow.CreateCell(curCol); if (header.Value.Item1.Item1.Count > 1) { sheet.AddMergedRegion(new CellRangeAddress(curRow, curRow + header.Value.Item1.Item1.Count - 1, curCol, curCol)); curCol++; foreach (var item in header.Value.Item1.Item2) { int id = header.Value.Item1.Item2.IndexOf(item); var cellValue = currentRow.CreateCell(1); cellValue.SetCellValue(item); currentRow.Height = (short)(header.Value.Item2[id] * 20); headers.Add(item); cellValue.CellStyle = headerCellStyle; currentRow = sheet.CreateRow(currentRow.RowNum + 1); } } else { int id = header.Value.Item1.Item1.IndexOf(header.Value.Item1.Item1[0]); sheet.AddMergedRegion(new CellRangeAddress(curRow, curRow, curCol, curCol + 1)); currentRow.Height = (short)(header.Value.Item2[id] * 20); curRow++; } curCell.SetCellValue(header.Key); curCell.CellStyle = headerCellStyle; if (header.Value.Item1.Item1.Count > 1) { curCol--; curRow += header.Value.Item1.Item1.Count; } } curCol = 2; foreach (var data in info.Data) { curRow = 1; foreach (var header in info.Headers.Values) { foreach (var item in header.Item1.Item1) { var property = typeof(T).GetProperty(item); var cellValue = sheet.GetRow(curRow)?.CreateCell(curCol); if (cellValue != null && property != null) { var value = property?.GetValue(data)?.ToString(); var rowHeight = GetRowHeight(item, info); var currentRow = sheet.GetRow(curRow); if (rowHeight != null) { currentRow.Height = (short)(rowHeight.Value * 20); } cellValue.SetCellValue(value); cellValue.CellStyle = dataCellStyle; } curRow++; } } curCol++; } using var fs = new FileStream(info.FilePath, FileMode.Create, FileAccess.Write); workbook.Write(fs); } private static int? GetRowHeight(string header, ExcelTableInfo info) where T:class { foreach (var item in info.Headers) { foreach (var elem in item.Value.Item1.Item1) { int id = item.Value.Item1.Item1.IndexOf(elem); if (item.Value.Item1.Item1[id] == header) return item.Value.Item2[id]; } } return 0; } private static ICellStyle GetHeaderCellStyle(IWorkbook workbook) { var style = workbook.CreateCellStyle(); style.BorderBottom = BorderStyle.Thin; style.BorderLeft = BorderStyle.Thin; style.BorderRight = BorderStyle.Thin; style.BorderTop = BorderStyle.Thin; var font = workbook.CreateFont(); font.Boldweight = (short)FontBoldWeight.Bold; style.SetFont(font); style.Alignment = HorizontalAlignment.Center; style.VerticalAlignment = VerticalAlignment.Center; return style; } private static ICellStyle GetDataCellStyle(IWorkbook workbook) { var style = workbook.CreateCellStyle(); style.BorderBottom = BorderStyle.Thin; style.BorderLeft = BorderStyle.Thin; style.BorderRight = BorderStyle.Thin; style.BorderTop = BorderStyle.Thin; return style; } } public class Property { public string? Name { get; set; } } }