PIbd-31_Rodionov.I.A._COP_28/COP/RodionovLibrary/NonVisualComponents/WordTableComponent.cs

233 lines
9.9 KiB
C#
Raw Normal View History

2024-09-22 23:29:54 +04:00
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;
using RodionovLibrary.NonVisualComponents.HelperModels;
using System.ComponentModel;
2024-09-22 13:24:14 +04:00
namespace RodionovLibrary.NonVisualComponents
{
public partial class WordTableComponent : Component
{
public WordTableComponent()
{
InitializeComponent();
}
public WordTableComponent(IContainer container)
{
container.Add(this);
InitializeComponent();
}
2024-09-22 23:29:54 +04:00
public void CreateTable<T>(WordTableInfo<T> tableInfo)
{
ValidateInputData(tableInfo);
using (WordprocessingDocument wordDoc = WordprocessingDocument.Create(tableInfo.FileName, WordprocessingDocumentType.Document))
{
MainDocumentPart mainPart = wordDoc.AddMainDocumentPart();
mainPart.Document = new Document();
Body body = mainPart.Document.AppendChild(new Body());
ParagraphProperties paragraphProperties = new();
paragraphProperties.AppendChild(new Justification { Val = JustificationValues.Center });
Paragraph titleParagraph = new();
titleParagraph.AppendChild(paragraphProperties);
Run docRun = new();
RunProperties runProperties = new();
runProperties.AppendChild(new FontSize { Val = "48" });
runProperties.AppendChild(new Bold());
docRun.AppendChild(runProperties);
docRun.AppendChild(new Text(tableInfo.Title));
titleParagraph.AppendChild(docRun);
body.Append(titleParagraph);
Table table = new();
double totalWidthTwips = tableInfo.FirstRowColumnParameters.Sum(column => column.Width) * 566.93;
TableProperties tableProperties = new(
new TableBorders(
new TopBorder { Val = BorderValues.Single, Size = 8 },
new BottomBorder { Val = BorderValues.Single, Size = 8 },
new LeftBorder { Val = BorderValues.Single, Size = 8 },
new RightBorder { Val = BorderValues.Single, Size = 8 },
new InsideHorizontalBorder { Val = BorderValues.Single, Size = 8 },
new InsideVerticalBorder { Val = BorderValues.Single, Size = 8 }
),
new TableWidth { Width = totalWidthTwips.ToString("F0"), Type = TableWidthUnitValues.Dxa },
new TableJustification { Val = TableRowAlignmentValues.Center }
);
table.AppendChild(tableProperties);
AddTableHeaderRow(table, tableInfo.FirstRowColumnParameters);
AddTableHeaderRow(table, tableInfo.SecondRowColumnParameters);
MergeColumns(table, tableInfo.MergedColumns);
AddTableData(table, tableInfo.Items, tableInfo.SecondRowColumnParameters);
body.Append(table);
mainPart.Document.Save();
}
}
private void ValidateInputData<T>(WordTableInfo<T> tableInfo)
{
if (string.IsNullOrEmpty(tableInfo.FileName) || string.IsNullOrEmpty(tableInfo.Title))
{
throw new ArgumentException("Не все данные заполнены");
}
CheckColumnParameters(tableInfo.FirstRowColumnParameters, false);
CheckColumnParameters(tableInfo.SecondRowColumnParameters, true);
if (tableInfo.Items == null || tableInfo.Items.Count == 0)
{
throw new ArgumentException("Данные для основной части таблицы не заданы");
}
foreach (var column in tableInfo.SecondRowColumnParameters)
{
if (typeof(T).GetProperty(column.PropertyName) == null)
{
throw new ArgumentException($"Свойство '{column.PropertyName}' не найдено в классе {typeof(T).Name}.");
}
}
ValidateMergedColumns(tableInfo.MergedColumns, tableInfo.FirstRowColumnParameters.Count);
}
private void CheckColumnParameters(List<ColumnParameters> columnParameters, bool isSecondRow)
{
if (columnParameters == null || columnParameters.Count == 0)
{
throw new ArgumentException("Не заданы колонки для таблицы");
}
foreach (var column in columnParameters)
{
if (string.IsNullOrEmpty(column.Header))
{
throw new ArgumentException("Заголовок не задан для одной из колонок в таблице");
}
if (column.Width <= 0)
{
throw new ArgumentException($"У колонки с заголовком {column.Header} ширина должна быть больше нуля.");
}
if (isSecondRow && string.IsNullOrEmpty(column.PropertyName))
{
throw new ArgumentException($"Свойство не задано для заголовка: {column.Header}.");
}
}
}
private void ValidateMergedColumns(List<(int start, int end)> mergedColumns, int totalColumns)
{
if (mergedColumns == null || mergedColumns.Count == 0)
{
return;
}
foreach (var (start, end) in mergedColumns)
{
if (start < 0 || end >= totalColumns)
{
throw new ArgumentException("Индексы объединенных колонок выходят за пределы допустимых значений.");
}
var overlappingRanges = mergedColumns
.Where(m => m != (start, end))
.Any(m => m.start <= end && m.end >= start);
if (overlappingRanges)
{
throw new ArgumentException("Объединенные ячейки пересекаются.");
}
}
}
private void AddTableHeaderRow(Table table, List<ColumnParameters> columnParameters)
{
TableRow headerRow = new();
foreach (var column in columnParameters)
{
TableCell cell = new(new Paragraph(new Run(new Text(column.Header))));
2024-09-22 23:29:54 +04:00
TableCellProperties cellProps = new()
{
TableCellWidth = new TableCellWidth { Type = TableWidthUnitValues.Dxa, Width = (column.Width * 566.93).ToString("F0") },
TableCellVerticalAlignment = new TableCellVerticalAlignment { Val = TableVerticalAlignmentValues.Center }
};
ParagraphProperties paragraphProperties = new(new Justification { Val = JustificationValues.Center });
RunProperties runProperties = new() { Bold = new Bold() };
cell.Append(cellProps);
cell.Append(paragraphProperties);
cell.Elements<Paragraph>().First().Elements<Run>().First().RunProperties = runProperties;
headerRow.Append(cell);
}
table.Append(headerRow);
}
private void MergeColumns(Table table, List<(int start, int end)> mergedColumns)
{
foreach (var (startCellIndex, endCellIndex) in mergedColumns)
{
for (int i = startCellIndex; i <= endCellIndex; i++)
{
TableCell cell = table.Elements<TableRow>().ElementAt(0).Elements<TableCell>().ElementAt(i);
cell.TableCellProperties.Append(new HorizontalMerge { Val = i == startCellIndex ? MergedCellValues.Restart : MergedCellValues.Continue });
}
}
int totalColumns = table.Elements<TableRow>().ElementAt(0).Elements<TableCell>().Count();
for (int i = 0; i < totalColumns; i++)
{
bool isColumnMergedHorizontally = mergedColumns.Any(m => m.start <= i && m.end >= i);
if (!isColumnMergedHorizontally)
{
TableCell firstRowCell = table.Elements<TableRow>().ElementAt(0).Elements<TableCell>().ElementAt(i);
TableCell secondRowCell = table.Elements<TableRow>().ElementAt(1).Elements<TableCell>().ElementAt(i);
firstRowCell.TableCellProperties.Append(new VerticalMerge { Val = MergedCellValues.Restart });
secondRowCell.TableCellProperties.Append(new VerticalMerge { Val = MergedCellValues.Continue });
}
}
}
private void AddTableData<T>(Table table, List<T> items, List<ColumnParameters> columnParameters)
{
foreach (var item in items)
{
TableRow dataRow = new();
foreach (var column in columnParameters)
{
TableCell cell = new(new Paragraph(new Run(new Text(item?.GetType().GetProperty(column.PropertyName)?.GetValue(item)?.ToString() ?? string.Empty))));
TableCellProperties cellProps = new()
{
TableCellVerticalAlignment = new TableCellVerticalAlignment { Val = TableVerticalAlignmentValues.Center }
};
ParagraphProperties paragraphProperties = new(new Justification { Val = JustificationValues.Center });
cell.Append(cellProps);
cell.Append(paragraphProperties);
dataRow.Append(cell);
}
table.Append(dataRow);
}
}
2024-09-22 13:24:14 +04:00
}
}