PIbd-31_Rodionov.I.A._COP_28/COP/RodionovLibrary/NonVisualComponents/WordTableComponent.cs
2024-09-22 23:29:54 +04:00

233 lines
9.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;
using RodionovLibrary.NonVisualComponents.HelperModels;
using System.ComponentModel;
namespace RodionovLibrary.NonVisualComponents
{
public partial class WordTableComponent : Component
{
public WordTableComponent()
{
InitializeComponent();
}
public WordTableComponent(IContainer container)
{
container.Add(this);
InitializeComponent();
}
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 == "MergeCell" ? "" : column.Header))));
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);
}
}
}
}