PIbd-31_Razubaev_S_M_COP-10/WinFormsLibrary/NonVisualComponents/WordTable.cs

188 lines
6.1 KiB
C#
Raw Normal View History

2024-10-04 11:08:55 +04:00
using Word = Microsoft.Office.Interop.Word;
using WinFormsLibrary.NonVisualComponents.Helpers;
using System.ComponentModel;
namespace WinFormsLibrary.NonVisualComponents
{
public partial class WordTable : Component
{
public WordTable()
{
InitializeComponent();
}
public WordTable(IContainer container)
{
container.Add(this);
InitializeComponent();
}
public void CreateTable<T>(WordTableInfo<T> tableInfo)
{
ValidateInputData(tableInfo);
var wordApp = new Word.Application();
var document = wordApp.Documents.Add();
var range = document.Range();
var paragraph = range.Paragraphs.Add();
paragraph.Range.Text = tableInfo.Title;
paragraph.Range.Font.Name = "Times New Roman";
paragraph.Range.Font.Size = 20;
paragraph.Range.Font.Bold = 1;
paragraph.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter;
paragraph.Range.ParagraphFormat.SpaceAfter = 8;
paragraph.Range.InsertParagraphAfter();
var table = document.Tables.Add(paragraph.Range, tableInfo.Items.Count + 2, tableInfo.ColumnInfos.Count);
table.Borders.Enable = 1;
table.Range.Font.Name = "Times New Roman";
table.Range.Font.Size = 11;
for (int i = 0; i < tableInfo.ColumnInfos.Count; i++)
{
table.Columns[i + 1].Width = (float)(tableInfo.ColumnInfos[i].Width * 28);
}
AddTableHeaderRow(table, tableInfo.ColumnInfos, true);
AddTableHeaderRow(table, tableInfo.ColumnInfos, false);
MergeColumns(table, tableInfo.MergedColumns);
AddTableData(table, tableInfo.Items, tableInfo.ColumnInfos);
document.SaveAs2(tableInfo.Path);
wordApp.Quit();
}
private void AddTableHeaderRow(Word.Table table, List<ColumnInfo> columnInfos, bool isFirstRow)
{
for (int i = 0; i < columnInfos.Count; i++)
{
var header = isFirstRow ? columnInfos[i].FirstRowHeader : columnInfos[i].SecondRowHeader;
if (!string.IsNullOrEmpty(header))
{
var cell = table.Cell(isFirstRow ? 1 : 2, i + 1);
cell.Range.Text = header;
cell.Range.Bold = 1;
cell.Range.ParagraphFormat.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter;
cell.VerticalAlignment = Word.WdCellVerticalAlignment.wdCellAlignVerticalCenter;
cell.Range.ParagraphFormat.SpaceBefore = 4;
cell.Range.ParagraphFormat.SpaceAfter = 4;
}
}
}
private void MergeColumns(Word.Table table, List<(int start, int end)> mergedColumns)
{
for (int i = 1; i <= table.Columns.Count; i++)
{
bool isMergedHorizontally = mergedColumns.Any(m => m.start <= i - 1 && m.end >= i - 1);
if (!isMergedHorizontally)
{
table.Cell(1, i).Merge(table.Cell(2, i));
}
}
int xOffset = 0;
foreach (var (start, end) in mergedColumns)
{
var cellStart = table.Cell(1, start + 1 - xOffset);
var cellEnd = table.Cell(1, end + 1 - xOffset);
string textToKeep = cellStart.Range.Text.TrimEnd('\r', '\a');
cellStart.Merge(cellEnd);
cellStart.Range.Text = textToKeep;
xOffset += end - start;
}
}
private void AddTableData<T>(Word.Table table, List<T> items, List<ColumnInfo> columnInfos)
{
for (int rowIndex = 0; rowIndex < items.Count; rowIndex++)
{
var item = items[rowIndex];
for (int colIndex = 0; colIndex < columnInfos.Count; colIndex++)
{
var property = typeof(T).GetProperty(columnInfos[colIndex].PropertyName);
var value = property?.GetValue(item)?.ToString() ?? string.Empty;
table.Cell(rowIndex + 3, colIndex + 1).Range.Text = value;
table.Cell(rowIndex + 3, colIndex + 1).Range.Bold = 0;
table.Cell(rowIndex + 3, colIndex + 1).Range.ParagraphFormat.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter;
table.Cell(rowIndex + 3, colIndex + 1).VerticalAlignment = Word.WdCellVerticalAlignment.wdCellAlignVerticalCenter;
table.Cell(rowIndex + 3, colIndex + 1).Range.ParagraphFormat.SpaceBefore = 2;
table.Cell(rowIndex + 3, colIndex + 1).Range.ParagraphFormat.SpaceAfter = 2;
}
}
}
private void ValidateInputData<T>(WordTableInfo<T> wordTableInfo)
{
if (string.IsNullOrEmpty(wordTableInfo.Path) || (string.IsNullOrEmpty(wordTableInfo.Title)))
{
throw new ArgumentException("Не все данные заполнены");
}
CheckColumnInfo(wordTableInfo.ColumnInfos);
foreach (var column in wordTableInfo.ColumnInfos)
{
if (typeof(T).GetProperty(column.PropertyName) == null)
{
throw new ArgumentException($"Свойство '{column.PropertyName}' не найдено в классе {typeof(T).Name}.");
}
}
ValidateMergedColumns(wordTableInfo.MergedColumns, wordTableInfo.ColumnInfos.Count);
}
public void CheckColumnInfo(List<ColumnInfo> columns)
{
if ((columns == null) || (columns.Count == 0))
{
throw new ArgumentException("Нет информации о колонках");
}
foreach (var column in columns)
{
if (string.IsNullOrEmpty(column.FirstRowHeader) && string.IsNullOrEmpty(column.SecondRowHeader))
{
throw new ArgumentException("Заголовок не задан для одной из колонок в таблице");
}
if (column.Width <= 0)
{
throw new ArgumentException("Ширина колонки должна быть больше нуля.");
}
if (string.IsNullOrEmpty(column.PropertyName))
{
throw new ArgumentException("Свойство не задано для одной из колонок.");
}
}
}
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("Объединенные ячейки пересекаются.");
}
}
}
}
}