diff --git a/Cop.Borovkov.Var3/Cop.Borovkov.Var3.sln b/Cop.Borovkov.Var3/Cop.Borovkov.Var3.sln
index 585063b..12f71ea 100644
--- a/Cop.Borovkov.Var3/Cop.Borovkov.Var3.sln
+++ b/Cop.Borovkov.Var3/Cop.Borovkov.Var3.sln
@@ -5,7 +5,9 @@ VisualStudioVersion = 17.10.35122.118
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cop.Borovkov.Var3", "Cop.Borovkov.Var3\Cop.Borovkov.Var3.csproj", "{A8604186-0CDE-4504-805B-46104141269A}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestCustomComponents", "TestCustomComponents\TestCustomComponents.csproj", "{E2C46D08-ACCE-4547-922B-E92AD76D99C8}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestCustomComponents", "TestCustomComponents\TestCustomComponents.csproj", "{E2C46D08-ACCE-4547-922B-E92AD76D99C8}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PIHelperSh.PdfCreator", "PIHelperSh.PdfCreater\PIHelperSh.PdfCreator.csproj", "{572BD835-A500-43C9-A66F-648540F4A1C8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +23,10 @@ Global
{E2C46D08-ACCE-4547-922B-E92AD76D99C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E2C46D08-ACCE-4547-922B-E92AD76D99C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E2C46D08-ACCE-4547-922B-E92AD76D99C8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {572BD835-A500-43C9-A66F-648540F4A1C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {572BD835-A500-43C9-A66F-648540F4A1C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {572BD835-A500-43C9-A66F-648540F4A1C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {572BD835-A500-43C9-A66F-648540F4A1C8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Components/CustomPdfTable.Designer.cs b/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Components/CustomPdfTable.Designer.cs
new file mode 100644
index 0000000..497ec19
--- /dev/null
+++ b/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Components/CustomPdfTable.Designer.cs
@@ -0,0 +1,36 @@
+namespace Cop.Borovkov.Var3.Components
+{
+ partial class CustomPdfTable
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Освободить все используемые ресурсы.
+ ///
+ /// истинно, если управляемый ресурс должен быть удален; иначе ложно.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Код, автоматически созданный конструктором компонентов
+
+ ///
+ /// Требуемый метод для поддержки конструктора — не изменяйте
+ /// содержимое этого метода с помощью редактора кода.
+ ///
+ private void InitializeComponent()
+ {
+ components = new System.ComponentModel.Container();
+ }
+
+ #endregion
+ }
+}
diff --git a/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Components/CustomPdfTable.cs b/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Components/CustomPdfTable.cs
new file mode 100644
index 0000000..0af6728
--- /dev/null
+++ b/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Components/CustomPdfTable.cs
@@ -0,0 +1,92 @@
+using Cop.Borovkov.Var3.Models;
+using PIHelperSh.PdfCreator;
+using PIHelperSh.PdfCreator.Enums;
+using PIHelperSh.PdfCreator.Interfaces;
+using PIHelperSh.PdfCreator.Models.TableModels;
+using System.ComponentModel;
+
+namespace Cop.Borovkov.Var3.Components
+{
+ ///
+ /// Компонент для сохранения таблицы в пдф
+ ///
+ public partial class CustomPdfTable : Component
+ {
+ ///
+ ///
+ public CustomPdfTable()
+ {
+ InitializeComponent();
+ }
+
+ ///
+ ///
+ ///
+ public CustomPdfTable(IContainer container)
+ {
+ container.Add(this);
+ InitializeComponent();
+ }
+
+ ///
+ /// Сохранить набор таблиц в пдф
+ ///
+ ///
+ ///
+ ///
+ public void SaveToPdf(PdfTableInfo tableInfo)
+ {
+ if (!tableInfo.Tables.Any())
+ {
+ return;
+ }
+
+ PdfCreator creator = new PdfCreator();
+
+ creator.AddParagraph(new()
+ {
+ Style = PdfStyleType.Title,
+ Text = tableInfo.Title,
+ MarginAfter = PdfMargin.Smal,
+ });
+
+ foreach (string[,] table in tableInfo.Tables)
+ {
+ List rows = new();
+
+ for (int i = 0; i < table.GetLength(0); ++i)
+ {
+ PDFSimpleTableRow row = new();
+
+ for (int j = 0; j < table.GetLength(1); ++j)
+ {
+ row.Items.Add(table[i, j]);
+ }
+
+ rows.Add(row);
+ }
+
+ creator.AddSimpleTable(new()
+ {
+ Header = rows.First().Items.Select(item => new PdfTableColumn()
+ {
+ Title = item,
+ Size = 3,
+ } as IPdfColumnItem).ToList(),
+ Rows = rows.Skip(1).ToList(),
+
+ HeaderStyle = PdfStyleType.Basic,
+ HeaderHorizontalAlignment = PdfAlignmentType.Left,
+ RowHorizontalAlignment = PdfAlignmentType.Left,
+ });
+
+ creator.AddParagraph(new()
+ {
+ MarginAfter = PdfMargin.Smal,
+ });
+ }
+
+ creator.SavePdf(tableInfo.FilePath);
+ }
+ }
+}
diff --git a/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Cop.Borovkov.Var3.csproj b/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Cop.Borovkov.Var3.csproj
index 3e210aa..a56206d 100644
--- a/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Cop.Borovkov.Var3.csproj
+++ b/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Cop.Borovkov.Var3.csproj
@@ -7,4 +7,8 @@
enable
+
+
+
+
diff --git a/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Models/PdfTableInfo.cs b/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Models/PdfTableInfo.cs
new file mode 100644
index 0000000..fa93c5a
--- /dev/null
+++ b/Cop.Borovkov.Var3/Cop.Borovkov.Var3/Models/PdfTableInfo.cs
@@ -0,0 +1,23 @@
+namespace Cop.Borovkov.Var3.Models
+{
+ ///
+ /// Параметры для создания таблиц в пдф
+ ///
+ public record PdfTableInfo
+ {
+ ///
+ /// имя файла (включая путь до файла)
+ ///
+ public string FilePath { get; init; } = @"C:\pdfTable.pdf";
+
+ ///
+ /// название документа(заголовок в документе)
+ ///
+ public string Title { get; init; } = "Таблица";
+
+ ///
+ /// Список таблиц
+ ///
+ public IEnumerable Tables { get; init; } = [];
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Enums/PdfAlignmentType.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Enums/PdfAlignmentType.cs
new file mode 100644
index 0000000..62bc7f7
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Enums/PdfAlignmentType.cs
@@ -0,0 +1,32 @@
+using MigraDoc.DocumentObjectModel;
+using PIHelperSh.Core.Attributes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PIHelperSh.PdfCreator.Enums
+{
+ ///
+ /// Тип выравнивания элементов
+ ///
+ public enum PdfAlignmentType
+ {
+ ///
+ /// По центру
+ ///
+ [TypeValue(ParagraphAlignment.Center)]
+ Center,
+ ///
+ /// По левому краю
+ ///
+ [TypeValue(ParagraphAlignment.Left)]
+ Left,
+ ///
+ /// По правому краю
+ ///
+ [TypeValue(ParagraphAlignment.Right)]
+ Rigth
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Enums/PdfLegendPosition.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Enums/PdfLegendPosition.cs
new file mode 100644
index 0000000..1923ccb
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Enums/PdfLegendPosition.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PIHelperSh.PdfCreator.Enums
+{
+ ///
+ /// Варианты расположения легенды
+ ///
+ public enum PdfLegendPosition
+ {
+ ///
+ /// Снизу(по умолчанию)
+ ///
+ Bottom,
+ ///
+ /// Справа
+ ///
+ Right,
+ ///
+ /// Слева
+ ///
+ Left,
+ ///
+ /// Сверху
+ ///
+ Top
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Enums/PdfMargin.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Enums/PdfMargin.cs
new file mode 100644
index 0000000..6553cec
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Enums/PdfMargin.cs
@@ -0,0 +1,36 @@
+using PIHelperSh.Core.Attributes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PIHelperSh.PdfCreator.Enums
+{
+ ///
+ /// Типы отступов после элементов (вертикальный)
+ ///
+ public enum PdfMargin
+ {
+ ///
+ /// Отступа нет
+ ///
+ [TypeValue("ocm")]
+ None,
+ ///
+ /// Отступ небольшой
+ ///
+ [TypeValue("0.3cm")]
+ Smal,
+ ///
+ /// Отступ средний
+ ///
+ [TypeValue("1cm")]
+ Medium,
+ ///
+ /// Отступ большой
+ ///
+ [TypeValue("1.6cm")]
+ Big
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Enums/PdfStyleType.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Enums/PdfStyleType.cs
new file mode 100644
index 0000000..57b4a5c
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Enums/PdfStyleType.cs
@@ -0,0 +1,54 @@
+using PIHelperSh.Core.Attributes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PIHelperSh.PdfCreator.Enums
+{
+ ///
+ /// Типы стилей в документе
+ ///
+ public enum PdfStyleType
+ {
+ ///
+ /// Основная часть документа
+ ///
+ [TypeValue("Normal")]
+ Basic,
+ ///
+ /// Название документа
+ ///
+ [TypeValue("NormalTitle")]
+ Title,
+ ///
+ /// Уровень в списке 1
+ ///
+ [TypeValue("BulletList")]
+ [TypeValue(1)]
+ ListLevel1,
+ ///
+ /// Уровень в списке 2
+ ///
+ [TypeValue("BulletList2")]
+ [TypeValue(2)]
+ ListLevel2,
+ ///
+ /// Уровень в списке 3
+ ///
+ [TypeValue("BulletList3")]
+ [TypeValue(3)]
+ ListLevel3,
+ ///
+ /// Жирный шрифт
+ ///
+ [TypeValue("NormalBold")]
+ Bold,
+ ///
+ /// Мелкий шрифт
+ ///
+ [TypeValue("NormalSmall")]
+ Small
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Interfaces/IPdfColumnItem.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Interfaces/IPdfColumnItem.cs
new file mode 100644
index 0000000..ba6ba55
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Interfaces/IPdfColumnItem.cs
@@ -0,0 +1,15 @@
+namespace PIHelperSh.PdfCreator.Interfaces
+{
+ ///
+ ///
+ public interface IPdfColumnItem
+ {
+ ///
+ ///
+ public float? Size { get; }
+
+ ///
+ ///
+ public string? Title { get; set; }
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Interfaces/IPdfCreator.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Interfaces/IPdfCreator.cs
new file mode 100644
index 0000000..a2d87b5
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Interfaces/IPdfCreator.cs
@@ -0,0 +1,64 @@
+using PIHelperSh.PdfCreator.Models.ImageModels;
+using PIHelperSh.PdfCreator.Models.PieChartModel;
+using PIHelperSh.PdfCreator.Models.TableModels;
+using PIHelperSh.PdfCreator.Models.TextModels;
+
+namespace PIHelperSh.PdfCreator.Interfaces
+{
+ ///
+ /// Создатель pdf документа
+ ///
+ public interface IPdfCreator
+ {
+ ///
+ /// Создаём параграф
+ ///
+ /// Модель параграфа, который вставляем
+ public void AddParagraph(PdfParagraph paragraph);
+
+ ///
+ /// Создаём маркированный список
+ ///
+ /// Модель списка(может быть многоуровневым). Max - 3 уровня
+ public void AddList(PdfList List);
+
+ ///
+ /// Создаёт таблицу, с шапкой из 2-х строк(с группировками)
+ ///
+ /// Тип DTO, из которой берутся данные в таблицу
+ /// Модель самой таблицы
+ ///
+ public void AddTable(PdfTable header, bool rowHeaded = false);
+
+ ///
+ /// Создаёт табличку, наподобие той, что с T, но проще
+ ///
+ ///
+ public void AddSimpleTable(PDFSimpleTable tableData);
+
+ ///
+ /// Создаёт круговую диаграмму.
+ ///
+ /// Модель для круговой диаграммы
+ public void AddChart(PdfPieChartModel pieChart);
+
+ ///
+ /// Добавляем на лист изображение. Можно по пути, можно по потоку, можно по Base64 строке
+ ///
+ /// Модель одного изображения
+ public void AddImage(PdfImage image);
+
+ ///
+ /// Метод сохранения созданного PDF документа
+ ///
+ /// Поток MemoryStream с документом
+ public MemoryStream SavePdf();
+
+ ///
+ /// Метод сохранения созданного PDF документа в файл
+ ///
+ /// Имя файла и путь до него. Проверки на расширение нет
+ public void SavePdf(string filename);
+
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Interfaces/IPdfElement.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Interfaces/IPdfElement.cs
new file mode 100644
index 0000000..3d6fb42
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Interfaces/IPdfElement.cs
@@ -0,0 +1,20 @@
+using PIHelperSh.PdfCreator.Enums;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PIHelperSh.PdfCreator.Interfaces
+{
+ ///
+ /// Аналогично word этот интерфейс нужен для работы списков.
+ ///
+ public interface IPdfElement
+ {
+ ///
+ /// //Отступ после(может быть и у списков и у параграфов)
+ ///
+ PdfMargin MarginAfter { get; }
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/ImageModels/MiraDocImage.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/ImageModels/MiraDocImage.cs
new file mode 100644
index 0000000..6aaa5ac
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/ImageModels/MiraDocImage.cs
@@ -0,0 +1,75 @@
+namespace PIHelperSh.PdfCreator.Models.ImageModels
+{
+ ///
+ /// Удобный метод для хранения изображений (для создания Pdf документа можно использовать либо путь до фото, либо поток с данными о нём)
+ ///
+ public class MiraDocImage
+ {
+ ///
+ /// Путь до фото
+ ///
+ public string? Path { get; set; } = null;
+
+ ///
+ /// Поток фото
+ ///
+ public Stream? Source
+ {
+ get => _source;
+ set
+ {
+ _source = value;
+ _b64Source = null;
+ }
+ }
+
+ private Stream? _source;
+
+ private string? _b64Source = null;
+
+ ///
+ /// Создание изображения из пути
+ ///
+ /// Путь
+ ///
+ public static MiraDocImage CreateFromPath(string path) => new() { Path = path };
+
+ ///
+ /// Создания изображения из строки base64
+ ///
+ /// изображение в формате base64
+ ///
+ public static MiraDocImage CreateFromBase64(string base64) => new() { _b64Source = $"base64:{base64}" };
+
+ ///
+ /// Создание изображения из потока
+ ///
+ /// Поток
+ ///
+ public static MiraDocImage CreateFromStream(Stream stream) => new() { Source = stream };
+
+ ///
+ ///
+ ///
+ ///
+ public string GetImageForMiraDoc()
+ {
+ if (!string.IsNullOrEmpty(Path)) return Path;
+ if (_b64Source != null) return _b64Source;
+ if (_source == null) throw new ArgumentNullException("Для изображения не задан ни путь, ни поток. Необходимо заполнить как минимум одно из этого, для работы");
+ _b64Source = GetImageAsStringBase64(_source);
+ return _b64Source;
+ }
+
+ private string GetImageAsStringBase64(Stream stream)
+ {
+ //Вот это вот, в общем-то, ещё один жуткий костыль. Дело в том, что MigraDoc не поддерживает создание изображений из потоков. Только из путей. Но всё же, способ есть
+ //Вот он собственно. И да, фактически это жуткая система, записывающая картинку в строку. Увы, по другому не получится
+ stream.Position = 0;
+ int count = (int)stream.Length;
+ byte[] data = new byte[count];
+ stream.Read(data, 0, count);
+ return $"base64:{Convert.ToBase64String(data)}";
+ }
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/ImageModels/PdfImage.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/ImageModels/PdfImage.cs
new file mode 100644
index 0000000..60d52a5
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/ImageModels/PdfImage.cs
@@ -0,0 +1,41 @@
+using PIHelperSh.PdfCreator.Enums;
+using PIHelperSh.PdfCreator.Interfaces;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PIHelperSh.PdfCreator.Models.ImageModels
+{
+ ///
+ /// Информация о изображении
+ ///
+ public class PdfImage : IPdfElement
+ {
+ ///
+ /// Путь до изображения
+ ///
+ public MiraDocImage Image { get; set; } = null!;
+
+ ///
+ /// Ширина изображения
+ ///
+ public int? Width { get; set; } = null;
+
+ ///
+ /// Высота изображения
+ ///
+ public int? Height { get; set; } = null;
+
+ ///
+ /// Выравнивание текста внутри параграфа (по умолчанию - по левой строне)
+ ///
+ public PdfAlignmentType ImageAlignment { get; set; } = PdfAlignmentType.Left;
+
+ ///
+ /// Отступ после параграфа (по умолчанию средний)
+ ///
+ public PdfMargin MarginAfter { get; set; } = PdfMargin.Medium;
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/PieChartModel/PdfPieChartData.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/PieChartModel/PdfPieChartData.cs
new file mode 100644
index 0000000..4542f04
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/PieChartModel/PdfPieChartData.cs
@@ -0,0 +1,39 @@
+using System.Drawing;
+
+namespace PIHelperSh.PdfCreator.Models.PieChartModel
+{
+ ///
+ /// Элемент данных. Одно значение для диаграммы.
+ ///
+ public class PdfPieChartData
+ {
+ ///
+ /// Название варианта
+ ///
+ public string DisplayName { get; set; } = null!;
+
+ ///
+ /// Значение варианта(по ним строят диаграмму)
+ ///
+ public double Value { get; set; }
+
+ ///
+ /// Цвет области на диаграме. При null будет использоватсся выдача цветов по умолчанию)
+ ///
+ public Color? Color { get; set; } = null;
+
+ ///
+ ///
+ public PdfPieChartData() { }
+
+ ///
+ ///
+ ///
+ ///
+ public PdfPieChartData(string displayName, double value)
+ {
+ DisplayName = displayName;
+ Value = value;
+ }
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/PieChartModel/PdfPieChartModel.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/PieChartModel/PdfPieChartModel.cs
new file mode 100644
index 0000000..21968a1
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/PieChartModel/PdfPieChartModel.cs
@@ -0,0 +1,50 @@
+using PIHelperSh.PdfCreator.Enums;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PIHelperSh.PdfCreator.Models.PieChartModel
+{
+ ///
+ /// Модель круговой диаграммы
+ ///
+ public class PdfPieChartModel
+ {
+ ///
+ /// Ширина диаграммы в см по умолчанию на всю ширину
+ ///
+ public double Width { get; set; } = 16;
+
+ ///
+ /// Высота диаграммы в см
+ ///
+ public double Height { get; set; } = 12;
+
+ ///
+ /// Заголовок диаграммы. Будет отображён над ней
+ ///
+ public string ChartName { get; set; } = null!;
+
+ ///
+ /// Стиль заголовка
+ ///
+ public PdfStyleType HeaderStyle { get; set; } = PdfStyleType.Bold;
+
+ ///
+ /// Выравнивание заголовка по горизонтали
+ ///
+ public PdfAlignmentType HeaderAlignment { get; set; } = PdfAlignmentType.Center;
+
+ ///
+ /// Вариант расположения легенды
+ ///
+ public PdfLegendPosition LegendPosition { get; set; } = PdfLegendPosition.Bottom;
+
+ ///
+ /// Набор данных для создания диаграммы
+ ///
+ public List DataSet { get; set; } = new();
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PDFSimpleTable.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PDFSimpleTable.cs
new file mode 100644
index 0000000..9c93e1b
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PDFSimpleTable.cs
@@ -0,0 +1,51 @@
+using PIHelperSh.PdfCreator.Enums;
+using PIHelperSh.PdfCreator.Interfaces;
+
+namespace PIHelperSh.PdfCreator.Models.TableModels
+{
+ ///
+ /// Простая табличка в PDF
+ ///
+ public class PDFSimpleTable
+ {
+ ///
+ /// Заголовок
+ ///
+ public List? Header { get; set; } = null;
+
+ ///
+ /// Стиль заголовка (по умолчанию - жирный)
+ ///
+ public PdfStyleType HeaderStyle { get; set; } = PdfStyleType.Bold;
+
+ ///
+ /// Выравнивание текста внутри заголовка (по умолчанию - по центру)
+ ///
+ public PdfAlignmentType HeaderHorizontalAlignment { get; set; } = PdfAlignmentType.Center;
+
+ ///
+ /// Набор строк
+ ///
+ public List Rows { get; set; } = new();
+
+ ///
+ /// Базовый стиль строк
+ ///
+ public PdfStyleType RowStyle = PdfStyleType.Basic;
+
+ ///
+ /// Базовое выравнивание элементов сторок
+ ///
+ public PdfAlignmentType RowHorizontalAlignment = PdfAlignmentType.Rigth;
+
+ ///
+ /// Отступ после таблицы
+ ///
+ public PdfMargin MarginAfter = PdfMargin.None;
+
+ ///
+ /// Меняем ли ориентацию страницы на альбомную
+ ///
+ public bool ChangePageOrientation = false;
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PDFSimpleTableRow.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PDFSimpleTableRow.cs
new file mode 100644
index 0000000..8b7e30a
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PDFSimpleTableRow.cs
@@ -0,0 +1,30 @@
+using PIHelperSh.PdfCreator.Enums;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PIHelperSh.PdfCreator.Models.TableModels
+{
+ ///
+ /// Строка простой таблицы
+ ///
+ public class PDFSimpleTableRow
+ {
+ ///
+ /// Элемменты данной стоки
+ ///
+ public List Items = new List();
+
+ ///
+ /// Стиль элементов строки, если он отличается от стиля строк, определённого в таблице
+ ///
+ public PdfStyleType? Style = null;
+
+ ///
+ /// Выравнивание элементов строки, если оно отличается от выравнивания, определённого в таблице
+ ///
+ public PdfAlignmentType? Alignment = null;
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PdfTable.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PdfTable.cs
new file mode 100644
index 0000000..81b483b
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PdfTable.cs
@@ -0,0 +1,42 @@
+using PIHelperSh.PdfCreator.Enums;
+using PIHelperSh.PdfCreator.Interfaces;
+
+namespace PIHelperSh.PdfCreator.Models.TableModels
+{
+ ///
+ /// Таблица для вставки на лист
+ ///
+ ///
+ public class PdfTable
+ {
+ ///
+ /// Шапка таблицы(2 строки/2 столбца)
+ ///
+ public List? Header { get; set; } = null;
+
+ ///
+ /// Стиль заголовка (по умолчанию - жирный)
+ ///
+ public PdfStyleType HeaderStyle { get; set; } = PdfStyleType.Bold;
+
+ ///
+ /// Выравнивание текста внутри заголовка (по умолчанию - по центру)
+ ///
+ public PdfAlignmentType HeaderHorizontalAlignment { get; set; } = PdfAlignmentType.Center;
+
+ ///
+ /// Список объектов, информация о которых будет в таблице.
+ ///
+ public List Records { get; set; } = new();
+
+ ///
+ /// Стиль объектов в таблице (по умолчанию - базовый)
+ ///
+ public PdfStyleType RecordStyle { get; set; } = PdfStyleType.Basic;
+
+ ///
+ /// Выравнивание текста объектов в таблице (по умолчанию - по левой строне)
+ ///
+ public PdfAlignmentType RecordHorizontalAlignment { get; set; } = PdfAlignmentType.Left;
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PdfTableColumn.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PdfTableColumn.cs
new file mode 100644
index 0000000..f436fdd
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PdfTableColumn.cs
@@ -0,0 +1,25 @@
+using PIHelperSh.PdfCreator.Interfaces;
+
+namespace PIHelperSh.PdfCreator.Models.TableModels
+{
+ ///
+ /// Столбец(строка) таблицы, определяющий дальнейшее содержимое
+ ///
+ public class PdfTableColumn : IPdfColumnItem
+ {
+ ///
+ /// Заголовок
+ ///
+ public string? Title { get; set; }
+
+ ///
+ /// Размер (Ширина столбца/Высота строки)
+ ///
+ public float? Size { get; set; }
+
+ ///
+ /// Название свойства, которое будет заполнять столбец
+ ///
+ public string PropertyName { get; set; } = null!;
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PdfTableColumnGroup.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PdfTableColumnGroup.cs
new file mode 100644
index 0000000..51db426
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TableModels/PdfTableColumnGroup.cs
@@ -0,0 +1,25 @@
+using PIHelperSh.PdfCreator.Interfaces;
+
+namespace PIHelperSh.PdfCreator.Models.TableModels
+{
+ ///
+ /// Группа столбцов(строк) таблицы, определяющий дальнейшее содержимое
+ ///
+ public class PdfTableColumnGroup : IPdfColumnItem
+ {
+ ///
+ /// Заголовок
+ ///
+ public string? Title { get; set; }
+
+ ///
+ /// Количество элементов в группе
+ ///
+ public float? Size => InnerColumns.Sum(x => x.Size);
+
+ ///
+ /// Столбцы/строки в группе
+ ///
+ public List InnerColumns { get; set; } = new();
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TextModels/PdfList.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TextModels/PdfList.cs
new file mode 100644
index 0000000..17b210e
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TextModels/PdfList.cs
@@ -0,0 +1,26 @@
+using PIHelperSh.PdfCreator.Enums;
+using PIHelperSh.PdfCreator.Interfaces;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PIHelperSh.PdfCreator.Models.TextModels
+{
+ ///
+ /// Список элементов в PDF
+ ///
+ public class PdfList : IPdfElement
+ {
+ ///
+ /// Элементы списка (параграфы или иные спсики)
+ ///
+ public List Content { get; set; } = new();
+
+ ///
+ /// Отступ после списка (по умолчанию - средний)
+ ///
+ public PdfMargin MarginAfter { get; set; } = PdfMargin.Medium;
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TextModels/PdfParagraph.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TextModels/PdfParagraph.cs
new file mode 100644
index 0000000..60282bd
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/Models/TextModels/PdfParagraph.cs
@@ -0,0 +1,36 @@
+using PIHelperSh.PdfCreator.Enums;
+using PIHelperSh.PdfCreator.Interfaces;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PIHelperSh.PdfCreator.Models.TextModels
+{
+ ///
+ /// Параграф в PDF
+ ///
+ public class PdfParagraph : IPdfElement
+ {
+ ///
+ /// Текст параграфа
+ ///
+ public string Text { get; set; } = string.Empty;
+
+ ///
+ /// Стиль параграфа (по умолчанию - базовый)
+ ///
+ public PdfStyleType Style { get; set; } = PdfStyleType.Basic;
+
+ ///
+ /// Выравнивание текста внутри параграфа (по умолчанию - по левой строне)
+ ///
+ public PdfAlignmentType ParagraphAlignment { get; set; } = PdfAlignmentType.Left;
+
+ ///
+ /// Отступ после параграфа (по умолчанию средний)
+ ///
+ public PdfMargin MarginAfter { get; set; } = PdfMargin.Medium;
+ }
+}
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/PIHelperSh.PdfCreator.csproj b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/PIHelperSh.PdfCreator.csproj
new file mode 100644
index 0000000..ebb8d93
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/PIHelperSh.PdfCreator.csproj
@@ -0,0 +1,38 @@
+
+
+
+ net8.0
+ enable
+ enable
+ True
+ Библиотека PDF
+ MaximK
+ Небольшая надстройка для более удобной работы с PDF
+ README.md
+ https://github.com/KuzarinM/PIHelperSh/tree/master/PIHelperSh.PdfCreater
+ True
+ LICENSE
+ 1.1.1
+ True
+
+
+
+
+ True
+ \
+
+
+
+
+
+
+
+
+
+
+ True
+ \
+
+
+
+
diff --git a/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/PdfCreator.cs b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/PdfCreator.cs
new file mode 100644
index 0000000..ca7eb08
--- /dev/null
+++ b/Cop.Borovkov.Var3/PIHelperSh.PdfCreater/PdfCreator.cs
@@ -0,0 +1,550 @@
+using MigraDoc.DocumentObjectModel;
+using System.Text;
+using MigraDoc.Rendering;
+using MigraDoc.DocumentObjectModel.Tables;
+using System.Reflection;
+using MigraDoc.DocumentObjectModel.Shapes.Charts;
+using PIHelperSh.Core.Extensions;
+using PIHelperSh.PdfCreator.Enums;
+using PIHelperSh.PdfCreator.Models.TableModels;
+using PIHelperSh.PdfCreator.Models.TextModels;
+using PIHelperSh.PdfCreator.Models.ImageModels;
+using PIHelperSh.PdfCreator.Models.PieChartModel;
+using PIHelperSh.PdfCreator.Interfaces;
+
+namespace PIHelperSh.PdfCreator
+{
+ ///
+ ///
+ public class PdfCreator : IPdfCreator
+ {
+ private Document? _document;
+ private Section? _section;
+
+ private readonly Unit _borderWidth = 0.5;
+
+ ///
+ ///
+ public PdfCreator()
+ {
+ _document = new Document();
+ DefineStyles(_document);
+ Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
+ _section = _document.AddSection();
+ }
+
+ #region Внутренние методы
+ private static string GetListLavel(int level)
+ {
+ try
+ {
+ return level.CreateEnumFromValue().GetValue();
+ }
+ catch (Exception)
+ {
+ return PdfStyleType.Basic.GetValue();
+ }
+ }
+
+ private void ConfigurateChartLegend(Chart chart, PdfLegendPosition position)
+ {
+ switch (position)
+ {
+ case PdfLegendPosition.Bottom:
+ chart.FooterArea.AddLegend();
+ break;
+ case PdfLegendPosition.Right:
+ chart.RightArea.AddLegend();
+ break;
+ case PdfLegendPosition.Left:
+ chart.LeftArea.AddLegend();
+ break;
+ case PdfLegendPosition.Top:
+ chart.TopArea.AddLegend();
+ break;
+ }
+ }
+
+ private static void DefineStyles(Document document)
+ {
+ #region Базовый стиль
+ var style = document.Styles["Normal"];
+ style.Font.Name = "Times New Roman";
+ style.Font.Size = 14;
+ #endregion
+
+ #region Стиль заголовка
+ style = document.Styles.AddStyle("NormalTitle", "Normal");
+ style.Font.Bold = true;
+ style.Font.Size = 18;
+ #endregion
+
+ #region Стиль жирный
+ style = document.Styles.AddStyle("NormalBold", "Normal");
+ style.Font.Bold = true;
+ #endregion
+
+ #region Маркированный список уровень 1
+ style = document.AddStyle("BulletList", "Normal");
+ style.ParagraphFormat.LeftIndent = "1.5cm";
+ style.ParagraphFormat.ListInfo = new ListInfo
+ {
+ ContinuePreviousList = true,//Продолжать список, который уже был ранее
+ ListType = ListType.BulletList1//Маркер
+ };
+ style.ParagraphFormat.TabStops.ClearAll();
+ style.ParagraphFormat.TabStops.AddTabStop(Unit.FromCentimeter(1.5), TabAlignment.Left);
+
+ style.ParagraphFormat.FirstLineIndent = "-0.5cm";
+ #endregion
+
+ #region Маркированный список уровень 2
+ style = document.AddStyle("BulletList2", "BulletList");
+ style.ParagraphFormat.LeftIndent = "3.0cm";
+ style.ParagraphFormat.ListInfo.ListType = ListType.BulletList2;
+ style.ParagraphFormat.TabStops.ClearAll();
+ style.ParagraphFormat.TabStops.AddTabStop(Unit.FromCentimeter(3.0), TabAlignment.Left);
+ #endregion
+
+ #region Маркированный список уровень 3
+ style = document.AddStyle("BulletList3", "BulletList");
+ style.ParagraphFormat.LeftIndent = "4.5cm";
+ style.ParagraphFormat.ListInfo.ListType = ListType.BulletList3;
+ style.ParagraphFormat.TabStops.ClearAll();
+ style.ParagraphFormat.TabStops.AddTabStop(Unit.FromCentimeter(4.5), TabAlignment.Left);
+ #endregion
+
+ #region Мелкий шрифт
+ style = document.Styles.AddStyle("NormalSmall", "Normal");
+ style.Font.Size = 11;
+ #endregion
+ }
+
+ private Paragraph? MakeParagraph(PdfParagraph pdfParagraph)
+ {
+ if (_section == null)
+ return null;
+ var paragraph = _section.AddParagraph(pdfParagraph.Text);
+ paragraph.Format.Alignment = pdfParagraph.ParagraphAlignment.GetValue();
+ //Т.к стили могут назначаться по иному, тут будет вот так вот
+ return paragraph;
+ }
+
+ private Paragraph? MakeList(PdfList pdfList, int level)
+ {
+ Paragraph? last = null;
+ foreach (IPdfElement element in pdfList.Content)
+ {
+ if (element is PdfParagraph par)
+ {
+ var paragraph = MakeParagraph(par);
+ if (paragraph == null)
+ continue;
+
+ paragraph.Format.SpaceAfter = "0.3cm";
+ paragraph.Style = GetListLavel(level);
+ last = paragraph;
+ }
+ else if (element is PdfList ls)
+ {
+ last = MakeList(ls, level + 1);
+ }
+ }
+ return last;
+ }
+
+ private void ConfigurateParagraph(Paragraph paragraph, PdfParagraph properties)
+ {
+ paragraph.Format.Alignment = properties.ParagraphAlignment.GetValue(); ;
+ if (properties.MarginAfter != PdfMargin.None) paragraph.Format.SpaceAfter = properties.MarginAfter.GetValue();
+ paragraph.Style = properties.Style.GetValue();
+ }
+
+ private void ConfigurateCell(Cell cell, string text, PdfAlignmentType alignment, PdfStyleType style, int? rightMerge = null, int? downMerge = null, bool dcw = false)
+ {
+ if (rightMerge.HasValue) cell.MergeRight = rightMerge.Value;
+ if (downMerge.HasValue)
+ {
+ cell.MergeDown = downMerge.Value;
+ cell.VerticalAlignment = VerticalAlignment.Center;
+ }
+
+ Paragraph paragraph = cell.AddParagraph(text);
+ ConfigurateParagraph(paragraph, new()
+ {
+ ParagraphAlignment = alignment,
+ Style = style,
+ MarginAfter = PdfMargin.None
+ });
+
+ cell.Borders.Left.Width = _borderWidth;
+ cell.Borders.Right.Width = _borderWidth;
+ cell.Borders.Top.Width = _borderWidth;
+ cell.Borders.Bottom.Width = _borderWidth;
+
+ if (dcw)
+ {
+ float columnNeeds = text.Length / 3.8f;
+ if (cell.Column.Width.Centimeter < columnNeeds)
+ cell.Column.Width = Unit.FromCentimeter(columnNeeds);
+ }
+ }
+
+ private Func