From 64766eabc4a570a20dd548559d24592a2691606d Mon Sep 17 00:00:00 2001 From: ksenianeva <95441235+ksenianeva@users.noreply.github.com> Date: Thu, 2 Nov 2023 23:55:44 +0400 Subject: [PATCH] Made excel diagram component --- .../LogicalComponents/DiagramLegendEnum.cs | 16 ++ .../WordDiagramComponent.Designer.cs | 36 +++++ .../LogicalComponents/WordDiagramComponent.cs | 142 ++++++++++++++++++ .../NevaevaLibrary/NevaevaLibrary.csproj | 9 ++ NevaevaLibrary/TestApp/Department.cs | 20 +++ NevaevaLibrary/TestApp/FormTest.Designer.cs | 15 ++ NevaevaLibrary/TestApp/FormTest.cs | 12 ++ NevaevaLibrary/TestApp/FormTest.resx | 3 + 8 files changed, 253 insertions(+) create mode 100644 NevaevaLibrary/NevaevaLibrary/LogicalComponents/DiagramLegendEnum.cs create mode 100644 NevaevaLibrary/NevaevaLibrary/LogicalComponents/WordDiagramComponent.Designer.cs create mode 100644 NevaevaLibrary/NevaevaLibrary/LogicalComponents/WordDiagramComponent.cs create mode 100644 NevaevaLibrary/TestApp/Department.cs diff --git a/NevaevaLibrary/NevaevaLibrary/LogicalComponents/DiagramLegendEnum.cs b/NevaevaLibrary/NevaevaLibrary/LogicalComponents/DiagramLegendEnum.cs new file mode 100644 index 0000000..90ec627 --- /dev/null +++ b/NevaevaLibrary/NevaevaLibrary/LogicalComponents/DiagramLegendEnum.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NevaevaLibrary.LogicalComponents +{ + public enum DiagramLegendEnum + { + TopLeft = 0, + TopRight = 1, + BottomRight = 2, + BottomLeft = 3, + } +} diff --git a/NevaevaLibrary/NevaevaLibrary/LogicalComponents/WordDiagramComponent.Designer.cs b/NevaevaLibrary/NevaevaLibrary/LogicalComponents/WordDiagramComponent.Designer.cs new file mode 100644 index 0000000..5960bd9 --- /dev/null +++ b/NevaevaLibrary/NevaevaLibrary/LogicalComponents/WordDiagramComponent.Designer.cs @@ -0,0 +1,36 @@ +namespace NevaevaLibrary.LogicalComponents +{ + partial class WordDiagramComponent + { + /// + /// Обязательная переменная конструктора. + /// + 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/NevaevaLibrary/NevaevaLibrary/LogicalComponents/WordDiagramComponent.cs b/NevaevaLibrary/NevaevaLibrary/LogicalComponents/WordDiagramComponent.cs new file mode 100644 index 0000000..c74e69d --- /dev/null +++ b/NevaevaLibrary/NevaevaLibrary/LogicalComponents/WordDiagramComponent.cs @@ -0,0 +1,142 @@ +using Microsoft.Office.Interop.Excel; +using Microsoft.Office.Interop.Word; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace NevaevaLibrary.LogicalComponents +{ + public partial class WordDiagramComponent : Component + { + public WordDiagramComponent() + { + InitializeComponent(); + } + + public WordDiagramComponent(IContainer container) + { + container.Add(this); + + InitializeComponent(); + } + + private object missing = System.Reflection.Missing.Value; + + 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 void createWithDiagram(string path, string title, string diagramTitle, DiagramLegendEnum diagramLegendAnchor, List data, string seriesNameField, string valueField) + { + var excelApp = new Microsoft.Office.Interop.Excel.Application { SheetsInNewWorkbook = 1 }; + Workbook workbook = excelApp.Workbooks.Add(Type.Missing); + Worksheet worksheet = (Worksheet)workbook.Worksheets.get_Item(1); + + FieldInfo? seriesName = typeof(T).GetField(seriesNameField); + FieldInfo? value = typeof(T).GetField(valueField); + if (seriesName == null || value == null) throw new ArgumentException("Переданного поля не существует"); + int offsetX = 1; + int offsetYMax = -1; + foreach (var item in data) + { + string columnChar = GetExcelColumnName(offsetX); + var cell = worksheet.get_Range(columnChar + "2", columnChar + "2"); + cell.Font.Size = 14; + cell.Font.Name = "Times New Roman"; + cell.ColumnWidth = 8; + cell.RowHeight = 25; + cell.HorizontalAlignment = Constants.xlCenter; + cell.VerticalAlignment = Constants.xlCenter; + cell.Value2 = seriesName.GetValue(item); + + int offsetY = 3; + + foreach (var val in (value.GetValue(item) as IEnumerable)) + { + cell = worksheet.get_Range(columnChar + offsetY, columnChar + offsetY); + cell.Value2 = val; + + offsetY++; + } + if (offsetY > offsetYMax) offsetYMax = offsetY; + + offsetX++; + } + + var charts = worksheet.ChartObjects() as ChartObjects; + int chartWidth = 300; + int chartHeight = 300; + var chartObject = charts.Add(250, 10, chartWidth, chartHeight); + var chart = chartObject.Chart; + var endColumn = GetExcelColumnName(offsetX - 1); + var range = worksheet.get_Range($"A2", endColumn + (offsetYMax - 1)); + chart.SetSourceData(range); + chart.ChartType = XlChartType.xlLine; + switch (diagramLegendAnchor) + { + case DiagramLegendEnum.TopLeft: + chart.Legend.Top = 0; + chart.Legend.Left = 0; + break; + case DiagramLegendEnum.TopRight: + chart.Legend.Top = 0; + chart.Legend.Left = chartWidth - chart.Legend.Width; + break; + case DiagramLegendEnum.BottomLeft: + chart.Legend.Top = chartHeight - chart.Legend.Height; + chart.Legend.Left = 0; + break; + case DiagramLegendEnum.BottomRight: + chart.Legend.Top = chartHeight - chart.Legend.Height; + chart.Legend.Left = chartWidth - chart.Legend.Width; + break; + } + chart.ChartWizard(Source: range, Title: diagramTitle); + + chart.Export(path.Substring(0, path.Length - 5) + ".jpg", "JPG", false); + + workbook.Close(SaveChanges: false); + excelApp.Quit(); + + var winword = new Microsoft.Office.Interop.Word.Application(); + var document = winword.Documents.Add(ref missing, ref missing, ref missing, ref missing); + document.PageSetup.RightMargin = 50; + document.PageSetup.LeftMargin = 50; + + var header = document.Content.Paragraphs.Add(Type.Missing); + header.Range.Text = title; + header.Format.Alignment = WdParagraphAlignment.wdAlignParagraphCenter; + header.Range.Font.Name = "Times New Roman"; + header.Range.Font.Size = 22; + header.Range.Font.Bold = 2; + header.Format.SpaceAfter = 18; + header.Range.InsertParagraphAfter(); + + document.Shapes.AddPicture(path.Substring(0, path.Length - 5) + ".jpg", Top: 200); + + document.SaveAs(path, Type.Missing, Type.Missing, Type.Missing, + Type.Missing, Type.Missing, Type.Missing, Type.Missing, + Type.Missing, Type.Missing, Type.Missing, Type.Missing, + Type.Missing, Type.Missing, Type.Missing, Type.Missing); + document.Close(ref missing, ref missing, ref missing); + document = null; + winword.Quit(ref missing, ref missing, ref missing); + } + } +} diff --git a/NevaevaLibrary/NevaevaLibrary/NevaevaLibrary.csproj b/NevaevaLibrary/NevaevaLibrary/NevaevaLibrary.csproj index 3bfe1be..c31a54e 100644 --- a/NevaevaLibrary/NevaevaLibrary/NevaevaLibrary.csproj +++ b/NevaevaLibrary/NevaevaLibrary/NevaevaLibrary.csproj @@ -26,6 +26,15 @@ false true + + tlbimp + 9 + 1 + 00020813-0000-0000-c000-000000000046 + 0 + false + true + diff --git a/NevaevaLibrary/TestApp/Department.cs b/NevaevaLibrary/TestApp/Department.cs new file mode 100644 index 0000000..cc35978 --- /dev/null +++ b/NevaevaLibrary/TestApp/Department.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TestApp +{ + public class Department + { + public string name; + public List sells; + + public Department(string name, List sells) + { + this.name = name; + this.sells = sells; + } + } +} diff --git a/NevaevaLibrary/TestApp/FormTest.Designer.cs b/NevaevaLibrary/TestApp/FormTest.Designer.cs index e5f8d35..d137799 100644 --- a/NevaevaLibrary/TestApp/FormTest.Designer.cs +++ b/NevaevaLibrary/TestApp/FormTest.Designer.cs @@ -44,6 +44,8 @@ this.openFileDialog = new System.Windows.Forms.OpenFileDialog(); this.buttonTable = new System.Windows.Forms.Button(); this.wordTableComponent = new NevaevaLibrary.LogicalComponents.WordTableComponent(this.components); + this.wordDiagramComponent = new NevaevaLibrary.LogicalComponents.WordDiagramComponent(this.components); + this.buttonDiagram = new System.Windows.Forms.Button(); this.SuspendLayout(); // // comboBoxControl @@ -166,11 +168,22 @@ this.buttonTable.UseVisualStyleBackColor = true; this.buttonTable.Click += new System.EventHandler(this.buttonTable_Click); // + // buttonDiagram + // + this.buttonDiagram.Location = new System.Drawing.Point(345, 319); + this.buttonDiagram.Name = "buttonDiagram"; + this.buttonDiagram.Size = new System.Drawing.Size(145, 29); + this.buttonDiagram.TabIndex = 12; + this.buttonDiagram.Text = "Word (диаграмма)"; + this.buttonDiagram.UseVisualStyleBackColor = true; + this.buttonDiagram.Click += new System.EventHandler(this.buttonDiagram_Click); + // // FormTest // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1109, 363); + this.Controls.Add(this.buttonDiagram); this.Controls.Add(this.buttonTable); this.Controls.Add(this.buttonWordText); this.Controls.Add(this.buttonGetSelectedList); @@ -206,5 +219,7 @@ private OpenFileDialog openFileDialog; private Button buttonTable; private NevaevaLibrary.LogicalComponents.WordTableComponent wordTableComponent; + private NevaevaLibrary.LogicalComponents.WordDiagramComponent wordDiagramComponent; + private Button buttonDiagram; } } \ No newline at end of file diff --git a/NevaevaLibrary/TestApp/FormTest.cs b/NevaevaLibrary/TestApp/FormTest.cs index 1e97309..338410b 100644 --- a/NevaevaLibrary/TestApp/FormTest.cs +++ b/NevaevaLibrary/TestApp/FormTest.cs @@ -100,5 +100,17 @@ namespace TestApp wordTableComponent.createWithTable(path, "header", merges, widths, headers, workers); MessageBox.Show("Готово!"); } + + private void buttonDiagram_Click(object sender, EventArgs e) + { + List departments = new List(); + + departments.Add(new Department("Dep 1", new List { 330, 220, 400, 500 })); + departments.Add(new Department("Dep 2", new List { 400, 300, 302 })); + departments.Add(new Department("Dep 3", new List { 200, 220, 270 })); + string path = AppDomain.CurrentDomain.BaseDirectory + "test3.docx"; + wordDiagramComponent.createWithDiagram(path, "test3", "Продажи", DiagramLegendEnum.TopRight, departments, "name", "sells"); + MessageBox.Show("Готово!"); + } } } diff --git a/NevaevaLibrary/TestApp/FormTest.resx b/NevaevaLibrary/TestApp/FormTest.resx index 65b5cbd..18b2509 100644 --- a/NevaevaLibrary/TestApp/FormTest.resx +++ b/NevaevaLibrary/TestApp/FormTest.resx @@ -66,4 +66,7 @@ 407, 17 + + 612, 17 + \ No newline at end of file