KOP_Library_v5/ViewComponents/NotVisualComponents/PdfTable.cs

171 lines
5.4 KiB
C#
Raw Normal View History

using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.Rendering;
using PdfSharp.Pdf.Content.Objects;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ViewComponents.NotVisualComponents
{
public partial class PdfTable : Component
{
public PdfTable()
{
InitializeComponent();
}
public PdfTable(IContainer container)
{
container.Add(this);
InitializeComponent();
}
public bool createTable<T>(string filepath, string header, List<(int, int)> merges, List<int> heights, List<(bool, string)> headers, List<T> items)
{
//проверки
if (merges.Count == 0 || heights.Count == 0 || headers.Count == 0 || items.Count == 0) throw new ArgumentException("Недостаточно данных");
int[] cellsArray = new int[heights.Count];
foreach (var merge in merges)
{
if (merge.Item1 >= merge.Item2) throw new ArgumentException("Неправильно заполнены объединения строк");
for (int i = merge.Item1; i < merge.Item2; i++)
{
cellsArray[i]++;
}
}
foreach (int cell in cellsArray)
{
if (cell > 1) throw new ArgumentException("Объединения заходят друг на друга");
}
//создание документа
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Document _document = new Document();
var style = _document.Styles["Normal"];
style = _document.Styles.AddStyle("NormalTitle", "Normal");
style.Font.Name = "Arial";
style.Font.Size = 25;
style.Font.Bold = true;
style = _document.Styles.AddStyle("Table", "Normal");
style.Font.Name = "Times New Roman";
style.Font.Size = 12;
//добавление заголовка
var section = _document.AddSection();
var paragraph = section.AddParagraph(header);
paragraph.Format.Alignment = ParagraphAlignment.Center;
paragraph.Format.SpaceAfter = "2cm";
paragraph.Style = "NormalTitle";
//добавление таблицы
Table table = section.AddTable();
table.Style = "Table";
table.Borders.Width = 0.25;
Column column;
for (int i = 0; i < items.Count + 2; i++)
{
column = table.AddColumn();
column.Format.Alignment = ParagraphAlignment.Center;
}
// создание шапки и заполнение контентом
int mergeRange = 0; //размерность слияния
int mergeIndex = 0; //стартовый индекс начала слияния
Row row;
for (int i = 0; i < headers.Count; i++)
{
//если элемент шапки не группируется по строкам
if (headers[i].Item1 == false)
{
//стилизация ячейки
row = table.AddRow();
row.Height = heights[i];
row.Format.Font.Bold = true;
row.Format.Alignment = ParagraphAlignment.Center;
row.Cells[0].AddParagraph(headers[i].Item2);
row.Cells[0].VerticalAlignment = VerticalAlignment.Center;
row.Cells[0].MergeRight = 1;
AddTheContent<T>(items, table, row.Index, 2);
mergeIndex++;
}
//если элемент шапки группируются по строкам
if (headers[i].Item1 == true)
{
mergeRange = merges.Find(x => x.Item1 == mergeIndex).Item2 - mergeIndex;
mergeIndex = merges.Find(x => x.Item1 == mergeIndex).Item2 + 1;
//стилизация ячейки. в этом блоке кода (до цикла) создаётся объединяющая ячейка
row = table.AddRow();
row.Height = heights[i];
row.Format.Alignment = ParagraphAlignment.Center;
row.Format.Font.Bold = true;
row.Cells[0].AddParagraph(headers[i].Item2);
row.Cells[0].VerticalAlignment = VerticalAlignment.Center;
row.Cells[0].MergeDown = mergeRange;
//с этого места создаются дочерние ячейки
for (int k = 0; k<mergeRange; k++)
{
i++;
row.Cells[1].AddParagraph(headers[i].Item2);
AddTheContent<T>(items, table, row.Index, 2);
row.Cells[1].VerticalAlignment = VerticalAlignment.Center;
row = table.AddRow();
row.Height = heights[i];
row.Format.Font.Bold = true;
row.Format.Alignment = ParagraphAlignment.Center;
}
i++;
row.Cells[1].AddParagraph(headers[i].Item2);
AddTheContent<T>(items, table, row.Index, 2);
row.Cells[1].VerticalAlignment = VerticalAlignment.Center;
}
}
PdfDocumentRenderer renderer = new PdfDocumentRenderer(true);
renderer.Document = _document;
renderer.RenderDocument();
renderer.PdfDocument.Save(filepath);
return true;
}
//метод заполнения таблицы контентом, заполнение происходит построчно.
public void AddTheContent<T>(List<T> items, Table table, int row_index, int cell_index)
{
foreach (Row r in table.Rows)
{
for (int i = 0; i<items.Count; i++)
{
if (r.Index == row_index && row_index == 0) r.Cells[cell_index+i].AddParagraph((i+1).ToString());
else if(row_index!=0 && r.Index == row_index)
{
T item = items[i];
var type = typeof(T);
var fields = type.GetFields();
r.Cells[cell_index + i].AddParagraph(fields[row_index-1].GetValue(item).ToString());
r.Cells[cell_index + i].VerticalAlignment = VerticalAlignment.Center;
}
}
}
}
}
}