178 lines
6.2 KiB
C#
178 lines
6.2 KiB
C#
|
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<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("Таблица");
|
|||
|
|
|||
|
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.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<T>(string header, ExcelTableInfo<T> 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; }
|
|||
|
}
|
|||
|
}
|