вроде как все воркает, но нужно подкорректировать

This commit is contained in:
Алексей Тихоненков 2024-10-02 18:26:36 +04:00
parent b5c4b431ad
commit acba0a072a
14 changed files with 474 additions and 49 deletions

View File

@ -0,0 +1,36 @@
namespace FormLibrary
{
partial class ComponentHistogramToPdf
{
/// <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,88 @@
using FormLibrary.HelperClasses;
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Shapes;
using MigraDoc.DocumentObjectModel.Shapes.Charts;
using MigraDoc.Rendering;
using OxyPlot.Series;
using OxyPlot;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using OxyPlot.WindowsForms;
namespace FormLibrary
{
public partial class ComponentHistogramToPdf : Component
{
public ComponentHistogramToPdf()
{
InitializeComponent();
}
public ComponentHistogramToPdf(IContainer container)
{
container.Add(this);
InitializeComponent();
}
public void CreateHistogramPdf(string filePath, string documentTitle, string chartTitle, LegendPosition legendPosition, List<ChartData> chartData)
{
// Проверка на заполненность входных данных
if (string.IsNullOrEmpty(filePath))
throw new ArgumentException("Путь к файлу не может быть пустым.");
if (string.IsNullOrEmpty(documentTitle))
throw new ArgumentException("Название документа не может быть пустым.");
if (string.IsNullOrEmpty(chartTitle))
throw new ArgumentException("Заголовок диаграммы не может быть пустым.");
if (chartData == null || chartData.Count == 0)
throw new ArgumentException("Набор данных не может быть пустым.");
foreach (var data in chartData)
{
if (string.IsNullOrEmpty(data.SeriesName) || data.Data == null || data.Data.Count == 0)
throw new ArgumentException($"Набор данных для серии '{data.SeriesName}' некорректен.");
}
// Создание графика
var plotModel = new PlotModel { Title = chartTitle };
foreach (var data in chartData)
{
var barSeries = new BarSeries { Title = data.SeriesName };
foreach (var item in data.Data)
{
barSeries.Items.Add(new BarItem(item.Value));
}
plotModel.Series.Add(barSeries);
}
// Сохранение графика в изображение
var pngExporter = new PngExporter { Width = 600, Height = 400};
using (var stream = new MemoryStream())
{
pngExporter.Export(plotModel, stream);
File.WriteAllBytes("chart.png", stream.ToArray());
}
// Создание документа
Document document = new Document();
document.Info.Title = documentTitle;
document.Info.Subject = "Гистограмма";
Section section = document.AddSection();
section.AddParagraph(chartTitle, "Heading1");
// Вставка изображения в PDF
var image = section.AddImage("chart.png");
image.Width = Unit.FromCentimeter(15);
// Сохранение документа в PDF
PdfDocumentRenderer renderer = new PdfDocumentRenderer(true) { Document = document };
renderer.RenderDocument();
renderer.PdfDocument.Save(filePath);
// Удалите временное изображение, если необходимо
File.Delete("chart.png");
}
}
}

View File

@ -8,6 +8,9 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="OxyPlot.Core" Version="2.2.0" />
<PackageReference Include="OxyPlot.WindowsForms" Version="2.2.0" />
<PackageReference Include="OxyPlot.Wpf" Version="2.2.0" />
<PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" /> <PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" />
</ItemGroup> </ItemGroup>

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FormLibrary.HelperClasses
{
public class ChartData
{
public string SeriesName { get; set; }
public Dictionary<string, double> Data { get; set; } // Ключ — категория, значение — значение для гистограммы
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FormLibrary.HelperClasses
{
public enum LegendPosition
{
Top,
Bottom,
Left,
Right
}
}

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FormLibrary.HelperClasses
{
public class PDFTableSettings<T>
{
public string FilePath { get; set; }
public string DocumentTitle { get; set; }
public List<string> HeaderTitles { get; set; }
public List<float> ColumnWidths { get; set; }
public float HeaderRowHeight { get; set; }
public float DataRowHeight { get; set; }
public List<T> DataList { get; set; }
public Dictionary<int, string> ColumnPropertyMappings { get; set; }
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FormLibrary.HelperClasses
{
public class PdfDocumentData
{
public string FileName { get; set; }
public string DocumentTitle { get; set; }
public List<string[,]> Tables { get; set; }
public PdfDocumentData(string fileName, string documentTitle, List<string[,]> tables)
{
FileName = fileName ?? throw new ArgumentNullException(nameof(fileName));
DocumentTitle = documentTitle ?? throw new ArgumentNullException(nameof(documentTitle));
Tables = tables ?? throw new ArgumentNullException(nameof(tables));
}
}
}

View File

@ -1,4 +1,5 @@
using MigraDoc.DocumentObjectModel; using FormLibrary.HelperClasses;
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Tables; using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.Rendering; using MigraDoc.Rendering;
using System.ComponentModel; using System.ComponentModel;
@ -22,41 +23,34 @@ namespace FormLibrary
InitializeComponent(); InitializeComponent();
} }
// Публичный метод для генерации PDF-документа
public void GeneratePdf(string fileName, string documentTitle, List<string[,]> tables)
{
// Проверка на корректность входных данных
if (string.IsNullOrWhiteSpace(fileName)) throw new ArgumentException("Имя файла не может быть пустым.");
if (string.IsNullOrWhiteSpace(documentTitle)) throw new ArgumentException("Название документа не может быть пустым.");
if (tables == null || tables.Count == 0) throw new ArgumentException("Необходимо передать хотя бы одну таблицу.");
// Создание документа public void GeneratePdf(PdfDocumentData pdfData)
{
if (string.IsNullOrWhiteSpace(pdfData.FileName)) throw new ArgumentException("Имя файла не может быть пустым.");
if (string.IsNullOrWhiteSpace(pdfData.DocumentTitle)) throw new ArgumentException("Название документа не может быть пустым.");
if (pdfData.Tables == null || pdfData.Tables.Count == 0) throw new ArgumentException("Необходимо передать хотя бы одну таблицу.");
Document document = new Document(); Document document = new Document();
Section section = document.AddSection(); Section section = document.AddSection();
// Установка заголовка документа
Paragraph title = section.AddParagraph(); Paragraph title = section.AddParagraph();
title.AddFormattedText(documentTitle, TextFormat.Bold); title.AddFormattedText(pdfData.DocumentTitle, TextFormat.Bold);
title.Format.Alignment = ParagraphAlignment.Center; title.Format.Alignment = ParagraphAlignment.Center;
section.AddParagraph(); // Пустая строка section.AddParagraph();
// Обработка таблиц foreach (var tableData in pdfData.Tables)
foreach (var tableData in tables)
{ {
// Создание таблицы
Table table = section.AddTable(); Table table = section.AddTable();
int columnsCount = tableData.GetLength(1); int columnsCount = tableData.GetLength(1);
// Определение колонок
for (int i = 0; i < columnsCount; i++) for (int i = 0; i < columnsCount; i++)
{ {
Column column = table.AddColumn(Unit.FromCentimeter(3)); // Ширина колонки 3 см Column column = table.AddColumn(Unit.FromCentimeter(3));
} }
// Настройка границ таблицы
table.Borders.Width = 0.75; // Толщина границ таблицы
table.Borders.Color = Colors.Black; // Цвет границ таблицы
// Добавление строк и ячеек table.Borders.Width = 0.75;
table.Borders.Color = Colors.Black;
for (int i = 0; i < tableData.GetLength(0); i++) for (int i = 0; i < tableData.GetLength(0); i++)
{ {
Row row = table.AddRow(); Row row = table.AddRow();
@ -66,14 +60,13 @@ namespace FormLibrary
} }
} }
section.AddParagraph(); // Пустая строка после таблицы section.AddParagraph();
} }
// Сохранение документа
PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(true); PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(true);
pdfRenderer.Document = document; pdfRenderer.Document = document;
pdfRenderer.RenderDocument(); pdfRenderer.RenderDocument();
pdfRenderer.PdfDocument.Save(fileName); pdfRenderer.PdfDocument.Save(pdfData.FileName);
} }
} }
} }

View File

@ -0,0 +1,36 @@
namespace FormLibrary
{
partial class PDFTableCustom
{
/// <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,92 @@
using FormLibrary.HelperClasses;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.DocumentObjectModel;
using MigraDoc.Rendering;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace FormLibrary
{
public partial class PDFTableCustom : Component
{
public PDFTableCustom()
{
InitializeComponent();
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
}
public PDFTableCustom(IContainer container)
{
container.Add(this);
InitializeComponent();
}
public void GeneratePDFWithHead<T>(PDFTableSettings<T> settings)
{
if (settings == null ||
string.IsNullOrEmpty(settings.FilePath) ||
string.IsNullOrEmpty(settings.DocumentTitle) ||
settings.HeaderTitles == null || settings.HeaderTitles.Count == 0 ||
settings.ColumnWidths == null || settings.DataList == null ||
settings.ColumnPropertyMappings == null)
throw new ArgumentException("Заполнены не все необходимые данные для генерации документа.");
if (settings.HeaderTitles.Count != settings.ColumnWidths.Count)
throw new ArgumentException("Количество заголовков должно совпадать с количеством ширин столбцов.");
Document document = new Document();
Section section = document.AddSection();
section.AddParagraph(settings.DocumentTitle, "Heading1");
Table table = new Table();
table.Borders.Width = 0.75;
// столбцы
for (int i = 0; i < settings.ColumnWidths.Count; i++)
{
Column column = table.AddColumn(Unit.FromCentimeter(settings.ColumnWidths[i]));
column.Format.Alignment = ParagraphAlignment.Center;
}
// заголовки
Row headerRow = table.AddRow();
headerRow.Height = Unit.FromCentimeter(settings.HeaderRowHeight);
for (int i = 0; i < settings.HeaderTitles.Count; i++)
{
headerRow.Cells[i].AddParagraph(settings.HeaderTitles[i]);
headerRow.Cells[i].Format.Font.Bold = true;
headerRow.Cells[i].Format.Alignment = ParagraphAlignment.Center;
}
// данные
foreach (var dataItem in settings.DataList)
{
Row row = table.AddRow();
row.Height = Unit.FromCentimeter(settings.DataRowHeight);
foreach (var columnMapping in settings.ColumnPropertyMappings)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(columnMapping.Value);
if (propertyInfo == null)
throw new ArgumentException($"Свойство {columnMapping.Value} не найдено в классе {typeof(T).Name}.");
object value = propertyInfo.GetValue(dataItem);
row.Cells[columnMapping.Key].AddParagraph(value != null ? value.ToString() : "");
}
}
section.Add(table);
PdfDocumentRenderer renderer = new PdfDocumentRenderer(true) { Document = document };
renderer.RenderDocument();
renderer.Save(settings.FilePath);
}
}
}

View File

@ -42,6 +42,11 @@
button7 = new Button(); button7 = new Button();
pdfTable1 = new FormLibrary.PDFTable(components); pdfTable1 = new FormLibrary.PDFTable(components);
button8 = new Button(); button8 = new Button();
pdfTableCustom1 = new FormLibrary.PDFTableCustom(components);
button9 = new Button();
button10 = new Button();
button11 = new Button();
componentHistogramToPdf1 = new FormLibrary.ComponentHistogramToPdf(components);
SuspendLayout(); SuspendLayout();
// //
// customListBox1 // customListBox1
@ -153,11 +158,41 @@
button8.UseVisualStyleBackColor = true; button8.UseVisualStyleBackColor = true;
button8.Click += GeneratePdfButton_Click; button8.Click += GeneratePdfButton_Click;
// //
// button9
//
button9.Location = new Point(189, 481);
button9.Name = "button9";
button9.Size = new Size(139, 23);
button9.TabIndex = 12;
button9.Text = "Create customPDF";
button9.UseVisualStyleBackColor = true;
button9.Click += btnGeneratePDF_Click;
//
// button10
//
button10.Location = new Point(0, 0);
button10.Name = "button10";
button10.Size = new Size(75, 23);
button10.TabIndex = 0;
//
// button11
//
button11.Location = new Point(347, 481);
button11.Name = "button11";
button11.Size = new Size(139, 23);
button11.TabIndex = 13;
button11.Text = "Create customPDF";
button11.UseVisualStyleBackColor = true;
button11.Click += btnGenerateHistogrammPdf_Click;
//
// MainForm // MainForm
// //
AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font; AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(944, 625); ClientSize = new Size(944, 625);
Controls.Add(button11);
Controls.Add(button10);
Controls.Add(button9);
Controls.Add(button8); Controls.Add(button8);
Controls.Add(button7); Controls.Add(button7);
Controls.Add(button6); Controls.Add(button6);
@ -191,5 +226,10 @@
private Button button7; private Button button7;
private FormLibrary.PDFTable pdfTable1; private FormLibrary.PDFTable pdfTable1;
private Button button8; private Button button8;
private FormLibrary.PDFTableCustom pdfTableCustom1;
private Button button9;
private Button button10;
private Button button11;
private FormLibrary.ComponentHistogramToPdf componentHistogramToPdf1;
} }
} }

View File

@ -130,39 +130,92 @@ namespace Forms
{ {
try try
{ {
// Создаем экземпляр компонента для генерации PDF var pdfData = new PdfDocumentData(
var documentGenerator = new PDFTable(); "G:\\Отчет1.pdf",
"Название документа",
// Пример таблиц new List<string[,]>
var tables = new List<string[,]>
{ {
new string[,] new string[,]
{ {
{ "test 1", "test 2", "test 3" }, { "Ячейка 1", "Ячейка 2", "Ячейка 3" },
{ "test 4", "test 5", "test 6" } { "Ячейка 4", "Ячейка 5", "Ячейка 6" }
}, },
new string[,] new string[,]
{ {
{ "test 1", "test 2" }, { "Ячейка 1", "Ячейка 2" },
{ "test 1", "test 2" } { "Ячейка 1", "Ячейка 2" }
} }
}; });
// Вызываем метод для создания PDF var documentGenerator = new PDFTable();
string filePath = "G:\\Отчет.pdf"; documentGenerator.GeneratePdf(pdfData);
string documentTitle = "test name";
documentGenerator.GeneratePdf(filePath, documentTitle, tables);
// Уведомляем пользователя
MessageBox.Show("PDF-документ успешно создан!", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information); MessageBox.Show("PDF-документ успешно создан!", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
} }
catch (Exception ex) catch (Exception ex)
{ {
// Обрабатываем ошибки
MessageBox.Show($"Произошла ошибка: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); MessageBox.Show($"Произошла ошибка: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
} }
} }
private void btnGeneratePDF_Click(object sender, EventArgs e)
{
// Создание объекта настроек
var settings = new PDFTableSettings<Student>
{
FilePath = "G:\\Отчет2.pdf",
DocumentTitle = "Отчет по студентам",
HeaderTitles = new List<string> { "Группа", "ФИО", "Курс" },
ColumnWidths = new List<float> { 4.0f, 6.0f, 2.0f },
HeaderRowHeight = 1.0f,
DataRowHeight = 1.0f,
DataList = new List<Student>
{
new Student { Group = "Пибд-33", FullName = "Иван Иванов", Course = 3 },
new Student { Group = "Пибд-33", FullName = "Петр Петров", Course = 2 },
new Student { Group = "Пибд-34", FullName = "Алексей Сидоров", Course = 4 }
},
ColumnPropertyMappings = new Dictionary<int, string>
{
{ 0, nameof(Student.Group) },
{ 1, nameof(Student.FullName) },
{ 2, nameof(Student.Course) }
}
};
try
{
pdfTableCustom1.GeneratePDFWithHead(settings);
MessageBox.Show("PDF-документ успешно создан!", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"Ошибка: {ex.Message}");
}
}
private void btnGenerateHistogrammPdf_Click(object sender, EventArgs e)
{
try
{
var histogramGenerator = new ComponentHistogramToPdf();
var chartData = new List<ChartData>
{
new ChartData { SeriesName = "Серия 1", Data = new Dictionary<string, double> { { "Категория 1", 5 }, { "Категория 2", 10 } } },
new ChartData { SeriesName = "Серия 2", Data = new Dictionary<string, double> { { "Категория 1", 3 }, { "Категория 2", 8 } } }
};
// Укажите путь, куда хотите сохранить PDF
string filePath = "G:\\Гистограмма.pdf";
// Генерация PDF
histogramGenerator.CreateHistogramPdf(filePath, "Название документа", "Заголовок диаграммы", LegendPosition.Top, chartData);
MessageBox.Show("PDF успешно сгенерирован!", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"Ошибка: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
} }
} }

View File

@ -120,4 +120,10 @@
<metadata name="pdfTable1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="pdfTable1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value> <value>17, 17</value>
</metadata> </metadata>
<metadata name="pdfTableCustom1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>122, 17</value>
</metadata>
<metadata name="componentHistogramToPdf1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>269, 17</value>
</metadata>
</root> </root>

View File

@ -1,3 +1,5 @@
using System.Text;
namespace Forms namespace Forms
{ {
internal static class Program internal static class Program
@ -10,6 +12,7 @@ namespace Forms
{ {
// To customize application configuration such as set high DPI settings or default font, // To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration. // see https://aka.ms/applicationconfiguration.
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
ApplicationConfiguration.Initialize(); ApplicationConfiguration.Initialize();
Application.Run(new MainForm()); Application.Run(new MainForm());
} }