PIbd-32_Artamonova_T.V._COP_2/COP/ExcelTable.cs

176 lines
6.2 KiB
C#

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<T>(ExcelTableInfo<T> 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<string> 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<T>(string header, ExcelTableInfo<T> 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; }
}
}