diff --git a/AbazovApp/AbazovAppView/FormTest.Designer.cs b/AbazovApp/AbazovAppView/FormTest.Designer.cs index 1bbe141..9e6cdf4 100644 --- a/AbazovApp/AbazovAppView/FormTest.Designer.cs +++ b/AbazovApp/AbazovAppView/FormTest.Designer.cs @@ -46,6 +46,8 @@ this.excelImagesComponent = new AbazovViewComponents.LogicalComponents.ExcelImagesComponent(this.components); this.buttonExcelImages = new System.Windows.Forms.Button(); this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); + this.buttonExcelTable = new System.Windows.Forms.Button(); + this.excelTableComponent = new AbazovViewComponents.LogicalComponents.ExcelTableComponent(this.components); this.SuspendLayout(); // // abazovCheckedListBox @@ -203,11 +205,22 @@ this.openFileDialog.Multiselect = true; this.openFileDialog.Title = "Выберте изображения"; // + // buttonExcelTable + // + this.buttonExcelTable.Location = new System.Drawing.Point(168, 327); + this.buttonExcelTable.Name = "buttonExcelTable"; + this.buttonExcelTable.Size = new System.Drawing.Size(128, 29); + this.buttonExcelTable.TabIndex = 15; + this.buttonExcelTable.Text = "Excel (Таблица)"; + this.buttonExcelTable.UseVisualStyleBackColor = true; + this.buttonExcelTable.Click += new System.EventHandler(this.buttonExcelTable_Click); + // // FormTest // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(850, 450); + this.Controls.Add(this.buttonExcelTable); this.Controls.Add(this.buttonExcelImages); this.Controls.Add(this.buttonSetIndex); this.Controls.Add(this.buttonGetIndex); @@ -248,5 +261,7 @@ private AbazovViewComponents.LogicalComponents.ExcelImagesComponent excelImagesComponent; private Button buttonExcelImages; private OpenFileDialog openFileDialog; + private Button buttonExcelTable; + private AbazovViewComponents.LogicalComponents.ExcelTableComponent excelTableComponent; } } \ No newline at end of file diff --git a/AbazovApp/AbazovAppView/FormTest.cs b/AbazovApp/AbazovAppView/FormTest.cs index d95fefc..8fd050c 100644 --- a/AbazovApp/AbazovAppView/FormTest.cs +++ b/AbazovApp/AbazovAppView/FormTest.cs @@ -142,5 +142,28 @@ namespace AbazovAppView if (excelImagesComponent.createWithImages(new ExcelImageInfo(path, "Header", files))) MessageBox.Show("Успех!"); else MessageBox.Show("Ошибка, проверьте консоль"); } + + private void buttonExcelTable_Click(object sender, EventArgs e) + { + List workers = new List(); + + workers.Add(new OfficeWorker(1, "Иванов", "Иван", 20, "Отдел продаж", "Бухгалтер", 25, "+7(834)234-03-49")); + workers.Add(new OfficeWorker(1, "Петров", "Петр", 25, "Отдел продаж", "Менеджер", 20, "+7(834)123-03-49")); + workers.Add(new OfficeWorker(1, "Сидоров", "Сергей", 27, "Отдел кадров", "HR", 2, "+7(834)593-03-49", true)); + string path = AppDomain.CurrentDomain.BaseDirectory + "test.xlsx"; + List<(int, int)> merges = new List<(int, int)>(); + merges.Add((1, 3)); + merges.Add((4, 6)); + List heights = Enumerable.Repeat(20, 9).ToList(); + + List<(string, string)> headers = new List<(string, string)> { ("id", "id"), ("", "Личные данные"), + ("lastName", "Фамилия"), ("firstName", "Имя"), + ("age", "Возраст"), ("", "Работа"), + ("department", "Отдел"), ("position", "Должность"), + ("boxNumber", "Номер бокса"), ("phoneNumber", "Телефон"), + ("isInVacation", "В отпуске"), }; + + if (excelTableComponent.createWithTable(path, "test", merges, heights, headers, workers)) MessageBox.Show("Успех"); + } } } diff --git a/AbazovApp/AbazovAppView/FormTest.resx b/AbazovApp/AbazovAppView/FormTest.resx index 97e2fb7..7bad74a 100644 --- a/AbazovApp/AbazovAppView/FormTest.resx +++ b/AbazovApp/AbazovAppView/FormTest.resx @@ -63,4 +63,7 @@ 233, 17 + + 392, 17 + \ No newline at end of file diff --git a/AbazovApp/AbazovAppView/OfficeWorker.cs b/AbazovApp/AbazovAppView/OfficeWorker.cs new file mode 100644 index 0000000..bde9ddc --- /dev/null +++ b/AbazovApp/AbazovAppView/OfficeWorker.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AbazovAppView +{ + public class OfficeWorker + { + public OfficeWorker(int id, string lastName, string firstName, int age, string department, string position, int boxNumber, string phoneNumber, bool isInVacation = false) + { + this.id = id; + this.lastName = lastName; + this.firstName = firstName; + this.age = age; + this.department = department; + this.position = position; + this.boxNumber = boxNumber; + this.phoneNumber = phoneNumber; + this.isInVacation = isInVacation; + } + + public int id; + public string lastName; + public string firstName; + public int age; + public string department; + public string position; + public int boxNumber; + public string phoneNumber; + public bool isInVacation; + } +} diff --git a/AbazovApp/AbazovViewComponents/LogicalComponents/ExcelTableComponent.Designer.cs b/AbazovApp/AbazovViewComponents/LogicalComponents/ExcelTableComponent.Designer.cs new file mode 100644 index 0000000..a48276d --- /dev/null +++ b/AbazovApp/AbazovViewComponents/LogicalComponents/ExcelTableComponent.Designer.cs @@ -0,0 +1,36 @@ +namespace AbazovViewComponents.LogicalComponents +{ + partial class ExcelTableComponent + { + /// + /// Обязательная переменная конструктора. + /// + 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/AbazovApp/AbazovViewComponents/LogicalComponents/ExcelTableComponent.cs b/AbazovApp/AbazovViewComponents/LogicalComponents/ExcelTableComponent.cs new file mode 100644 index 0000000..feff2da --- /dev/null +++ b/AbazovApp/AbazovViewComponents/LogicalComponents/ExcelTableComponent.cs @@ -0,0 +1,194 @@ +using Microsoft.Office.Core; +using Microsoft.Office.Interop.Excel; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data.Common; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace AbazovViewComponents.LogicalComponents +{ + public partial class ExcelTableComponent : Component + { + public ExcelTableComponent() + { + InitializeComponent(); + } + + public ExcelTableComponent(IContainer container) + { + container.Add(this); + + InitializeComponent(); + } + + private string GetExcelColumnName(int columnNumber) + { + string columnName = ""; + + while (columnNumber > 0) + { + int modulo = (columnNumber - 1) % 26; + columnName = Convert.ToChar('A' + modulo) + columnName; + columnNumber = (columnNumber - modulo) / 26; + } + + return columnName; + } + + public bool createWithTable(string path, string title, List<(int, int)> merges, List heights, List<(string, string)> headers, List items) + { + if (merges.Count == 0 || heights.Count == 0 || headers.Count == 0 || items.Count == 0) throw new ArgumentException("Недостаточно данных"); + int[] cellsArray = new int[heights.Count]; + foreach (var merge in merges) + { + if (merge.Item1 >= merge.Item2) throw new ArgumentException("Неправильно заполнены объединения строк"); + for (int i = merge.Item1; i < merge.Item2; i++) + { + cellsArray[i]++; + } + } + foreach (int cell in cellsArray) + { + if (cell > 1) throw new ArgumentException("Объединения заходят друг на друга"); + } + + var excelApp = new Microsoft.Office.Interop.Excel.Application { SheetsInNewWorkbook = 1 }; + Workbook workbook = excelApp.Workbooks.Add(Type.Missing); + try + { + //create + Worksheet worksheet = (Worksheet)workbook.Worksheets.get_Item(1); + + //header + var excelcells = worksheet.get_Range("A1", "A1"); + excelcells.Font.Bold = true; + excelcells.Font.Size = 14; + excelcells.Font.Name = "Times New Roman"; + excelcells.ColumnWidth = 8; + excelcells.RowHeight = 25; + excelcells.HorizontalAlignment = Constants.xlCenter; + excelcells.VerticalAlignment = Constants.xlCenter; + excelcells.Value2 = title; + + //checks + List ranges = new List(); + foreach (var merge in merges) + { + ranges.Add(worksheet.get_Range("A" + (merge.Item1 + 2), "A" + (merge.Item2 + 2))); + } + + int rangeIndex = 0; + int headerIndex = 0; + List cellFields = new List(); + var type = typeof(T); + for (int i = 0; i < heights.Count; i++) + { + if (cellsArray[i] == 1) + { + //work with merge + if (!string.IsNullOrEmpty(headers[headerIndex].Item1)) throw new ArgumentException("Заголовки и объединения строк не совпадают"); + + var groupRange = ranges[rangeIndex]; + groupRange.Merge(Type.Missing); + groupRange.Font.Bold = true; + groupRange.Font.Size = 14; + groupRange.Font.Name = "Times New Roman"; + groupRange.ColumnWidth = 20; + groupRange.HorizontalAlignment = Constants.xlCenter; + groupRange.VerticalAlignment = Constants.xlCenter; + groupRange.Value2 = headers[headerIndex].Item2; + headerIndex++; + + //work with cells in merge + for (; i <= merges[rangeIndex].Item2; i++) + { + //work with cell + if (string.IsNullOrEmpty(headers[headerIndex].Item1)) throw new ArgumentException("Заголовки и объединения строк не совпадают"); + var field = type.GetField(headers[headerIndex].Item1); + if (field == null) throw new ArgumentException("В заголовках указано поле, которого нет в переданном классе"); + //format header + var range = worksheet.get_Range("B" + (i + 2), "B" + (i + 2)); + range.Font.Bold = true; + range.Font.Size = 14; + range.Font.Name = "Times New Roman"; + range.ColumnWidth = 20; + range.RowHeight = heights[i]; + range.HorizontalAlignment = Constants.xlCenter; + range.VerticalAlignment = Constants.xlCenter; + range.Value2 = headers[headerIndex].Item2; + + cellFields.Add(field); + headerIndex++; + } + i--; + rangeIndex++; + } + else + { + //work with cell + if (string.IsNullOrEmpty(headers[headerIndex].Item1)) throw new ArgumentException("Заголовки и объединения строк не совпадают"); + var field = type.GetField(headers[headerIndex].Item1); + if (field == null) throw new ArgumentException("В заголовках указано поле, которого нет в переданном классе"); + //format header + var range = worksheet.get_Range("A" + (i + 2), "B" + (i + 2)); + range.Merge(Type.Missing); + range.Font.Bold = true; + range.Font.Size = 14; + range.Font.Name = "Times New Roman"; + range.ColumnWidth = 40; + range.RowHeight = heights[i]; + range.HorizontalAlignment = Constants.xlCenter; + range.VerticalAlignment = Constants.xlCenter; + range.Value2 = headers[headerIndex].Item2; + + cellFields.Add(field); + headerIndex++; + } + } + + int columnNum = 3; + foreach (T item in items) + { + string column = GetExcelColumnName(columnNum); + int rowNum = 2; + foreach (var cellField in cellFields) + { + var range = worksheet.get_Range(column + rowNum, column + rowNum); + range.Font.Size = 14; + range.Font.Name = "Times New Roman"; + range.ColumnWidth = 20; + range.HorizontalAlignment = Constants.xlCenter; + range.VerticalAlignment = Constants.xlCenter; + range.Value2 = cellField.FieldType == typeof(bool) ? ((bool) cellField.GetValue(item) ? "Да" : "Нет") : cellField.GetValue(item); + + rowNum++; + } + columnNum++; + } + var borderRange = worksheet.get_Range("A2", GetExcelColumnName(columnNum-1) + (headerIndex - 1)); + borderRange.Borders.LineStyle = XlLineStyle.xlContinuous; + borderRange.Borders.Weight = 2d; + + //save + object missing = System.Reflection.Missing.Value; + workbook.SaveAs(path, XlFileFormat.xlOpenXMLWorkbook, missing, missing, false, false, XlSaveAsAccessMode.xlNoChange, + XlSaveConflictResolution.xlUserResolution, true, missing, missing, missing); + workbook.Close(); + excelApp.Quit(); + + return true; + } + catch (Exception ex) + { + workbook.Close(); + excelApp.Quit(); + throw; + } + } + } +}