Лабораторная работа 2
This commit is contained in:
parent
88184c5e6d
commit
8d8d704a13
4
WinFormsApp1/WinFormsApp1/Form1.Designer.cs
generated
4
WinFormsApp1/WinFormsApp1/Form1.Designer.cs
generated
@ -32,6 +32,7 @@
|
||||
this.userControl11 = new WinFormsLibrary1.CheckedListBoxControl();
|
||||
this.dataControl1 = new WinFormsLibrary1.DataControl();
|
||||
this.treeViewControl1 = new WinFormsLibrary1.TreeViewControl();
|
||||
this.excel21 = new WinFormsLibrary1.ExcelTable(this.components);
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// userControl11
|
||||
@ -80,5 +81,8 @@
|
||||
private WinFormsLibrary1.CheckedListBoxControl userControl11;
|
||||
private WinFormsLibrary1.DataControl dataControl1;
|
||||
private WinFormsLibrary1.TreeViewControl treeViewControl1;
|
||||
private WinFormsLibrary1.ExcelImages excelComponent1;
|
||||
private WinFormsLibrary1.ExcelTable excel22;
|
||||
private WinFormsLibrary1.ExcelTable excel21;
|
||||
}
|
||||
}
|
36
WinFormsApp1/WinFormsLibrary1/ExcelImages.Designer.cs
generated
Normal file
36
WinFormsApp1/WinFormsLibrary1/ExcelImages.Designer.cs
generated
Normal file
@ -0,0 +1,36 @@
|
||||
namespace WinFormsLibrary1
|
||||
{
|
||||
partial class ExcelImages
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
80
WinFormsApp1/WinFormsLibrary1/ExcelImages.cs
Normal file
80
WinFormsApp1/WinFormsLibrary1/ExcelImages.cs
Normal file
@ -0,0 +1,80 @@
|
||||
using System.ComponentModel;
|
||||
using OfficeOpenXml;
|
||||
namespace WinFormsLibrary1
|
||||
{
|
||||
public partial class ExcelImages : Component
|
||||
{
|
||||
public ExcelImages()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public ExcelImages(IContainer container)
|
||||
{
|
||||
container.Add(this);
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void CreateDocument(
|
||||
string filePath,
|
||||
string documentTitle,
|
||||
List<Image> images)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(filePath))
|
||||
{
|
||||
throw new ArgumentException("Путь к файлу не может быть пустым.", nameof(filePath));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(documentTitle))
|
||||
{
|
||||
throw new ArgumentException("Название документа не может быть пустым.", nameof(documentTitle));
|
||||
}
|
||||
|
||||
if (images == null || images.Count == 0)
|
||||
{
|
||||
throw new ArgumentException("Массив изображений не может быть пустым.", nameof(images));
|
||||
}
|
||||
|
||||
using (var package = new ExcelPackage())
|
||||
{
|
||||
var worksheet = package.Workbook.Worksheets.Add(documentTitle);
|
||||
|
||||
worksheet.Cells[1, 1].Value = documentTitle;
|
||||
worksheet.Cells[1, 1].Style.Font.Bold = true;
|
||||
worksheet.Cells[1, 1].Style.Font.Size = 16;
|
||||
|
||||
double row = 2;
|
||||
foreach (var image in images)
|
||||
{
|
||||
var excelImage = worksheet.Drawings.AddPicture($"Image{(int)(row - 1)}", new MemoryStream(ImageToByteArray(image)));
|
||||
excelImage.SetPosition((int)(row - 1), 0, 0, 0);
|
||||
excelImage.SetSize(image.Width, image.Height);
|
||||
|
||||
row += (int)(image.Height/ PointsToPixels(worksheet.Row(1).Height));
|
||||
}
|
||||
|
||||
FileInfo file = new FileInfo(filePath);
|
||||
package.SaveAs(file);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] ImageToByteArray(Image image)
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
// Метод для перевода пунктов в пиксели
|
||||
static double PointsToPixels(double points)
|
||||
{
|
||||
return points * (96.0 / 72.0); // Стандартный DPI для экранов 96 пикселей на дюйм, а 1 пункт = 1/72 дюйма
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
36
WinFormsApp1/WinFormsLibrary1/ExcelTable.Designer.cs
generated
Normal file
36
WinFormsApp1/WinFormsLibrary1/ExcelTable.Designer.cs
generated
Normal file
@ -0,0 +1,36 @@
|
||||
namespace WinFormsLibrary1
|
||||
{
|
||||
partial class ExcelTable
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
212
WinFormsApp1/WinFormsLibrary1/ExcelTable.cs
Normal file
212
WinFormsApp1/WinFormsLibrary1/ExcelTable.cs
Normal file
@ -0,0 +1,212 @@
|
||||
using System.ComponentModel;
|
||||
using OfficeOpenXml;
|
||||
using OfficeOpenXml.Style;
|
||||
|
||||
namespace WinFormsLibrary1
|
||||
{
|
||||
public partial class ExcelTable : Component
|
||||
{
|
||||
public ExcelTable()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
public ExcelTable(IContainer container)
|
||||
{
|
||||
container.Add(this);
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
// Публичный метод для создания Excel документа
|
||||
public void GenerateExcel<T>(string filePath, string documentTitle,
|
||||
List<MergeInfo> mergeInfo,
|
||||
List<(string, string, string propertyName)> headerTitles, List<T> data)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath) || string.IsNullOrEmpty(documentTitle) ||
|
||||
mergeInfo == null || headerTitles == null || data == null)
|
||||
{
|
||||
throw new ArgumentException("Не все входные данные заполнены.");
|
||||
}
|
||||
// Проверка на заполненность шапки
|
||||
ValidateHeaders(headerTitles);
|
||||
|
||||
// Проверки на корректность объединения ячеек и заполнения
|
||||
ValidateMergedCells(mergeInfo, headerTitles.Count);
|
||||
|
||||
using (var package = new ExcelPackage())
|
||||
{
|
||||
var worksheet = package.Workbook.Worksheets.Add("Sheet1");
|
||||
|
||||
worksheet.Cells[1, 1].Value = documentTitle;
|
||||
worksheet.Cells[1, 1, 1, headerTitles.Count].Merge = true;
|
||||
worksheet.Cells[1, 1].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
|
||||
|
||||
//Мержим заголовки по столбцам
|
||||
for (int i = 1; i < headerTitles.Count; i++)
|
||||
{
|
||||
if (headerTitles[i].Item2 == headerTitles[i + 1].Item2)
|
||||
{
|
||||
int j;
|
||||
for (j = i; j < headerTitles.Count; j++)
|
||||
{
|
||||
if (headerTitles[j].Item2 != headerTitles[j + 1].Item2) break;
|
||||
}
|
||||
|
||||
mergeInfo.Add(new MergeInfo(2, i + 1, 2, j + 1));
|
||||
i = j + 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Заполняем шапку таблицы
|
||||
for (int i = 0; i < headerTitles.Count; i++)
|
||||
{
|
||||
worksheet.Cells[2, i + 1].Value = headerTitles[i].Item2;
|
||||
worksheet.Cells[3, i + 1].Value = headerTitles[i].Item1;
|
||||
|
||||
//Мержим заголовки по строкам
|
||||
if (headerTitles[i].Item1 == headerTitles[i].Item2) mergeInfo.Add(new MergeInfo(2, i + 1, 3, i + 1));
|
||||
}
|
||||
|
||||
// Применение объединений ячеек
|
||||
foreach (var merge in mergeInfo)
|
||||
{
|
||||
worksheet.Cells[merge.StartRow, merge.StartColumn, merge.EndRow, merge.EndColumn].Merge = true;
|
||||
}
|
||||
|
||||
// Установка высоты строк
|
||||
for (int i = 0; i < data.Count; i++)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Заполнение данных таблицы
|
||||
for (int rowIndex = 0; rowIndex < data.Count; rowIndex++)
|
||||
{
|
||||
var rowData = data[rowIndex];
|
||||
for (int colIndex = 0; colIndex < headerTitles.Count; colIndex++)
|
||||
{
|
||||
// Используем сопоставление полей/свойств объекта
|
||||
string propertyName = headerTitles[colIndex].propertyName;
|
||||
var property = rowData.GetType().GetProperty(propertyName);
|
||||
|
||||
if (property == null)
|
||||
throw new ArgumentException($"Свойство {property} не найдено в классе {propertyName}.");
|
||||
|
||||
worksheet.Cells[rowIndex + 4, colIndex + 1].Value = property.GetValue(rowData);
|
||||
|
||||
}
|
||||
|
||||
string propertyName2 = "height";
|
||||
var propertyHeight = rowData.GetType().GetProperty(propertyName2);
|
||||
|
||||
if (propertyHeight == null)
|
||||
throw new ArgumentException($"Свойство {propertyHeight} не найдено в классе {propertyName2}.");
|
||||
worksheet.Row(rowIndex + 4).Height = (double)propertyHeight.GetValue(rowData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Сохранение файла
|
||||
var file = new FileInfo(filePath);
|
||||
package.SaveAs(file);
|
||||
}
|
||||
}
|
||||
|
||||
public class Person
|
||||
{
|
||||
public int ID { get; set; } // Идентификатор
|
||||
public string status { get; set; }
|
||||
public string name { get; set; }
|
||||
public string fio { get; set; }
|
||||
public int Age { get; set; }
|
||||
public string vos { get; set; }
|
||||
public string kids { get; set; }
|
||||
public string dol { get; set; }
|
||||
public string pod { get; set; }
|
||||
public int prem { get; set; }
|
||||
public int height { get; set; }
|
||||
|
||||
public Person(int height, int id, string status, string name, string fio, int Age, string vos, string kids, string dol, string pod, int prem)
|
||||
{
|
||||
this.height = height;
|
||||
this.ID = id;
|
||||
this.status = status;
|
||||
this.name = name;
|
||||
this.fio = fio;
|
||||
this.Age = Age;
|
||||
this.vos = vos;
|
||||
this.kids = kids;
|
||||
this.dol = dol;
|
||||
this.pod = pod;
|
||||
this.prem = prem;
|
||||
}
|
||||
}
|
||||
|
||||
// Метод для проверки на заполненность шапки
|
||||
private void ValidateHeaders(List<(string, string, string)> headerInfo)
|
||||
{
|
||||
foreach (var header in headerInfo)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(header.Item1) || string.IsNullOrWhiteSpace(header.Item2))
|
||||
{
|
||||
throw new ArgumentException("Все ячейки шапки должны быть заполнены.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Метод для проверки наложения объединенных ячеек
|
||||
private void ValidateMergedCells(List<MergeInfo> mergeInfo, int headerColumnsCount)
|
||||
{
|
||||
foreach (var merge in mergeInfo)
|
||||
{
|
||||
if (merge.StartColumn > headerColumnsCount || merge.EndColumn > headerColumnsCount)
|
||||
{
|
||||
throw new ArgumentException("Объединенные ячейки выходят за пределы шапки.");
|
||||
}
|
||||
|
||||
// Дополнительные проверки можно добавить здесь
|
||||
}
|
||||
|
||||
// Проверка на наложение объединенных ячеек
|
||||
for (int i = 0; i < mergeInfo.Count; i++)
|
||||
{
|
||||
var currentMerge = mergeInfo[i];
|
||||
|
||||
for (int j = i + 1; j < mergeInfo.Count; j++)
|
||||
{
|
||||
var otherMerge = mergeInfo[j];
|
||||
|
||||
// Проверка пересечения по строкам и столбцам
|
||||
bool isOverlapping =
|
||||
currentMerge.StartRow <= otherMerge.EndRow && currentMerge.EndRow >= otherMerge.StartRow &&
|
||||
currentMerge.StartColumn <= otherMerge.EndColumn && currentMerge.EndColumn >= otherMerge.StartColumn;
|
||||
|
||||
if (isOverlapping)
|
||||
{
|
||||
throw new ArgumentException($"Объединенные ячейки пересекаются: [{currentMerge.StartRow},{currentMerge.StartColumn}] - [{currentMerge.EndRow},{currentMerge.EndColumn}] и [{otherMerge.StartRow},{otherMerge.StartColumn}] - [{otherMerge.EndRow},{otherMerge.EndColumn}].");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Класс для информации об объединении ячеек
|
||||
public class MergeInfo
|
||||
{
|
||||
public int StartRow { get; set; }
|
||||
public int StartColumn { get; set; }
|
||||
public int EndRow { get; set; }
|
||||
public int EndColumn { get; set; }
|
||||
|
||||
public MergeInfo(int startRow, int startColumn, int endRow, int endColumn)
|
||||
{
|
||||
StartRow = startRow;
|
||||
StartColumn = startColumn;
|
||||
EndRow = endRow;
|
||||
EndColumn = endColumn;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
36
WinFormsApp1/WinFormsLibrary1/PieChart.Designer.cs
generated
Normal file
36
WinFormsApp1/WinFormsLibrary1/PieChart.Designer.cs
generated
Normal file
@ -0,0 +1,36 @@
|
||||
namespace WinFormsLibrary1
|
||||
{
|
||||
partial class PieChart
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
111
WinFormsApp1/WinFormsLibrary1/PieChart.cs
Normal file
111
WinFormsApp1/WinFormsLibrary1/PieChart.cs
Normal file
@ -0,0 +1,111 @@
|
||||
using System.ComponentModel;
|
||||
using OfficeOpenXml;
|
||||
using OfficeOpenXml.Drawing.Chart;
|
||||
|
||||
|
||||
namespace WinFormsLibrary1
|
||||
{
|
||||
public partial class PieChart : Component
|
||||
{
|
||||
public PieChart()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public PieChart(IContainer container)
|
||||
{
|
||||
container.Add(this);
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
// Публичный метод для создания Excel-документа с круговой диаграммой
|
||||
public void CreateExcelWithPieChart(string filePath, string documentTitle,
|
||||
string chartTitle, LegendPosition legendPosition, List<PieChartData> chartData)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath) || string.IsNullOrEmpty(documentTitle) || string.IsNullOrEmpty(chartTitle) || chartData == null || chartData.Count == 0)
|
||||
{
|
||||
throw new ArgumentException("Все входные данные должны быть заполнены.");
|
||||
}
|
||||
|
||||
using (var package = new ExcelPackage())
|
||||
{
|
||||
var worksheet = package.Workbook.Worksheets.Add("ChartSheet");
|
||||
|
||||
// Устанавливаем заголовок документа
|
||||
worksheet.Cells[1, 1].Value = documentTitle;
|
||||
worksheet.Cells[1, 1, 1, 2].Merge = true;
|
||||
worksheet.Cells[1, 1].Style.Font.Size = 16;
|
||||
worksheet.Cells[1, 1].Style.Font.Bold = true;
|
||||
|
||||
// Записываем данные для диаграммы в ячейки
|
||||
int row = 3;
|
||||
worksheet.Cells[row, 1].Value = "Series";
|
||||
worksheet.Cells[row, 2].Value = "Value";
|
||||
|
||||
foreach (var data in chartData)
|
||||
{
|
||||
row++;
|
||||
worksheet.Cells[row, 1].Value = data.SeriesName;
|
||||
worksheet.Cells[row, 2].Value = data.Value;
|
||||
}
|
||||
|
||||
// Создаем круговую диаграмму
|
||||
var pieChart = worksheet.Drawings.AddChart(chartTitle, eChartType.Pie) as ExcelPieChart;
|
||||
|
||||
// Устанавливаем диапазоны данных для диаграммы
|
||||
pieChart.Series.Add(worksheet.Cells[4, 2, row, 2], worksheet.Cells[4, 1, row, 1]);
|
||||
|
||||
// Заголовок диаграммы
|
||||
pieChart.Title.Text = chartTitle;
|
||||
|
||||
// Установка положения легенды
|
||||
switch (legendPosition)
|
||||
{
|
||||
case LegendPosition.Top:
|
||||
pieChart.Legend.Position = eLegendPosition.Top;
|
||||
break;
|
||||
case LegendPosition.Bottom:
|
||||
pieChart.Legend.Position = eLegendPosition.Bottom;
|
||||
break;
|
||||
case LegendPosition.Left:
|
||||
pieChart.Legend.Position = eLegendPosition.Left;
|
||||
break;
|
||||
case LegendPosition.Right:
|
||||
pieChart.Legend.Position = eLegendPosition.Right;
|
||||
break;
|
||||
case LegendPosition.None:
|
||||
pieChart.Legend.Remove();
|
||||
break;
|
||||
}
|
||||
|
||||
// Сохранение файла
|
||||
var file = new FileInfo(filePath);
|
||||
package.SaveAs(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PieChartData
|
||||
{
|
||||
public string SeriesName { get; set; } // Название серии
|
||||
public double Value { get; set; } // Значение
|
||||
|
||||
public PieChartData(string seriesName, double value)
|
||||
{
|
||||
SeriesName = seriesName ?? throw new ArgumentNullException(nameof(seriesName));
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Перечисление для позиции легенды
|
||||
public enum LegendPosition
|
||||
{
|
||||
Top,
|
||||
Bottom,
|
||||
Left,
|
||||
Right,
|
||||
None
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user