This commit is contained in:
dyakonovr 2024-09-29 21:12:45 +04:00
parent e57bd46f1f
commit b4035d6b13
16 changed files with 891 additions and 7 deletions

View File

@ -28,6 +28,7 @@
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
customCheckedListBox = new WinFormsLibrary1.CustomCheckedListBox();
addInListboxItemButton = new Button();
clearListboxButton = new Button();
@ -46,6 +47,12 @@
addEmployeeButton = new Button();
departamentComboBox = new ComboBox();
getSelectedTreeItemButton = new Button();
pdfWithImages1 = new WinFormsLibrary1.PdfWithImages(components);
listBoxImages = new ListBox();
button1 = new Button();
createPdfButton = new Button();
pdfTableButton = new Button();
pdfDiagramButton = new Button();
SuspendLayout();
//
// customCheckedListBox
@ -213,11 +220,65 @@
getSelectedTreeItemButton.UseVisualStyleBackColor = true;
getSelectedTreeItemButton.Click += getSelectedTreeItemButton_Click;
//
// listBoxImages
//
listBoxImages.FormattingEnabled = true;
listBoxImages.ItemHeight = 15;
listBoxImages.Location = new Point(25, 398);
listBoxImages.Name = "listBoxImages";
listBoxImages.Size = new Size(280, 124);
listBoxImages.TabIndex = 18;
//
// button1
//
button1.Location = new Point(25, 528);
button1.Name = "button1";
button1.Size = new Size(139, 23);
button1.TabIndex = 19;
button1.Text = "Выбрать изображения";
button1.UseVisualStyleBackColor = true;
button1.Click += button1_Click;
//
// createPdfButton
//
createPdfButton.Location = new Point(170, 528);
createPdfButton.Name = "createPdfButton";
createPdfButton.Size = new Size(135, 23);
createPdfButton.TabIndex = 20;
createPdfButton.Text = "Создать PDF";
createPdfButton.UseVisualStyleBackColor = true;
createPdfButton.Click += createPdfButton_Click;
//
// pdfTableButton
//
pdfTableButton.Location = new Point(342, 398);
pdfTableButton.Name = "pdfTableButton";
pdfTableButton.Size = new Size(152, 23);
pdfTableButton.TabIndex = 21;
pdfTableButton.Text = "Создать таблицу в PDF";
pdfTableButton.UseVisualStyleBackColor = true;
pdfTableButton.Click += pdfTableButton_Click;
//
// pdfDiagramButton
//
pdfDiagramButton.Location = new Point(342, 427);
pdfDiagramButton.Name = "pdfDiagramButton";
pdfDiagramButton.Size = new Size(152, 23);
pdfDiagramButton.TabIndex = 22;
pdfDiagramButton.Text = "Создать диаграмму";
pdfDiagramButton.UseVisualStyleBackColor = true;
pdfDiagramButton.Click += pdfDiagramButton_Click;
//
// Form1
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(700, 407);
ClientSize = new Size(700, 566);
Controls.Add(pdfDiagramButton);
Controls.Add(pdfTableButton);
Controls.Add(createPdfButton);
Controls.Add(button1);
Controls.Add(listBoxImages);
Controls.Add(getSelectedTreeItemButton);
Controls.Add(departamentComboBox);
Controls.Add(addEmployeeButton);
@ -263,5 +324,11 @@
private Button addEmployeeButton;
private ComboBox departamentComboBox;
private Button getSelectedTreeItemButton;
private WinFormsLibrary1.PdfWithImages pdfWithImages1;
private ListBox listBoxImages;
private Button button1;
private Button createPdfButton;
private Button pdfTableButton;
private Button pdfDiagramButton;
}
}

View File

@ -1,12 +1,24 @@
using System.Security.Cryptography.Xml;
using WinFormsLibrary1;
using WinFormsLibrary1.Errors;
using WinFormsLibrary1.Configs.Diagram;
using WinFormsLibrary1.Configs.Image;
using WinFormsLibrary1.Models;
using WinFormsLibrary1.Errors;
using WinFormsLibrary1.Configs.Diagram;
using WinFormsLibrary1.Configs.Table;
using PdfSharp.Pdf.Content.Objects;
namespace WinFormsApp1
{
public partial class Form1 : Form
{
private PdfWithImages pdfWithImages = new PdfWithImages();
private List<byte[]> selectedImages = new List<byte[]>();
private PdfWithTable pdfWithTable = new PdfWithTable();
private PdfWithDiagram pdfWithDiagram = new PdfWithDiagram();
public Form1()
{
InitializeComponent();
@ -106,5 +118,116 @@ namespace WinFormsApp1
nameTextBox.Text = employee.Name;
departamentComboBox.SelectedItem = employee.Department;
}
// PDF WITH IMAGE
private void button1_Click(object sender, EventArgs e)
{
using OpenFileDialog openFileDialog = new OpenFileDialog
{
Multiselect = true,
Filter = "Èçîáðàæåíèÿ|*.jpg;*.jpeg;*.png;*.bmp"
};
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
// Î÷èùàåì ïðåäûäóùèå äàííûå
selectedImages.Clear();
listBoxImages.Items.Clear();
// Äîáàâëÿåì âûáðàííûå èçîáðàæåíèÿ â ñïèñîê
foreach (string filePath in openFileDialog.FileNames)
{
selectedImages.Add(File.ReadAllBytes(filePath));
listBoxImages.Items.Add(Path.GetFileName(filePath));
}
}
}
private void createPdfButton_Click(object sender, EventArgs e)
{
if (selectedImages.Count == 0)
{
MessageBox.Show("Âûáåðèòå õîòÿ áû îäíî èçîáðàæåíèå!", "Îøèáêà", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// Êîíôèãóðàöèÿ äëÿ PDF-äîêóìåíòà
var config = new PdfWithImageConfig
{
FilePath = "PdfWithImage.pdf",
Header = "Äîêóìåíò ñ èçîáðàæåíèÿìè",
Images = selectedImages
};
// Ñîçäàíèå PDF ÷åðåç êîìïîíåíò
pdfWithImages.CreatePdf(config);
MessageBox.Show("PDF óñïåøíî ñîçäàí!", "Óñïåõ", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
// PDF WITH TABLE
private void pdfTableButton_Click(object sender, EventArgs e)
{
PdfWithTableConfig<Human> config = new PdfWithTableConfig<Human>
{
FileName = "PdfWithTable.pdf",
DocumentTitle = "Ïðèìåð Òàáëèöû",
RowHeights = new List<double> { 1, 1, 1 },
Headers = new Dictionary<string, List<string>>
{
{ "Ëè÷íûå äàííûå", new List<string> {"Èìÿ", "Ôàìèëèÿ"} },
{ "Âîçðàñò", new List<string>() }
},
PropertiesPerRow = new List<string> { "Name", "Surname", "Age" },
Data = new List<Human>
{
new Human("Èâàí", "Èâàíîâ", 30),
new Human("Ïåòð", "Ïåòðîâ", 25),
new Human("Ñåðãåé", "Ñåðãååâ", 35)
}
};
try
{
// Âûçîâ ìåòîäà äëÿ ñîçäàíèÿ PDF
pdfWithTable.CreatePdf(config);
MessageBox.Show("PDF-äîêóìåíò óñïåøíî ñîçäàí!", "Óñïåõ", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"Îøèáêà ïðè ñîçäàíèè PDF: {ex.Message}", "Îøèáêà", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// PDF TO DIAGRAM
private void pdfDiagramButton_Click(object sender, EventArgs e)
{
try
{
pdfWithDiagram.CreateDoc(new PdfWithDiagramConfig
{
FilePath = "PdfWithPieDiagram.pdf",
Header = "Çàãîëîâîê",
ChartTitle = "Êðóãîâàÿ äèàãðàììà",
LegendLocation = WinFormsLibrary1.Configs.Diagram.Location.Bottom,
Data = new Dictionary<string, List<(string Name, double Value)>>
{
{
"Product A", new List<(string Name, double Value)>
{
("1111", 30.0),
("2", 20.0),
("3", 50.0)
}
}
}
});
MessageBox.Show("PDF äîêóìåíò ñ äèàãðàììîé ñîçäàí!", "Óñïåõ");
}
catch (Exception ex)
{
MessageBox.Show($"Îøèáêà: {ex.Message}");
}
}
}
}

View File

@ -117,4 +117,7 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="pdfWithImages1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WinFormsLibrary1.Configs.Diagram
{
public enum Location
{
Left,
Right,
Top,
Bottom
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WinFormsLibrary1.Configs.Diagram
{
public class PdfWithDiagramConfig
{
public string FilePath { get; set; }
public string Header { get; set; }
public string ChartTitle { get; set; }
public Location LegendLocation { get; set; }
public Dictionary<string, List<(string Name, double Value)>> Data { get; set; }
public void CheckFields()
{
if (string.IsNullOrEmpty(FilePath))
throw new ArgumentNullException(nameof(FilePath), "File path cannot be null or empty.");
if (string.IsNullOrEmpty(Header))
throw new ArgumentNullException(nameof(Header), "Header cannot be null or empty.");
if (Data == null || !Data.Any())
throw new ArgumentNullException(nameof(Data), "Data cannot be null or empty.");
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WinFormsLibrary1.Configs.Image
{
public class PdfWithImageConfig
{
public string FilePath { get; set; }
public string Header { get; set; }
public List<byte[]> Images { get; set; }
public void CheckFields()
{
if (string.IsNullOrWhiteSpace(FilePath) || string.IsNullOrWhiteSpace(Header) || Images == null || Images.Count == 0)
{
throw new ArgumentException("Все поля должны быть заполнены.");
}
}
}
}

View File

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WinFormsLibrary1.Configs.Table
{
public class PdfWithTableConfig<T>
{
/// <summary>
/// Имя файла для сохранения PDF-документа.
/// </summary>
public string FileName { get; set; }
/// <summary>
/// Заголовок документа PDF.
/// </summary>
public string DocumentTitle { get; set; }
/// <summary>
/// Список высот строк таблицы в виде массива двойных значений.
/// </summary>
public List<double> RowHeights { get; set; }
/// <summary>
/// Заголовки таблицы, где ключ - имя обобщающего столбца, а значение - список заголовков для соответствующего столбца.
/// ВАЖНО: если строка не имеет обобщающего столбца, то заголовком будет ключ (список будет пустой)
/// <code>
/// var Headers = new Dictionary
/// {
/// {"Личные данные", new List("Имя", "Фамилия")},
/// {"Возраст", new List()},
/// }
///
/// ------------------------------
/// | | Имя |
/// | Личные данные |------------|
/// | | Фамилия |
/// |----------------------------|
/// | Возраст |
/// ------------------------------
/// </code>
/// </summary>
public Dictionary<string, List<string>> Headers { get; set; }
/// <summary>
/// Список названий свойств, соответствующих данным, которые будут отображаться в строках таблицы.
/// </summary>
public List<string> PropertiesPerRow { get; set; }
/// <summary>
/// Данные для заполнения таблицы, представляющие собой список объектов типа T.
/// </summary>
public List<T> Data { get; set; }
/// <summary>
/// Проверяет корректность полей конфигурации.
/// Вызывает исключение, если какое-либо поле не соответствует требованиям.
/// </summary>
public void CheckFields()
{
if (string.IsNullOrWhiteSpace(FileName))
throw new ArgumentException("Имя файла не может быть пустым.", nameof(FileName));
if (string.IsNullOrWhiteSpace(DocumentTitle))
throw new ArgumentException("Название документа не может быть пустым.", nameof(DocumentTitle));
if (Headers == null || Headers.Count == 0)
throw new ArgumentException("Заголовки для шапки не могут быть пустыми.", nameof(Headers));
if (Data == null || Data.Count == 0)
throw new ArgumentException("Данные для таблицы не могут быть пустыми.", nameof(Data));
if (RowHeights == null || RowHeights.Count == 0)
throw new ArgumentException("Высоты строк не могут быть пустыми.", nameof(RowHeights));
if (PropertiesPerRow.Any(string.IsNullOrWhiteSpace))
throw new ArgumentException("Список названий свойств не может содержать пустые строки.", nameof(PropertiesPerRow));
if (RowHeights.Count != PropertiesPerRow.Count)
throw new ArgumentException("Количество высот строк должно соответствовать количеству названий свойств.", nameof(RowHeights));
if (Data.Count != PropertiesPerRow.Count)
throw new ArgumentException("Количество данных должно соответствовать количеству названий свойств.", nameof(Data));
}
}
}

View File

@ -35,20 +35,18 @@
//
textBox.Dock = DockStyle.Fill;
textBox.Location = new Point(0, 0);
textBox.Margin = new Padding(3, 2, 3, 2);
textBox.Name = "textBox";
textBox.Size = new Size(81, 23);
textBox.Size = new Size(93, 27);
textBox.TabIndex = 0;
textBox.TextChanged += textBox1_TextChanged;
//
// CustomTextBox
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
Controls.Add(textBox);
Margin = new Padding(3, 2, 3, 2);
Name = "CustomTextBox";
Size = new Size(81, 16);
Size = new Size(93, 21);
ResumeLayout(false);
PerformLayout();
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WinFormsLibrary1.Models
{
public class Human
{
public string Name { get; set; }
public string Surname { get; set; }
public int Age { get; set; }
public Human() { }
public Human(string name, string surname, int age)
{
Name = name;
Surname = surname;
Age = age;
}
}
}

View File

@ -0,0 +1,36 @@
namespace WinFormsLibrary1
{
partial class PdfWithDiagram
{
/// <summary>
/// Обязательная переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Требуемый метод для поддержки конструктора — не изменяйте
/// содержимое этого метода с помощью редактора кода.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@ -0,0 +1,117 @@
using MigraDoc.DocumentObjectModel.Shapes;
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MigraDoc.DocumentObjectModel.Shapes.Charts;
using WinFormsLibrary1.Configs.Diagram;
namespace WinFormsLibrary1
{
public partial class PdfWithDiagram : Component
{
public PdfWithDiagram()
{
InitializeComponent();
}
public PdfWithDiagram(IContainer container)
{
container.Add(this);
InitializeComponent();
}
private Document _document;
private Chart _chart;
private Document Document
{
get
{
if (_document == null)
{
_document = new Document();
}
return _document;
}
}
public void CreateHeader(string header)
{
var section = Document.AddSection();
var paragraph = section.AddParagraph(header);
paragraph.Format.Font.Color = Colors.Black;
paragraph.Format.Font.Bold = true;
}
private void ConfigChart(PdfWithDiagramConfig config)
{
((Shape)_chart).Width = Unit.FromCentimeter(16.0);
((Shape)_chart).Height = Unit.FromCentimeter(12.0);
_chart.TopArea.AddParagraph(config.ChartTitle);
_chart.XAxis.MajorTickMark = (TickMarkType)2;
_chart.YAxis.MajorTickMark = (TickMarkType)2;
_chart.YAxis.HasMajorGridlines = true;
_chart.PlotArea.LineFormat.Width = new Unit(1);
_chart.PlotArea.LineFormat.Visible = true;
switch (config.LegendLocation)
{
case Location.Left:
_chart.LeftArea.AddLegend();
break;
case Location.Right:
_chart.RightArea.AddLegend();
break;
case Location.Top:
_chart.TopArea.AddLegend();
break;
case Location.Bottom:
_chart.BottomArea.AddLegend();
break;
}
}
public void CreatePieChart(PdfWithDiagramConfig config)
{
_chart = new Chart(ChartType.Pie2D);
foreach (var kvp in config.Data)
{
Series series = _chart.SeriesCollection.AddSeries();
series.Name = kvp.Key;
series.Add(kvp.Value.Select(x => x.Value).ToArray()); // Используем Value для данных
}
_chart.XValues.AddXSeries().Add(config.Data.First().Value.Select(x => x.Name).ToArray()); // Используем Date для оси X
ConfigChart(config);
}
public void SaveDoc(string filepath)
{
if (string.IsNullOrEmpty(filepath))
throw new ArgumentNullException(nameof(filepath), "File path cannot be null or empty.");
if (_document == null)
throw new ArgumentNullException(nameof(_document), "Document is not created.");
if (_chart != null)
_document.LastSection.Add(_chart);
PdfDocumentRenderer documentRenderer = new PdfDocumentRenderer(true)
{
Document = _document
};
documentRenderer.RenderDocument();
documentRenderer.PdfDocument.Save(filepath);
}
public void CreateDoc(PdfWithDiagramConfig config)
{
config.CheckFields();
CreateHeader(config.Header);
CreatePieChart(config);
SaveDoc(config.FilePath);
}
}
}

View File

@ -0,0 +1,36 @@
namespace WinFormsLibrary1
{
partial class PdfWithImages
{
/// <summary>
/// Обязательная переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Требуемый метод для поддержки конструктора — не изменяйте
/// содержимое этого метода с помощью редактора кода.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@ -0,0 +1,177 @@
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WinFormsLibrary1.Configs.Image;
namespace WinFormsLibrary1
{
public partial class PdfWithImages : Component
{
private Document _document = null;
private Section _section = null;
private List<byte[]> _images = null;
private Document Document
{
get
{
if (_document == null)
{
_document = new Document();
}
return _document;
}
}
private Section Section
{
get
{
if (_section == null)
{
_section = Document.AddSection();
}
return _section;
}
}
private List<byte[]> Images
{
get
{
if (_images == null)
{
_images = new List<byte[]>();
}
return _images;
}
}
public PdfWithImages()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
InitializeComponent();
}
public PdfWithImages(IContainer container)
{
container.Add(this);
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
InitializeComponent();
}
public void CreatePdf(PdfWithImageConfig config)
{
config.CheckFields();
CreateHeader(config.Header);
foreach (var image in config.Images)
{
CreateImage(image);
}
SavePdf(config.FilePath);
}
public void CreateHeader(string header)
{
var paragraph = Section.AddParagraph(header);
paragraph.Format.Font.Name = "Arial";
paragraph.Format.Font.Bold = true;
paragraph.Format.Font.Size = 20;
paragraph.Format.SpaceAfter = 10;
}
public void SavePdf(string filepath)
{
if (string.IsNullOrWhiteSpace(filepath))
{
throw new ArgumentNullException("Имя файла не задано");
}
if (_document == null || _section == null)
{
throw new ArgumentNullException("Документ не сформирован, сохранять нечего");
}
var pdfRenderer = new PdfDocumentRenderer(true)
{
Document = _document,
};
pdfRenderer.RenderDocument();
pdfRenderer.Save(filepath);
}
public void CreateImage(byte[] image)
{
if (image == null || image.Length == 0)
{
throw new ArgumentNullException("Картинка не загружена");
}
Images.Add(image);
var imageFileName = Path.GetTempFileName();
File.WriteAllBytes(imageFileName, image);
var img = Section.AddImage(imageFileName);
img.Width = Unit.FromCentimeter(15); // Можно настроить ширину изображения
img.LockAspectRatio = true;
Section.AddParagraph();
/*if (image == null || image.Length == 0)
{
throw new ArgumentNullException("Картинка не загружена");
}
Images.Add(image);
// Создаём временный файл
var imageFileName = Path.GetTempFileName();
File.WriteAllBytes(imageFileName, image);
// Открываем изображение и проверяем его ориентацию
using (var img = System.Drawing.Image.FromFile(imageFileName))
{
// Проверяем ориентацию и вращаем, если необходимо
if (Array.IndexOf(img.PropertyIdList, 274) > -1)
{
var orientation = (int)img.GetPropertyItem(274).Value[0];
switch (orientation)
{
case 3: // Переворот на 180 градусов
img.RotateFlip(RotateFlipType.Rotate180FlipNone);
break;
case 6: // Поворот на 90 градусов вправо
img.RotateFlip(RotateFlipType.Rotate90FlipNone);
break;
case 8: // Поворот на 90 градусов влево
img.RotateFlip(RotateFlipType.Rotate270FlipNone);
break;
}
}
// Сохраняем отредактированное изображение
img.Save(imageFileName);
}
// Вставляем изображение в PDF
var pdfImage = Section.AddImage(imageFileName);
pdfImage.Width = Unit.FromCentimeter(15); // Можно настроить ширину изображения
pdfImage.LockAspectRatio = true;
// Добавляем пустую строку после изображения
Section.AddParagraph();*/
}
}
}

View File

@ -0,0 +1,36 @@
namespace WinFormsLibrary1
{
partial class PdfWithTable
{
/// <summary>
/// Обязательная переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Требуемый метод для поддержки конструктора — не изменяйте
/// содержимое этого метода с помощью редактора кода.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@ -0,0 +1,110 @@
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.IO;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.Rendering;
using PdfSharp.Pdf;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using WinFormsLibrary1.Configs.Table;
namespace WinFormsLibrary1
{
public partial class PdfWithTable : Component
{
public void CreatePdf<T>(PdfWithTableConfig<T> config)
{
config.CheckFields();
// Создание документа
var document = new Document();
var section = document.AddSection();
// Установка заголовка
var titleParagraph = section.AddParagraph(config.DocumentTitle);
titleParagraph.Format.Alignment = ParagraphAlignment.Center;
titleParagraph.Format.Font.Size = 16;
titleParagraph.Format.Font.Bold = true;
titleParagraph.Format.SpaceAfter = 20;
// Создание таблицы
var table = section.AddTable();
table.Borders.Width = 0.75;
// Создание столбцов
for (int i = 0; i < config.Data.Count + 2; i++)
{
var column = table.AddColumn(Unit.FromCentimeter(3)); // Ширину можно настроить
column.Format.Alignment = ParagraphAlignment.Center;
}
// Создание заголовков
for (int rowIndex = 0; rowIndex < config.PropertiesPerRow.Count; rowIndex++)
{
var row = table.AddRow();
row.Height = Unit.FromCentimeter(config.RowHeights[rowIndex]); // Высота строки
foreach (Cell cell in row.Cells)
{
cell.VerticalAlignment = VerticalAlignment.Center;
cell.Format.Alignment = ParagraphAlignment.Center;
}
}
int rowNum = 0;
foreach (var kvp in config.Headers)
{
string key = kvp.Key;
List<string> values = kvp.Value;
if (values.Count == 0)
{
table.Rows[rowNum].Cells[0].AddParagraph(key);
table.Rows[rowNum].Cells[0].MergeRight = 1;
rowNum++;
}
else
{
table.Rows[rowNum].Cells[0].AddParagraph(key);
table.Rows[rowNum].Cells[0].MergeDown = values.Count - 1;
foreach (var value in values)
{
table.Rows[rowNum].Cells[1].AddParagraph(value);
rowNum++;
}
}
}
for (int colIndex = 0; colIndex < config.Data.Count; colIndex++)
{
for (int rowIndex = 0; rowIndex < config.PropertiesPerRow.Count; rowIndex++)
{
Type type = typeof(T);
PropertyInfo property = type.GetProperty(config.PropertiesPerRow[rowIndex]);
if (property == null)
{
throw new ArgumentException($"Property with name {config.PropertiesPerRow[rowIndex]} doesn't exist in class {type.Name}");
}
table.Rows[rowIndex].Cells[colIndex + 2].AddParagraph(property.GetValue(config.Data[colIndex]).ToString());
}
}
// Рендеринг документа в PDF
var pdfRenderer = new PdfDocumentRenderer(true)
{
Document = document
};
pdfRenderer.RenderDocument();
pdfRenderer.PdfDocument.Save(config.FileName);
}
}
}

View File

@ -7,4 +7,8 @@
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" />
</ItemGroup>
</Project>