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 == "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);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-22 13:24:14 +04:00
|
|
|
|
}
|
|
|
|
|
}
|