From 0c01e4561a53c5e646c0cf7d635a33dfde00d5f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20=D0=9F=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D0=BF=D0=BE=D0=B2?= Date: Wed, 23 Oct 2024 17:56:27 +0400 Subject: [PATCH] =?UTF-8?q?=D0=93=D0=BE=D1=82=D0=BE=D0=B2=D0=B0=D1=8F=20?= =?UTF-8?q?=D0=B2=D1=82=D0=BE=D1=80=D0=B0=D1=8F=20=D0=BB=D0=B0=D0=B1=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...nentExcelTableWithColumnHeader.Designer.cs | 36 +++++ .../ComponentExcelTableWithColumnHeader.cs | 115 +++++++++++++++ .../WinFormsApp/FormNoVisual.Designer.cs | 138 +++++++++++++++++- WinFormSolution/WinFormsApp/FormNoVisual.cs | 77 ++++++++++ WinFormSolution/WinFormsApp/FormNoVisual.resx | 3 + WinFormSolution/WinFormsApp/TableEmployee.cs | 32 ++++ 6 files changed, 400 insertions(+), 1 deletion(-) create mode 100644 WinFormSolution/Components/ComponentExcelTableWithColumnHeader.Designer.cs create mode 100644 WinFormSolution/Components/ComponentExcelTableWithColumnHeader.cs create mode 100644 WinFormSolution/WinFormsApp/TableEmployee.cs diff --git a/WinFormSolution/Components/ComponentExcelTableWithColumnHeader.Designer.cs b/WinFormSolution/Components/ComponentExcelTableWithColumnHeader.Designer.cs new file mode 100644 index 0000000..372d63c --- /dev/null +++ b/WinFormSolution/Components/ComponentExcelTableWithColumnHeader.Designer.cs @@ -0,0 +1,36 @@ +namespace Components +{ + partial class ComponentExcelTableWithColumnHeader + { + /// + /// Обязательная переменная конструктора. + /// + 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/WinFormSolution/Components/ComponentExcelTableWithColumnHeader.cs b/WinFormSolution/Components/ComponentExcelTableWithColumnHeader.cs new file mode 100644 index 0000000..6f0e767 --- /dev/null +++ b/WinFormSolution/Components/ComponentExcelTableWithColumnHeader.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Reflection; +using System.Runtime.InteropServices; +using Excel = Microsoft.Office.Interop.Excel; + +namespace Components +{ + public partial class ComponentExcelTableWithColumnHeader : Component + { + public ComponentExcelTableWithColumnHeader() + { + InitializeComponent(); + } + + public ComponentExcelTableWithColumnHeader(IContainer container) : this() + { + container.Add(this); + } + + public void GenerateExcelFile( + string filePath, + string documentTitle, + List<(int StartRow, int EndRow, int StartCol, int EndCol, string title)> mergeCellsInfo, + List tableData, + List<(string title, string propertyName, float height)> headersConfig) + { + if (string.IsNullOrEmpty(filePath) || headersConfig == null) + { + throw new ArgumentException("Все входные данные должны быть заполнены."); + } + + Excel.Application excelApp = new Excel.Application(); + excelApp.Visible = false; + Excel.Workbook workbook = excelApp.Workbooks.Add(); + Excel.Worksheet worksheet = (Excel.Worksheet)workbook.Sheets[1]; + + worksheet.Cells[1, 1].Value = documentTitle; + worksheet.Range[worksheet.Cells[1, 1], worksheet.Cells[1, tableData.Count + 2]].Merge(); + worksheet.Cells[1, 1].HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter; + + for (int i = 0; i < headersConfig.Count; i++) + { + worksheet.Cells[2 + i, 2].Value = headersConfig[i].title; + worksheet.Cells[2 + i, 2].Font.Bold = true; + worksheet.Rows[i + 1].RowHeight = headersConfig[i].height; + } + + for (int colIndex = 0; colIndex < tableData.Count; colIndex++) + { + var data = tableData[colIndex]; + + for (int rowIndex = 0; rowIndex < headersConfig.Count; rowIndex++) + { + var property = data.GetType().GetProperty(headersConfig[rowIndex].propertyName); + if (property != null) + { + worksheet.Cells[rowIndex + 2, colIndex + 3].Value = property.GetValue(data); + } + } + } + + List rows = new List(); + foreach (var mergeInfo in mergeCellsInfo) + { + ValidateMergeCells(mergeCellsInfo); + worksheet.Range[worksheet.Cells[mergeInfo.StartRow + 1, mergeInfo.StartCol], + worksheet.Cells[mergeInfo.EndRow + 1, mergeInfo.EndCol]].Merge(); + worksheet.Cells[mergeInfo.StartRow + 1, mergeInfo.StartCol].Value = mergeInfo.title; + for (int r = mergeInfo.StartRow + 1; r <= mergeInfo.EndRow + 1; r++) + { + rows.Add(r); + } + } + + for (int i = 2; i < headersConfig.Count + 2; i++) + { + if (!rows.Contains(i)) + { + worksheet.Range[worksheet.Cells[i, 1], worksheet.Cells[i, 2]].Merge(); + } + } + + workbook.SaveAs(filePath); + workbook.Close(); + Marshal.ReleaseComObject(workbook); + excelApp.Quit(); + Marshal.ReleaseComObject(excelApp); + } + + private void ValidateMergeCells(List<(int StartRow, int EndRow, int StartCol, int EndCol, string title)> mergeCellsInfo) + { + for (int i = 0; i < mergeCellsInfo.Count; i++) + { + for (int j = i + 1; j < mergeCellsInfo.Count; j++) + { + if (CellsOverlap(mergeCellsInfo[i], mergeCellsInfo[j])) + { + throw new InvalidOperationException("Объединенные ячейки пересекаются."); + } + } + } + } + + private bool CellsOverlap( + (int StartRow, int EndRow, int StartCol, int EndCol, string title) range1, + (int StartRow, int EndRow, int StartCol, int EndCol, string title) range2) + { + bool rowsOverlap = range1.StartRow <= range2.EndRow && range1.EndRow >= range2.StartRow; + bool colsOverlap = range1.StartCol <= range2.EndCol && range1.EndCol >= range2.StartCol; + return rowsOverlap && colsOverlap; + } + } +} \ No newline at end of file diff --git a/WinFormSolution/WinFormsApp/FormNoVisual.Designer.cs b/WinFormSolution/WinFormsApp/FormNoVisual.Designer.cs index ff1a77d..b1e71a2 100644 --- a/WinFormSolution/WinFormsApp/FormNoVisual.Designer.cs +++ b/WinFormSolution/WinFormsApp/FormNoVisual.Designer.cs @@ -47,8 +47,22 @@ comboBoxLegendPosition = new ComboBox(); labelLegendPosition = new Label(); textBoxDiagramTitle = new TextBox(); + componentExcelTableWithColumnHeader = new Components.ComponentExcelTableWithColumnHeader(components); + dataGridViewEmployees = new DataGridView(); + textBoxSurname = new TextBox(); + textBoxName = new TextBox(); + numericUpDownAge = new NumericUpDown(); + label1 = new Label(); + textBoxWorkPlace = new TextBox(); + textBoxPost = new TextBox(); + textBoxSalary = new TextBox(); + buttonAddEmployee = new Button(); + buttonClearEmployes = new Button(); + buttonGenerateExcelWithTable = new Button(); ((System.ComponentModel.ISupportInitialize)dataGridViewSeries).BeginInit(); ((System.ComponentModel.ISupportInitialize)numericUpDownSeriesValue).BeginInit(); + ((System.ComponentModel.ISupportInitialize)dataGridViewEmployees).BeginInit(); + ((System.ComponentModel.ISupportInitialize)numericUpDownAge).BeginInit(); SuspendLayout(); // // textBoxFilePath @@ -204,11 +218,119 @@ textBoxDiagramTitle.Size = new Size(300, 27); textBoxDiagramTitle.TabIndex = 15; // + // dataGridViewEmployees + // + dataGridViewEmployees.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + dataGridViewEmployees.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; + dataGridViewEmployees.Location = new Point(779, 12); + dataGridViewEmployees.Name = "dataGridViewEmployees"; + dataGridViewEmployees.RowHeadersVisible = false; + dataGridViewEmployees.RowHeadersWidth = 51; + dataGridViewEmployees.Size = new Size(619, 201); + dataGridViewEmployees.TabIndex = 16; + // + // textBoxSurname + // + textBoxSurname.Location = new Point(782, 219); + textBoxSurname.Name = "textBoxSurname"; + textBoxSurname.PlaceholderText = "Фамилия"; + textBoxSurname.Size = new Size(164, 27); + textBoxSurname.TabIndex = 17; + // + // textBoxName + // + textBoxName.Location = new Point(782, 256); + textBoxName.Name = "textBoxName"; + textBoxName.PlaceholderText = "Имя"; + textBoxName.Size = new Size(164, 27); + textBoxName.TabIndex = 18; + // + // numericUpDownAge + // + numericUpDownAge.Location = new Point(858, 292); + numericUpDownAge.Name = "numericUpDownAge"; + numericUpDownAge.Size = new Size(88, 27); + numericUpDownAge.TabIndex = 19; + // + // label1 + // + label1.AutoSize = true; + label1.Location = new Point(782, 294); + label1.Name = "label1"; + label1.Size = new Size(64, 20); + label1.TabIndex = 20; + label1.Text = "Возраст"; + // + // textBoxWorkPlace + // + textBoxWorkPlace.Location = new Point(980, 219); + textBoxWorkPlace.Name = "textBoxWorkPlace"; + textBoxWorkPlace.PlaceholderText = "Место работы"; + textBoxWorkPlace.Size = new Size(164, 27); + textBoxWorkPlace.TabIndex = 21; + // + // textBoxPost + // + textBoxPost.Location = new Point(980, 256); + textBoxPost.Name = "textBoxPost"; + textBoxPost.PlaceholderText = "Должность"; + textBoxPost.Size = new Size(164, 27); + textBoxPost.TabIndex = 22; + // + // textBoxSalary + // + textBoxSalary.Location = new Point(980, 292); + textBoxSalary.Name = "textBoxSalary"; + textBoxSalary.PlaceholderText = "Зарплата"; + textBoxSalary.Size = new Size(164, 27); + textBoxSalary.TabIndex = 23; + // + // buttonAddEmployee + // + buttonAddEmployee.Location = new Point(1150, 219); + buttonAddEmployee.Name = "buttonAddEmployee"; + buttonAddEmployee.Size = new Size(94, 29); + buttonAddEmployee.TabIndex = 24; + buttonAddEmployee.Text = "Добавить"; + buttonAddEmployee.UseVisualStyleBackColor = true; + buttonAddEmployee.Click += buttonAddEmployee_Click; + // + // buttonClearEmployes + // + buttonClearEmployes.Location = new Point(1250, 219); + buttonClearEmployes.Name = "buttonClearEmployes"; + buttonClearEmployes.Size = new Size(94, 29); + buttonClearEmployes.TabIndex = 25; + buttonClearEmployes.Text = "Очистить"; + buttonClearEmployes.UseVisualStyleBackColor = true; + buttonClearEmployes.Click += buttonClearEmployes_Click; + // + // buttonGenerateExcelWithTable + // + buttonGenerateExcelWithTable.Location = new Point(1149, 256); + buttonGenerateExcelWithTable.Name = "buttonGenerateExcelWithTable"; + buttonGenerateExcelWithTable.Size = new Size(195, 29); + buttonGenerateExcelWithTable.TabIndex = 26; + buttonGenerateExcelWithTable.Text = "Сгенерировать"; + buttonGenerateExcelWithTable.UseVisualStyleBackColor = true; + buttonGenerateExcelWithTable.Click += buttonGenerateExcelWithTable_Click; + // // FormNoVisual // AutoScaleDimensions = new SizeF(8F, 20F); AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(1054, 446); + ClientSize = new Size(1410, 446); + Controls.Add(buttonGenerateExcelWithTable); + Controls.Add(buttonClearEmployes); + Controls.Add(buttonAddEmployee); + Controls.Add(textBoxSalary); + Controls.Add(textBoxPost); + Controls.Add(textBoxWorkPlace); + Controls.Add(label1); + Controls.Add(numericUpDownAge); + Controls.Add(textBoxName); + Controls.Add(textBoxSurname); + Controls.Add(dataGridViewEmployees); Controls.Add(textBoxDiagramTitle); Controls.Add(labelLegendPosition); Controls.Add(comboBoxLegendPosition); @@ -229,6 +351,8 @@ Text = "FormNoVisual"; ((System.ComponentModel.ISupportInitialize)dataGridViewSeries).EndInit(); ((System.ComponentModel.ISupportInitialize)numericUpDownSeriesValue).EndInit(); + ((System.ComponentModel.ISupportInitialize)dataGridViewEmployees).EndInit(); + ((System.ComponentModel.ISupportInitialize)numericUpDownAge).EndInit(); ResumeLayout(false); PerformLayout(); } @@ -253,5 +377,17 @@ private ComboBox comboBoxLegendPosition; private Label labelLegendPosition; private TextBox textBoxDiagramTitle; + private Components.ComponentExcelTableWithColumnHeader componentExcelTableWithColumnHeader; + private DataGridView dataGridViewEmployees; + private TextBox textBoxSurname; + private TextBox textBoxName; + private NumericUpDown numericUpDownAge; + private Label label1; + private TextBox textBoxWorkPlace; + private TextBox textBoxPost; + private TextBox textBoxSalary; + private Button buttonAddEmployee; + private Button buttonClearEmployes; + private Button buttonGenerateExcelWithTable; } } \ No newline at end of file diff --git a/WinFormSolution/WinFormsApp/FormNoVisual.cs b/WinFormSolution/WinFormsApp/FormNoVisual.cs index 235dbdf..e2ab297 100644 --- a/WinFormSolution/WinFormsApp/FormNoVisual.cs +++ b/WinFormSolution/WinFormsApp/FormNoVisual.cs @@ -1,4 +1,5 @@ using Components; +using System.Collections.Generic; using static System.Windows.Forms.VisualStyles.VisualStyleElement; using LegendPosition = Components.ComponentExcelWithPieDiagram.LegendPosition; @@ -7,6 +8,15 @@ namespace WinFormsApp public partial class FormNoVisual : Form { private List _chartData; + private class TestData + { + public string Name { get; set; } + public int Age { get; set; } + public string City { get; set; } + } + + private List _employees = new List(); + private double _chartDataValuesSum { get @@ -143,5 +153,72 @@ namespace WinFormsApp numericUpDownSeriesValue.Maximum = (decimal)(100 - _chartDataValuesSum); numericUpDownSeriesValue.Value = numericUpDownSeriesValue.Maximum; } + + private void buttonAddEmployee_Click(object sender, EventArgs e) + { + double salary; + if (double.TryParse(textBoxSalary.Text.Replace(".", ","), out salary)) + { + _employees.Add(new TableEmployee( + _employees.Count, + textBoxName.Text, + textBoxSurname.Text, + (int)numericUpDownAge.Value, + textBoxWorkPlace.Text, + textBoxPost.Text, + salary + )); + + UpdateTableEmployees(); + } + } + + private void buttonClearEmployes_Click(object sender, EventArgs e) + { + _employees.Clear(); + UpdateTableEmployees(); + } + + private void buttonGenerateExcelWithTable_Click(object sender, EventArgs e) + { + List<(int StartRow, int EndRow, int StartCol, int EndCol, string title)> mergeCellsInfo = new List<(int StartRow, int EndRow, int StartCol, int EndCol, string title)> + { + (2, 3, 1, 1, "Личные данные"), + (5, 6, 1, 1, "Работа") + }; + + List<(string title, string propertyName, float height)> headersConfig = new List<(string title, string propertyName, float height)> + { + ("ID", "ID", 20), + ("Фамилия", "SurName", 20), + ("Имя", "Name", 20), + ("Возраст", "Age", 20), + ("Место работы", "WorkPlace", 40), + ("Должность", "WorkPost", 40), + ("Зарплата", "Salary", 30) + }; + + try + { + componentExcelTableWithColumnHeader.GenerateExcelFile( + textBoxFilePath.Text, + textBoxTitle.Text, + mergeCellsInfo, + _employees, + headersConfig + ); + MessageBox.Show("Файл успешно создан", "Результат", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + catch (Exception ex) + { + MessageBox.Show($"Ошибка при создании файла:\n{ex.Message}", "Результат", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void UpdateTableEmployees() + { + dataGridViewEmployees.DataSource = null; + dataGridViewEmployees.DataSource = _employees; + } } } diff --git a/WinFormSolution/WinFormsApp/FormNoVisual.resx b/WinFormSolution/WinFormsApp/FormNoVisual.resx index 7407882..9b72422 100644 --- a/WinFormSolution/WinFormsApp/FormNoVisual.resx +++ b/WinFormSolution/WinFormsApp/FormNoVisual.resx @@ -123,4 +123,7 @@ 256, 17 + + 531, 17 + \ No newline at end of file diff --git a/WinFormSolution/WinFormsApp/TableEmployee.cs b/WinFormSolution/WinFormsApp/TableEmployee.cs new file mode 100644 index 0000000..2ceb498 --- /dev/null +++ b/WinFormSolution/WinFormsApp/TableEmployee.cs @@ -0,0 +1,32 @@ +using System.ComponentModel; + +namespace WinFormsApp +{ + public class TableEmployee + { + [DisplayName("ID")] + public int ID { get; set; } + [DisplayName("Имя")] + public string Name { get; set; } + [DisplayName("Фамилия")] + public string SurName { get; set; } + [DisplayName("Возраст")] + public int Age { get; set; } + [DisplayName("Место работы")] + public string WorkPlace { get; set; } + [DisplayName("Должность")] + public string WorkPost { get; set; } + [DisplayName("Зарплата")] + public double Salary { get; set; } + public TableEmployee(int id, string name, string surname, int age, string workPlace, string workPost, double salary) + { + ID = id; + Name = name; + SurName = surname; + Age = age; + WorkPlace = workPlace; + WorkPost = workPost; + Salary = salary; + } + } +}