using System; using System.Collections.Generic; using System.ComponentModel; using System.Reflection; using System.Runtime.InteropServices; using Excel = Microsoft.Office.Interop.Excel; namespace Components { public partial class ComponentExcelTableWithColumnHeader : Component { public ComponentExcelTableWithColumnHeader() { InitializeComponent(); } public ComponentExcelTableWithColumnHeader(IContainer container) : this() { container.Add(this); } public void GenerateExcelFile( string filePath, string documentTitle, List<(int StartRow, int EndRow, int StartCol, int EndCol, string title)> mergeCellsInfo, List tableData, List<(string title, string propertyName, float height)> headersConfig) { if (string.IsNullOrEmpty(filePath) || headersConfig == null) { throw new ArgumentException("Все входные данные должны быть заполнены."); } Excel.Application excelApp = new Excel.Application(); excelApp.Visible = false; Excel.Workbook workbook = excelApp.Workbooks.Add(); Excel.Worksheet worksheet = (Excel.Worksheet)workbook.Sheets[1]; worksheet.Cells[1, 1].Value = documentTitle; worksheet.Range[worksheet.Cells[1, 1], worksheet.Cells[1, tableData.Count + 2]].Merge(); worksheet.Cells[1, 1].HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter; for (int i = 0; i < headersConfig.Count; i++) { worksheet.Cells[2 + i, 2].Value = headersConfig[i].title; worksheet.Cells[2 + i, 2].Font.Bold = true; worksheet.Rows[i + 1].RowHeight = headersConfig[i].height; } for (int colIndex = 0; colIndex < tableData.Count; colIndex++) { var data = tableData[colIndex]; for (int rowIndex = 0; rowIndex < headersConfig.Count; rowIndex++) { var property = data.GetType().GetProperty(headersConfig[rowIndex].propertyName); if (property != null) { worksheet.Cells[rowIndex + 2, colIndex + 3].Value = property.GetValue(data); } } } List rows = new List(); foreach (var mergeInfo in mergeCellsInfo) { ValidateMergeCells(mergeCellsInfo); worksheet.Range[worksheet.Cells[mergeInfo.StartRow + 1, mergeInfo.StartCol], worksheet.Cells[mergeInfo.EndRow + 1, mergeInfo.EndCol]].Merge(); worksheet.Cells[mergeInfo.StartRow + 1, mergeInfo.StartCol].Value = mergeInfo.title; for (int r = mergeInfo.StartRow + 1; r <= mergeInfo.EndRow + 1; r++) { rows.Add(r); } } for (int i = 2; i < headersConfig.Count + 2; i++) { if (!rows.Contains(i)) { worksheet.Range[worksheet.Cells[i, 1], worksheet.Cells[i, 2]].Merge(); } } workbook.SaveAs(filePath); workbook.Close(); Marshal.ReleaseComObject(workbook); excelApp.Quit(); Marshal.ReleaseComObject(excelApp); } private void ValidateMergeCells(List<(int StartRow, int EndRow, int StartCol, int EndCol, string title)> mergeCellsInfo) { for (int i = 0; i < mergeCellsInfo.Count; i++) { for (int j = i + 1; j < mergeCellsInfo.Count; j++) { if (CellsOverlap(mergeCellsInfo[i], mergeCellsInfo[j])) { throw new InvalidOperationException("Объединенные ячейки пересекаются."); } } } } private bool CellsOverlap( (int StartRow, int EndRow, int StartCol, int EndCol, string title) range1, (int StartRow, int EndRow, int StartCol, int EndCol, string title) range2) { bool rowsOverlap = range1.StartRow <= range2.EndRow && range1.EndRow >= range2.StartRow; bool colsOverlap = range1.StartCol <= range2.EndCol && range1.EndCol >= range2.StartCol; return rowsOverlap && colsOverlap; } } }