using NPOI.XSSF.UserModel; using OfficeOpenXml.Drawing; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using PutincevLibrary.Info; using NPOI.SS.UserModel; using NPOI.SS.Util; using BorderStyle = NPOI.SS.UserModel.BorderStyle; using HorizontalAlignment = NPOI.SS.UserModel.HorizontalAlignment; namespace PutincevLibrary { public partial class ComponentExcelWithTable : Component { public ComponentExcelWithTable() { InitializeComponent(); } public ComponentExcelWithTable(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("Таблица"); 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.Count > 1) { sheet.AddMergedRegion(new CellRangeAddress(curRow, curRow + header.Value.Item1.Count - 1, curCol, curCol)); curCol++; foreach (var (key, displayName) in header.Value.Item1) { int id = header.Value.Item1.IndexOf((key, displayName)); var cellValue = currentRow.CreateCell(1); cellValue.SetCellValue(displayName); currentRow.Height = (short)(header.Value.Item2[id] * 20); headers.Add(displayName); cellValue.CellStyle = headerCellStyle; currentRow = sheet.CreateRow(currentRow.RowNum + 1); } } else { int id = header.Value.Item1.IndexOf(header.Value.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.Count > 1) { curCol--; curRow += header.Value.Item1.Count; } } curCol = 2; foreach (var data in info.Data) { curRow = 1; foreach (var header in info.Headers.Values) { foreach (var (key, _) in header.Item1) { var property = typeof(T).GetProperty(key); var cellValue = sheet.GetRow(curRow)?.CreateCell(curCol); if (cellValue != null && property != null) { var value = property?.GetValue(data)?.ToString(); var rowHeight = GetRowHeight(key, 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 (key, displayName) in item.Value.Item1) { int id = item.Value.Item1.IndexOf((key, displayName)); if (key == 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 = NPOI.SS.UserModel.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; } } }