diff --git a/Lab 2/Belianin_2/Belianin_2.sln b/Lab 2/Belianin_2/Belianin_2.sln
new file mode 100644
index 0000000..b133bd4
--- /dev/null
+++ b/Lab 2/Belianin_2/Belianin_2.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.9.34728.123
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyCustomComponents", "MyCustomComponents\MyCustomComponents.csproj", "{33B0240F-25C6-4577-BE81-5381D939E230}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesktopWithMyVisualComponents", "DesktopWithMyVisualComponents\DesktopWithMyVisualComponents.csproj", "{D784BAED-C48F-46F2-A6A0-BBD6CE599A59}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {33B0240F-25C6-4577-BE81-5381D939E230}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {33B0240F-25C6-4577-BE81-5381D939E230}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {33B0240F-25C6-4577-BE81-5381D939E230}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {33B0240F-25C6-4577-BE81-5381D939E230}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D784BAED-C48F-46F2-A6A0-BBD6CE599A59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D784BAED-C48F-46F2-A6A0-BBD6CE599A59}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D784BAED-C48F-46F2-A6A0-BBD6CE599A59}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D784BAED-C48F-46F2-A6A0-BBD6CE599A59}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {26502496-F9AE-4E02-986A-76FD9595E9AE}
+ EndGlobalSection
+EndGlobal
diff --git a/Lab 2/Belianin_2/DesktopWithMyVisualComponents/DesktopWithMyVisualComponents.csproj b/Lab 2/Belianin_2/DesktopWithMyVisualComponents/DesktopWithMyVisualComponents.csproj
new file mode 100644
index 0000000..c27ce9b
--- /dev/null
+++ b/Lab 2/Belianin_2/DesktopWithMyVisualComponents/DesktopWithMyVisualComponents.csproj
@@ -0,0 +1,21 @@
+
+
+
+ WinExe
+ net6.0-windows
+ enable
+ true
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Lab 2/Belianin_2/DesktopWithMyVisualComponents/Device.cs b/Lab 2/Belianin_2/DesktopWithMyVisualComponents/Device.cs
new file mode 100644
index 0000000..5cc393b
--- /dev/null
+++ b/Lab 2/Belianin_2/DesktopWithMyVisualComponents/Device.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DesktopWithMyVisualComponents
+{
+ public class Device
+ {
+ public int Id { get; set; }
+
+ public string DeviceType { get; set; }
+
+ public string Model { get; set; }
+
+ public string SerialNumber { get; set; }
+
+ public string Owner { get; set; }
+
+ public DateTime PurchaseDate { get; set; }
+
+ public string State { get; set; }
+
+ public string Color { get; set; }
+
+ public int WarrantyPeriod { get; set; }
+
+ public int Price { get; set; }
+
+ public Device(string serialNumber, string deviceType, string model)
+ {
+ SerialNumber = serialNumber;
+ Model = model;
+ DeviceType = deviceType;
+ }
+
+ public Device() { }
+ }
+}
diff --git a/Lab 2/Belianin_2/DesktopWithMyVisualComponents/FormMain.Designer.cs b/Lab 2/Belianin_2/DesktopWithMyVisualComponents/FormMain.Designer.cs
new file mode 100644
index 0000000..6de219f
--- /dev/null
+++ b/Lab 2/Belianin_2/DesktopWithMyVisualComponents/FormMain.Designer.cs
@@ -0,0 +1,424 @@
+namespace DesktopWithMyVisualComponents
+{
+ partial class FormMain
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.customInputRangeNumber = new MyCustomComponents.CustomInputRangeNumber();
+ this.buttonCheck = new System.Windows.Forms.Button();
+ this.labelCheckValue = new System.Windows.Forms.Label();
+ this.groupBoxInput = new System.Windows.Forms.GroupBox();
+ this.groupBoxSelected = new System.Windows.Forms.GroupBox();
+ this.buttonGetSelected = new System.Windows.Forms.Button();
+ this.labelSelectedValue = new System.Windows.Forms.Label();
+ this.buttonClear = new System.Windows.Forms.Button();
+ this.buttonAdd = new System.Windows.Forms.Button();
+ this.textBoxAdd = new System.Windows.Forms.TextBox();
+ this.customSelectedCheckedListBoxProperty = new MyCustomComponents.CustomSelectedCheckedListBoxProperty();
+ this.groupBoxData = new System.Windows.Forms.GroupBox();
+ this.labelDeviceType = new System.Windows.Forms.Label();
+ this.labelModel = new System.Windows.Forms.Label();
+ this.labelRegNum = new System.Windows.Forms.Label();
+ this.buttonGetFromTree = new System.Windows.Forms.Button();
+ this.buttonAddToTree = new System.Windows.Forms.Button();
+ this.comboBoxDeviceType = new System.Windows.Forms.ComboBox();
+ this.textBoxModel = new System.Windows.Forms.TextBox();
+ this.textBoxSerialNumber = new System.Windows.Forms.TextBox();
+ this.customTreeView = new MyCustomComponents.CustomTreeView();
+ this.tabControl = new System.Windows.Forms.TabControl();
+ this.Visual = new System.Windows.Forms.TabPage();
+ this.Docs = new System.Windows.Forms.TabPage();
+ this.buttonWordWithDiagram = new System.Windows.Forms.Button();
+ this.buttonWordWithTable = new System.Windows.Forms.Button();
+ this.buttonWordWithImage = new System.Windows.Forms.Button();
+ this.wordWithImages = new MyCustomComponents.WordWithImages(this.components);
+ this.wordWithTable = new MyCustomComponents.WordWithTable(this.components);
+ this.wordWithDiagram = new MyCustomComponents.WordWithDiagram(this.components);
+ this.groupBoxInput.SuspendLayout();
+ this.groupBoxSelected.SuspendLayout();
+ this.groupBoxData.SuspendLayout();
+ this.tabControl.SuspendLayout();
+ this.Visual.SuspendLayout();
+ this.Docs.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // customInputRangeNumber
+ //
+ this.customInputRangeNumber.AutoValidate = System.Windows.Forms.AutoValidate.Disable;
+ this.customInputRangeNumber.CausesValidation = false;
+ this.customInputRangeNumber.Location = new System.Drawing.Point(34, 25);
+ this.customInputRangeNumber.Margin = new System.Windows.Forms.Padding(3, 5, 3, 5);
+ this.customInputRangeNumber.MaxValue = new decimal(new int[] { -1, -1, -1, 0});
+ this.customInputRangeNumber.MinValue = new decimal(new int[] { -1, -1, -1, -2147483648});
+ this.customInputRangeNumber.Name = "customInputRangeNumber";
+ this.customInputRangeNumber.Size = new System.Drawing.Size(144, 40);
+ this.customInputRangeNumber.TabIndex = 0;
+ this.customInputRangeNumber.Value = new decimal(new int[] { 0, 0, 0, 0});
+ //
+ // buttonCheck
+ //
+ this.buttonCheck.Location = new System.Drawing.Point(193, 29);
+ this.buttonCheck.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.buttonCheck.Name = "buttonCheck";
+ this.buttonCheck.Size = new System.Drawing.Size(144, 31);
+ this.buttonCheck.TabIndex = 1;
+ this.buttonCheck.Text = "Check";
+ this.buttonCheck.UseVisualStyleBackColor = true;
+ this.buttonCheck.Click += new System.EventHandler(this.buttonCheck_Click);
+ //
+ // labelCheckValue
+ //
+ this.labelCheckValue.AutoSize = true;
+ this.labelCheckValue.Location = new System.Drawing.Point(34, 148);
+ this.labelCheckValue.Name = "labelCheckValue";
+ this.labelCheckValue.Size = new System.Drawing.Size(82, 20);
+ this.labelCheckValue.TabIndex = 2;
+ this.labelCheckValue.Text = "Enter value";
+ //
+ // groupBoxInput
+ //
+ this.groupBoxInput.Controls.Add(this.customInputRangeNumber);
+ this.groupBoxInput.Controls.Add(this.labelCheckValue);
+ this.groupBoxInput.Controls.Add(this.buttonCheck);
+ this.groupBoxInput.Location = new System.Drawing.Point(7, 8);
+ this.groupBoxInput.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.groupBoxInput.Name = "groupBoxInput";
+ this.groupBoxInput.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.groupBoxInput.Size = new System.Drawing.Size(355, 253);
+ this.groupBoxInput.TabIndex = 9;
+ this.groupBoxInput.TabStop = false;
+ this.groupBoxInput.Text = "Input";
+ //
+ // groupBoxSelected
+ //
+ this.groupBoxSelected.Controls.Add(this.buttonGetSelected);
+ this.groupBoxSelected.Controls.Add(this.labelSelectedValue);
+ this.groupBoxSelected.Controls.Add(this.buttonClear);
+ this.groupBoxSelected.Controls.Add(this.buttonAdd);
+ this.groupBoxSelected.Controls.Add(this.textBoxAdd);
+ this.groupBoxSelected.Controls.Add(this.customSelectedCheckedListBoxProperty);
+ this.groupBoxSelected.Location = new System.Drawing.Point(370, 8);
+ this.groupBoxSelected.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.groupBoxSelected.Name = "groupBoxSelected";
+ this.groupBoxSelected.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.groupBoxSelected.Size = new System.Drawing.Size(355, 253);
+ this.groupBoxSelected.TabIndex = 10;
+ this.groupBoxSelected.TabStop = false;
+ this.groupBoxSelected.Text = "Selected";
+ //
+ // buttonGetSelected
+ //
+ this.buttonGetSelected.Location = new System.Drawing.Point(219, 192);
+ this.buttonGetSelected.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.buttonGetSelected.Name = "buttonGetSelected";
+ this.buttonGetSelected.Size = new System.Drawing.Size(114, 31);
+ this.buttonGetSelected.TabIndex = 14;
+ this.buttonGetSelected.Text = "Get Selected";
+ this.buttonGetSelected.UseVisualStyleBackColor = true;
+ this.buttonGetSelected.Click += new System.EventHandler(this.buttonGetSelected_Click);
+ //
+ // labelSelectedValue
+ //
+ this.labelSelectedValue.AutoSize = true;
+ this.labelSelectedValue.Location = new System.Drawing.Point(219, 148);
+ this.labelSelectedValue.Name = "labelSelectedValue";
+ this.labelSelectedValue.Size = new System.Drawing.Size(105, 20);
+ this.labelSelectedValue.TabIndex = 11;
+ this.labelSelectedValue.Text = "Selected value";
+ //
+ // buttonClear
+ //
+ this.buttonClear.Location = new System.Drawing.Point(219, 108);
+ this.buttonClear.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.buttonClear.Name = "buttonClear";
+ this.buttonClear.Size = new System.Drawing.Size(114, 31);
+ this.buttonClear.TabIndex = 13;
+ this.buttonClear.Text = "Clear";
+ this.buttonClear.UseVisualStyleBackColor = true;
+ this.buttonClear.Click += new System.EventHandler(this.buttonClear_Click);
+ //
+ // buttonAdd
+ //
+ this.buttonAdd.Location = new System.Drawing.Point(219, 69);
+ this.buttonAdd.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.buttonAdd.Name = "buttonAdd";
+ this.buttonAdd.Size = new System.Drawing.Size(114, 31);
+ this.buttonAdd.TabIndex = 12;
+ this.buttonAdd.Text = "Add or Select";
+ this.buttonAdd.UseVisualStyleBackColor = true;
+ this.buttonAdd.Click += new System.EventHandler(this.buttonAdd_Click);
+ //
+ // textBoxAdd
+ //
+ this.textBoxAdd.Location = new System.Drawing.Point(219, 31);
+ this.textBoxAdd.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.textBoxAdd.Name = "textBoxAdd";
+ this.textBoxAdd.Size = new System.Drawing.Size(114, 27);
+ this.textBoxAdd.TabIndex = 11;
+ //
+ // customSelectedCheckedListBoxProperty
+ //
+ this.customSelectedCheckedListBoxProperty.Location = new System.Drawing.Point(41, 25);
+ this.customSelectedCheckedListBoxProperty.Margin = new System.Windows.Forms.Padding(3, 5, 3, 5);
+ this.customSelectedCheckedListBoxProperty.Name = "customSelectedCheckedListBoxProperty";
+ this.customSelectedCheckedListBoxProperty.SelectedElement = "";
+ this.customSelectedCheckedListBoxProperty.Size = new System.Drawing.Size(171, 209);
+ this.customSelectedCheckedListBoxProperty.TabIndex = 0;
+ //
+ // groupBoxData
+ //
+ this.groupBoxData.Controls.Add(this.labelDeviceType);
+ this.groupBoxData.Controls.Add(this.labelModel);
+ this.groupBoxData.Controls.Add(this.labelRegNum);
+ this.groupBoxData.Controls.Add(this.buttonGetFromTree);
+ this.groupBoxData.Controls.Add(this.buttonAddToTree);
+ this.groupBoxData.Controls.Add(this.comboBoxDeviceType);
+ this.groupBoxData.Controls.Add(this.textBoxModel);
+ this.groupBoxData.Controls.Add(this.textBoxSerialNumber);
+ this.groupBoxData.Controls.Add(this.customTreeView);
+ this.groupBoxData.Location = new System.Drawing.Point(7, 269);
+ this.groupBoxData.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.groupBoxData.Name = "groupBoxData";
+ this.groupBoxData.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.groupBoxData.Size = new System.Drawing.Size(719, 307);
+ this.groupBoxData.TabIndex = 11;
+ this.groupBoxData.TabStop = false;
+ this.groupBoxData.Text = "Data";
+ //
+ // labelDeviceType
+ //
+ this.labelDeviceType.AutoSize = true;
+ this.labelDeviceType.Location = new System.Drawing.Point(494, 155);
+ this.labelDeviceType.Name = "labelDeviceType";
+ this.labelDeviceType.Size = new System.Drawing.Size(119, 20);
+ this.labelDeviceType.TabIndex = 8;
+ this.labelDeviceType.Text = "Тип устройства";
+ //
+ // labelModel
+ //
+ this.labelModel.AutoSize = true;
+ this.labelModel.Location = new System.Drawing.Point(494, 96);
+ this.labelModel.Name = "labelModel";
+ this.labelModel.Size = new System.Drawing.Size(63, 20);
+ this.labelModel.TabIndex = 7;
+ this.labelModel.Text = "Модель";
+ //
+ // labelRegNum
+ //
+ this.labelRegNum.AutoSize = true;
+ this.labelRegNum.Location = new System.Drawing.Point(494, 37);
+ this.labelRegNum.Name = "labelRegNum";
+ this.labelRegNum.Size = new System.Drawing.Size(185, 20);
+ this.labelRegNum.TabIndex = 6;
+ this.labelRegNum.Text = "Регистрационный номер";
+ //
+ // buttonGetFromTree
+ //
+ this.buttonGetFromTree.Location = new System.Drawing.Point(494, 260);
+ this.buttonGetFromTree.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.buttonGetFromTree.Name = "buttonGetFromTree";
+ this.buttonGetFromTree.Size = new System.Drawing.Size(215, 31);
+ this.buttonGetFromTree.TabIndex = 5;
+ this.buttonGetFromTree.Text = "Get Selected";
+ this.buttonGetFromTree.UseVisualStyleBackColor = true;
+ this.buttonGetFromTree.Click += new System.EventHandler(this.buttonGetFromTree_Click);
+ //
+ // buttonAddToTree
+ //
+ this.buttonAddToTree.Location = new System.Drawing.Point(494, 221);
+ this.buttonAddToTree.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.buttonAddToTree.Name = "buttonAddToTree";
+ this.buttonAddToTree.Size = new System.Drawing.Size(215, 31);
+ this.buttonAddToTree.TabIndex = 4;
+ this.buttonAddToTree.Text = "Add";
+ this.buttonAddToTree.UseVisualStyleBackColor = true;
+ this.buttonAddToTree.Click += new System.EventHandler(this.buttonAddToTree_Click);
+ //
+ // comboBoxDeviceType
+ //
+ this.comboBoxDeviceType.FormattingEnabled = true;
+ this.comboBoxDeviceType.Location = new System.Drawing.Point(494, 179);
+ this.comboBoxDeviceType.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.comboBoxDeviceType.Name = "comboBoxDeviceType";
+ this.comboBoxDeviceType.Size = new System.Drawing.Size(214, 28);
+ this.comboBoxDeviceType.TabIndex = 3;
+ //
+ // textBoxModel
+ //
+ this.textBoxModel.Location = new System.Drawing.Point(494, 120);
+ this.textBoxModel.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.textBoxModel.Name = "textBoxModel";
+ this.textBoxModel.Size = new System.Drawing.Size(214, 27);
+ this.textBoxModel.TabIndex = 2;
+ //
+ // textBoxSerialNumber
+ //
+ this.textBoxSerialNumber.Location = new System.Drawing.Point(494, 61);
+ this.textBoxSerialNumber.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.textBoxSerialNumber.Name = "textBoxSerialNumber";
+ this.textBoxSerialNumber.Size = new System.Drawing.Size(214, 27);
+ this.textBoxSerialNumber.TabIndex = 1;
+ //
+ // customTreeView
+ //
+ this.customTreeView.Location = new System.Drawing.Point(17, 29);
+ this.customTreeView.Margin = new System.Windows.Forms.Padding(3, 5, 3, 5);
+ this.customTreeView.Name = "customTreeView";
+ this.customTreeView.Size = new System.Drawing.Size(455, 269);
+ this.customTreeView.TabIndex = 0;
+ //
+ // tabControl
+ //
+ this.tabControl.Controls.Add(this.Visual);
+ this.tabControl.Controls.Add(this.Docs);
+ this.tabControl.Location = new System.Drawing.Point(14, 16);
+ this.tabControl.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.tabControl.Name = "tabControl";
+ this.tabControl.SelectedIndex = 0;
+ this.tabControl.Size = new System.Drawing.Size(746, 621);
+ this.tabControl.TabIndex = 12;
+ //
+ // Visual
+ //
+ this.Visual.Controls.Add(this.groupBoxData);
+ this.Visual.Controls.Add(this.groupBoxInput);
+ this.Visual.Controls.Add(this.groupBoxSelected);
+ this.Visual.Location = new System.Drawing.Point(4, 29);
+ this.Visual.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.Visual.Name = "Visual";
+ this.Visual.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.Visual.Size = new System.Drawing.Size(738, 588);
+ this.Visual.TabIndex = 0;
+ this.Visual.Text = "Visual";
+ this.Visual.UseVisualStyleBackColor = true;
+ //
+ // Docs
+ //
+ this.Docs.Controls.Add(this.buttonWordWithDiagram);
+ this.Docs.Controls.Add(this.buttonWordWithTable);
+ this.Docs.Controls.Add(this.buttonWordWithImage);
+ this.Docs.Location = new System.Drawing.Point(4, 29);
+ this.Docs.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.Docs.Name = "Docs";
+ this.Docs.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.Docs.Size = new System.Drawing.Size(738, 588);
+ this.Docs.TabIndex = 1;
+ this.Docs.Text = "Docs";
+ this.Docs.UseVisualStyleBackColor = true;
+ //
+ // buttonWordWithDiagram
+ //
+ this.buttonWordWithDiagram.Location = new System.Drawing.Point(490, 223);
+ this.buttonWordWithDiagram.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.buttonWordWithDiagram.Name = "buttonWordWithDiagram";
+ this.buttonWordWithDiagram.Size = new System.Drawing.Size(227, 97);
+ this.buttonWordWithDiagram.TabIndex = 13;
+ this.buttonWordWithDiagram.Text = "Word With Diagram";
+ this.buttonWordWithDiagram.UseVisualStyleBackColor = true;
+ this.buttonWordWithDiagram.Click += new System.EventHandler(this.buttonWordWithDiagram_Click);
+ //
+ // buttonWordWithTable
+ //
+ this.buttonWordWithTable.Location = new System.Drawing.Point(256, 223);
+ this.buttonWordWithTable.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.buttonWordWithTable.Name = "buttonWordWithTable";
+ this.buttonWordWithTable.Size = new System.Drawing.Size(227, 97);
+ this.buttonWordWithTable.TabIndex = 14;
+ this.buttonWordWithTable.Text = "Word With Table";
+ this.buttonWordWithTable.UseVisualStyleBackColor = true;
+ this.buttonWordWithTable.Click += new System.EventHandler(this.buttonWordWithTable_Click);
+ //
+ // buttonWordWithImage
+ //
+ this.buttonWordWithImage.Location = new System.Drawing.Point(22, 223);
+ this.buttonWordWithImage.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.buttonWordWithImage.Name = "buttonWordWithImage";
+ this.buttonWordWithImage.Size = new System.Drawing.Size(227, 97);
+ this.buttonWordWithImage.TabIndex = 13;
+ this.buttonWordWithImage.Text = "Word With Image";
+ this.buttonWordWithImage.UseVisualStyleBackColor = true;
+ this.buttonWordWithImage.Click += new System.EventHandler(this.buttonWordWithImage_Click);
+ //
+ // FormMain
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(771, 648);
+ this.Controls.Add(this.tabControl);
+ this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.Name = "FormMain";
+ this.Text = "FormMain";
+ this.groupBoxInput.ResumeLayout(false);
+ this.groupBoxInput.PerformLayout();
+ this.groupBoxSelected.ResumeLayout(false);
+ this.groupBoxSelected.PerformLayout();
+ this.groupBoxData.ResumeLayout(false);
+ this.groupBoxData.PerformLayout();
+ this.tabControl.ResumeLayout(false);
+ this.Visual.ResumeLayout(false);
+ this.Docs.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private MyCustomComponents.CustomInputRangeNumber customInputRangeNumber;
+ private TextBox textBoxMin;
+ private TextBox textBoxMax;
+ private Button buttonCheck;
+ private Label labelCheckValue;
+ private GroupBox groupBoxInput;
+ private GroupBox groupBoxSelected;
+ private Button buttonGetSelected;
+ private Label labelSelectedValue;
+ private Button buttonClear;
+ private Button buttonAdd;
+ private TextBox textBoxAdd;
+ private MyCustomComponents.CustomSelectedCheckedListBoxProperty customSelectedCheckedListBoxProperty;
+ private GroupBox groupBoxData;
+ private MyCustomComponents.CustomTreeView customTreeView;
+ private Button buttonGetFromTree;
+ private Button buttonAddToTree;
+ private ComboBox comboBoxDeviceType;
+ private TextBox textBoxModel;
+ private TextBox textBoxSerialNumber;
+ private Label labelDeviceType;
+ private Label labelModel;
+ private Label labelRegNum;
+ private TabControl tabControl;
+ private TabPage Visual;
+ private TabPage Docs;
+ private Button buttonWordWithImage;
+ private MyCustomComponents.WordWithImages wordWithImages;
+ private Button buttonWordWithTable;
+ private MyCustomComponents.WordWithTable wordWithTable;
+ private Button buttonWordWithDiagram;
+ private MyCustomComponents.WordWithDiagram wordWithDiagram;
+ }
+}
\ No newline at end of file
diff --git a/Lab 2/Belianin_2/DesktopWithMyVisualComponents/FormMain.cs b/Lab 2/Belianin_2/DesktopWithMyVisualComponents/FormMain.cs
new file mode 100644
index 0000000..c24da68
--- /dev/null
+++ b/Lab 2/Belianin_2/DesktopWithMyVisualComponents/FormMain.cs
@@ -0,0 +1,255 @@
+using MyCustomComponents;
+using MyCustomComponents.Models;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace DesktopWithMyVisualComponents
+{
+ public partial class FormMain : Form
+ {
+ readonly List devices = new()
+ {
+ new Device { Id = 1, SerialNumber = "SM-12345", DeviceType = "Мобильный телефон", Model = "IPhone 13", Owner = "Иван Иванов", PurchaseDate = new DateTime(2022, 5, 15), State = "Новый", Price = 70000, Color = "Синий", WarrantyPeriod = 6 },
+ new Device { Id = 2, SerialNumber = "CO2UD8471", DeviceType = "Ноутбук", Model = "MacBook Pro", Owner = "Петр Петров", PurchaseDate = new DateTime(2021, 3, 20), State = "Б/У", Price = 150000, Color = "Черный", WarrantyPeriod = 12 },
+ new Device { Id = 3, SerialNumber = "R80NZD8812", DeviceType = "Умные часы", Model = "Galaxy Watch 4", Owner = "Анна Смирнова", PurchaseDate = new DateTime(2023, 1, 10), State = "Новый", Price = 25000, Color = "Белый", WarrantyPeriod = 18 },
+ new Device { Id = 4, SerialNumber = "SM-G3412", DeviceType = "Мобильный телефон", Model = "Samsung Galaxy S24", Owner = "Елена Кузнецова", PurchaseDate = new DateTime(2023, 7, 25), State = "Новый", Price = 80000, Color = "Синий", WarrantyPeriod = 6 },
+ new Device { Id = 5, SerialNumber = "FN738214", DeviceType = "Умные часы", Model = "Apple Watch 3", Owner = "Дмитрий Федоров", PurchaseDate = new DateTime(2020, 8, 5), State = "Б/У", Price = 15000, Color = "Красный", WarrantyPeriod = 24 },
+ };
+
+ public FormMain()
+ {
+ InitializeComponent();
+
+ // Пример для компонента
+ var list = new List() { "Значение 1", "Значение 2", "Значение 3", "Значение 4", "Значение 5" };
+ customSelectedCheckedListBoxProperty.Items.AddRange(list.ToArray());
+
+ comboBoxDeviceType.Items.Add("Мобильный телефон");
+ comboBoxDeviceType.Items.Add("Ноутбук");
+ comboBoxDeviceType.Items.Add("Умные часы");
+
+ // Загрузка дерева с девайсами
+ LoadTree();
+
+ customTreeView.SelectedTreeNode = 2;
+
+ // Присоединить обработчик события при изменении значения
+ customInputRangeNumber.ChangeEvent += CustomInputRangeNumber_ChangeEvent;
+ }
+
+ // Загрузка дерево с иерархией устройств на основе типа устройства, модели и серийного номера
+ public void LoadTree()
+ {
+ // Очистите существующие узлы перед загрузкой новых
+ customTreeView.Clear();
+
+ customTreeView.hierarchy = new List { "DeviceType", "Model", "SerialNumber" };
+
+ foreach (Device device in devices)
+ {
+ customTreeView.AddNode(device, "SerialNumber");
+ }
+ }
+
+ // Вынесенная логика проверки значения
+ private void UpdateLabelWithValue()
+ {
+ labelCheckValue.Text = customInputRangeNumber.Value.ToString();
+ if (string.IsNullOrEmpty(labelCheckValue.Text))
+ {
+ labelCheckValue.Text = customInputRangeNumber.Error;
+ }
+ }
+
+ // Добавляем метод для обработки изменения значения
+ private void CustomInputRangeNumber_ChangeEvent(object sender, EventArgs e)
+ {
+ UpdateLabelWithValue();
+ }
+
+ // Метод проверки значения в Input
+ private void buttonCheck_Click(object sender, EventArgs e)
+ {
+ UpdateLabelWithValue();
+ }
+
+ // Установка границ
+ private void buttonSetBorders_Click(object sender, EventArgs e)
+ {
+ if (decimal.TryParse(textBoxMin.Text, out decimal minValue) && decimal.TryParse(textBoxMax.Text, out decimal maxValue))
+ {
+ // Проверка: MaxValue должно быть больше MinValue
+ if (maxValue <= minValue)
+ {
+ labelCheckValue.Text = "Ошибка: MaxValue должно быть больше MinValue.";
+ return;
+ }
+
+ // Устанавливаем границы
+ customInputRangeNumber.MinValue = minValue;
+ customInputRangeNumber.MaxValue = maxValue;
+ labelCheckValue.Text = "Границы установлены";
+
+ // Проверим текущее значение компонента на соответствие новому диапазону
+ /*try
+ {
+ var currentValue = customInputRangeNumber.Value;
+
+ // Если значение в пределах, выводим сообщение об успехе
+ labelCheckValue.Text = "Границы установлены. Текущее значение в пределах диапазона.";
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ // Если текущее значение вне диапазона, выводим ошибку
+ labelCheckValue.Text = $"Ошибка: {ex.Message}";
+ }*/
+ }
+ else
+ {
+ labelCheckValue.Text = "Ошибка: неверные значения границ";
+ }
+ }
+
+ private void textBoxMin_KeyPress(object sender, KeyPressEventArgs e)
+ {
+ char ch = e.KeyChar;
+
+ if (!Char.IsDigit(ch) && ch != 8 && ch != 45)
+ {
+ e.Handled = true;
+ }
+ }
+
+ private void textBoxMax_KeyPress(object sender, KeyPressEventArgs e)
+ {
+ char ch = e.KeyChar;
+
+ if (!Char.IsDigit(ch) && ch != 8 && ch != 45)
+ {
+ e.Handled = true;
+ }
+ }
+
+ private void buttonAdd_Click(object sender, EventArgs e)
+ {
+ if (textBoxAdd.Text != "" && !customSelectedCheckedListBoxProperty.Items.Contains(textBoxAdd.Text))
+ customSelectedCheckedListBoxProperty.Items.Add(textBoxAdd.Text);
+ else if (customSelectedCheckedListBoxProperty.Items.Contains(textBoxAdd.Text))
+ customSelectedCheckedListBoxProperty.SelectedElement = textBoxAdd.Text;
+ }
+
+ private void buttonClear_Click(object sender, EventArgs e)
+ {
+ customSelectedCheckedListBoxProperty.Clear();
+ }
+
+ private void buttonGetSelected_Click(object sender, EventArgs e)
+ {
+ labelSelectedValue.Text = customSelectedCheckedListBoxProperty.SelectedElement;
+ if (string.IsNullOrEmpty(labelSelectedValue.Text))
+ {
+ labelSelectedValue.Text = "Значение \nне выбрано";
+ }
+ }
+
+ // Добавление нового узла в дерево
+ private void buttonAddToTree_Click(object sender, EventArgs e)
+ {
+ Device device = new Device
+ {
+ SerialNumber = textBoxSerialNumber.Text,
+ Model = textBoxModel.Text,
+ DeviceType = comboBoxDeviceType.SelectedItem?.ToString()
+ };
+
+ customTreeView.AddNode(device, "SerialNumber");
+ }
+
+ // Получение данных выбранного узла из дерева
+ private void buttonGetFromTree_Click(object sender, EventArgs e)
+ {
+ Device? device = customTreeView.GetSelectedNode();
+ if (device == null)
+ {
+ return;
+ }
+
+ textBoxSerialNumber.Text = device.SerialNumber;
+ textBoxModel.Text = device.Model;
+ comboBoxDeviceType.SelectedItem = device.DeviceType;
+ }
+
+ private void buttonWordWithImage_Click(object sender, EventArgs e)
+ {
+ var openFileDialog = new OpenFileDialog();
+ bool flag = true;
+ var images = new List();
+ while (flag)
+ {
+ if (openFileDialog.ShowDialog() == DialogResult.OK)
+ {
+ images.Add(File.ReadAllBytes(openFileDialog.FileName));
+ }
+ else
+ {
+ flag = false;
+ }
+ }
+ wordWithImages.CreateDoc(new WordWithImageConfig
+ {
+ FilePath = "E:\\COP\\Lab 2\\WordWithImageDocx.docx",
+ Header = "Картинки:",
+ Images = images,
+ });
+ }
+
+ private void buttonWordWithTable_Click(object sender, EventArgs e)
+ {
+ wordWithTable.CreateDoc(new WordWithTableDataConfig
+ {
+ FilePath = "E:\\COP\\Lab 2\\WordWithTableDocx.docx",
+ Header = "Таблица:",
+ UseUnion = true,
+ ColumnsRowsWidth = new List<(int, int)> { (0, 5), (0, 5), (0, 10), (0, 10), (0, 7), (0, 7), (0, 10), (0, 10), (0, 8) },
+ ColumnUnion = new List<(int StartIndex, int Count)> { (2, 3), (5, 3) },
+ Headers = new List<(int ColumnIndex, int RowIndex, string Header, string PropertyName)>
+ {
+ (0, 0, "Номер", "Id"),
+ (1, 0, "Серийный номер", "SerialNumber"),
+ (2, 0, "Об устройстве", "DeviceType"),
+ (2, 1, "Модель", "Model"),
+ (3, 1, "Цвет", "Color"),
+ (4, 1, "Стоимость", "Price"),
+ (5, 0, "Покупатели", ""),
+ (5, 1, "Дата покупки", "PurchaseDate"),
+ (6, 1, "Владелец", "Owner"),
+ (7, 1, "Статус", "State"),
+ (8, 0, "Гарантия", "WarrantyPeriod"),
+ },
+ Data = devices
+ });
+ }
+
+ private void buttonWordWithDiagram_Click(object sender, EventArgs e)
+ {
+ wordWithDiagram.CreateDoc(new WordWithDiagramConfig
+ {
+ FilePath = "E:\\COP\\Lab 2\\WordWithDiagramDocx.docx",
+ Header = "Диаграмма",
+ ChartTitle = "Круговая диаграмма",
+ LegendLocation = MyCustomComponents.Models.Location.Bottom,
+ Data = new Dictionary>
+ {
+ { "Серия 1", new List<(int Date, double Value)> { (1, 20), (2, 30), (3, 50) } }
+ }
+ });
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/DesktopWithMyVisualComponents/FormMain.resx b/Lab 2/Belianin_2/DesktopWithMyVisualComponents/FormMain.resx
new file mode 100644
index 0000000..93c550b
--- /dev/null
+++ b/Lab 2/Belianin_2/DesktopWithMyVisualComponents/FormMain.resx
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 161, 17
+
+
+ 295, 17
+
+
\ No newline at end of file
diff --git a/Lab 2/Belianin_2/DesktopWithMyVisualComponents/Program.cs b/Lab 2/Belianin_2/DesktopWithMyVisualComponents/Program.cs
new file mode 100644
index 0000000..7aba605
--- /dev/null
+++ b/Lab 2/Belianin_2/DesktopWithMyVisualComponents/Program.cs
@@ -0,0 +1,17 @@
+namespace DesktopWithMyVisualComponents
+{
+ internal static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ // To customize application configuration such as set high DPI settings or default font,
+ // see https://aka.ms/applicationconfiguration.
+ ApplicationConfiguration.Initialize();
+ Application.Run(new FormMain());
+ }
+ }
+}
\ No newline at end of file
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Attributes/AlwaysCreateAttribute .cs b/Lab 2/Belianin_2/MyCustomComponents/Attributes/AlwaysCreateAttribute .cs
new file mode 100644
index 0000000..db0392f
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Attributes/AlwaysCreateAttribute .cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Attributes
+{
+ public class AlwaysCreateAttribute : Attribute
+ {
+ public AlwaysCreateAttribute() { }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/CustomInputRangeNumber.Designer.cs b/Lab 2/Belianin_2/MyCustomComponents/CustomInputRangeNumber.Designer.cs
new file mode 100644
index 0000000..afbf042
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/CustomInputRangeNumber.Designer.cs
@@ -0,0 +1,59 @@
+namespace MyCustomComponents
+{
+ partial class CustomInputRangeNumber
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ 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()
+ {
+ numericUpDown = new NumericUpDown();
+ ((System.ComponentModel.ISupportInitialize)numericUpDown).BeginInit();
+ SuspendLayout();
+ //
+ // numericUpDown
+ //
+ numericUpDown.Location = new Point(3, 2);
+ numericUpDown.Margin = new Padding(3, 2, 3, 2);
+ numericUpDown.Name = "numericUpDown";
+ numericUpDown.Size = new Size(131, 23);
+ numericUpDown.TabIndex = 0;
+ //
+ // CustomInputRangeNumber
+ //
+ AutoScaleDimensions = new SizeF(7F, 15F);
+ AutoScaleMode = AutoScaleMode.Font;
+ Controls.Add(numericUpDown);
+ Margin = new Padding(3, 2, 3, 2);
+ Name = "CustomInputRangeNumber";
+ Size = new Size(141, 27);
+ ((System.ComponentModel.ISupportInitialize)numericUpDown).EndInit();
+ ResumeLayout(false);
+ }
+
+ #endregion
+
+ private NumericUpDown numericUpDown;
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/CustomInputRangeNumber.cs b/Lab 2/Belianin_2/MyCustomComponents/CustomInputRangeNumber.cs
new file mode 100644
index 0000000..e3da2f6
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/CustomInputRangeNumber.cs
@@ -0,0 +1,122 @@
+using MyCustomComponents.Extensions;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace MyCustomComponents
+{
+ public partial class CustomInputRangeNumber : UserControl
+ {
+ // Диапазон
+ private string example = "Введите значение от " + decimal.MinValue + " до " + decimal.MaxValue;
+
+ // В случае ошибки
+ public string Error { get; protected set; } = string.Empty;
+
+ // Создам 2 публичных поля для настройки границ диапазона
+ public decimal? MinValue { get; set; } = null;
+ public decimal? MaxValue { get; set; } = null;
+
+
+ /* Публичное свойство для установки и получения введённого значения (set, get). При получении проводится проверка,
+ Если введённое значение не входит в диапозон, возвращать значение null, а в отдельное поле выводить текст ошибки.
+ При установке должна проводиться проверка, если передаваемое значение не входит в диапозон, то не заполнять поле компонента.
+ */
+
+ public decimal? Value
+ {
+ get
+ {
+ // Как мы проверим что программист не забыл задать минимальное, максимальное значение?
+ // Проверка, что MinValue и MaxValue задан
+ if (!MinValue.HasValue || !MaxValue.HasValue)
+ {
+ throw new RangeException("MinValue и MaxValue должны быть заданы.");
+ }
+
+ // Проверяем, что max не может быть min
+ if (MaxValue.Value <= MinValue.Value)
+ {
+ throw new RangeException("MaxValue должно быть больше MinValue");
+ }
+
+ decimal currentValue = numericUpDown.Value;
+
+ // Проверка, что значение в диапазоне
+ if (currentValue < MinValue.Value || currentValue > MaxValue.Value)
+ {
+ throw new RangeException($"Введённое значение {currentValue} лежит вне диапазона {MinValue.Value} - {MaxValue.Value}.");
+ }
+
+ return currentValue;
+ }
+ set
+ {
+ // Проверка, что MinValue и MaxValue заданы
+ if (!MinValue.HasValue || !MaxValue.HasValue)
+ {
+ Error = "MinValue и MaxValue должны быть заданы.";
+ return;
+ }
+
+ // Проверка, что MinValue меньше MaxValue
+ if (MinValue.Value >= MaxValue.Value)
+ {
+ Error = "Диапазон неверен. MinValue должен быть меньше, чем MaxValue.";
+ return;
+ }
+
+ // Если число верно в диапозоне, то значение устанавливается
+ if (value.HasValue && value.Value >= MinValue.Value && value.Value <= MaxValue.Value)
+ {
+ numericUpDown.Value = value.Value;
+
+ // Очистить ошибку, если значение установлено успешно
+ Error = null;
+ }
+ else
+ {
+ Error = $"Значение должно быть в диапазоне от {MinValue.Value} до {MaxValue.Value}.";
+ }
+ }
+ }
+
+
+ public CustomInputRangeNumber()
+ {
+ InitializeComponent();
+ }
+
+ private void numericUpDown_Enter(object sender, EventArgs e)
+ {
+ ToolTip toolTip = new ToolTip();
+ toolTip.Show(example, numericUpDown, 30, -20, 1000);
+ }
+
+ private void numericUpDown_ValueChanged(object sender, EventArgs e)
+ {
+ _changeEvent?.Invoke(sender, e);
+ }
+
+ private EventHandler _changeEvent;
+
+ // Событие, вызываемое при смене значения
+ public event EventHandler ChangeEvent
+ {
+ add
+ {
+ _changeEvent += value;
+ }
+ remove
+ {
+ _changeEvent -= value;
+ }
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/CustomInputRangeNumber.resx b/Lab 2/Belianin_2/MyCustomComponents/CustomInputRangeNumber.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/CustomInputRangeNumber.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Lab 2/Belianin_2/MyCustomComponents/CustomSelectedCheckedListBoxProperty.Designer.cs b/Lab 2/Belianin_2/MyCustomComponents/CustomSelectedCheckedListBoxProperty.Designer.cs
new file mode 100644
index 0000000..ca537d7
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/CustomSelectedCheckedListBoxProperty.Designer.cs
@@ -0,0 +1,56 @@
+namespace MyCustomComponents
+{
+ partial class CustomSelectedCheckedListBoxProperty
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ 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()
+ {
+ checkedListBox = new CheckedListBox();
+ SuspendLayout();
+ //
+ // checkedListBox
+ //
+ checkedListBox.FormattingEnabled = true;
+ checkedListBox.Location = new Point(4, 4);
+ checkedListBox.Name = "checkedListBox";
+ checkedListBox.Size = new Size(164, 180);
+ checkedListBox.TabIndex = 0;
+ //
+ // CustomSelectedCheckedListBoxProperty
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ Controls.Add(checkedListBox);
+ Name = "CustomSelectedCheckedListBoxProperty";
+ Size = new Size(171, 209);
+ ResumeLayout(false);
+ }
+
+ #endregion
+
+ private CheckedListBox checkedListBox;
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/CustomSelectedCheckedListBoxProperty.cs b/Lab 2/Belianin_2/MyCustomComponents/CustomSelectedCheckedListBoxProperty.cs
new file mode 100644
index 0000000..43999dd
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/CustomSelectedCheckedListBoxProperty.cs
@@ -0,0 +1,89 @@
+using MyCustomComponents.Extensions;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace MyCustomComponents
+{
+ public partial class CustomSelectedCheckedListBoxProperty : UserControl
+ {
+ /* Публичное свойство, которое передаёт ссылку на свойство Items
+ * элемента ComboBox, через которое и идёт заполнение */
+ public CheckedListBox.ObjectCollection Items => checkedListBox.Items;
+
+ public CustomSelectedCheckedListBoxProperty()
+ {
+ InitializeComponent();
+ }
+
+ // Отдельный публичный метод очистки списка
+ public void Clear()
+ {
+ checkedListBox.Items.Clear();
+ }
+
+ private EventHandler _changeEvent;
+
+ private void checkedListBox_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ _changeEvent?.Invoke(sender, e);
+ }
+
+ // Событие, вызываемое при смене значения в CheckedListBox
+ public event EventHandler Changed
+ {
+ add
+ {
+ _changeEvent += value;
+ }
+ remove
+ {
+ _changeEvent -= value;
+ }
+ }
+
+
+ // Публичное свойство (set, get) для установки и получения выбранного значения (возвращает пустую строку, если нет выбранного значения)
+ public string SelectedElement
+ {
+ get
+ {
+ return (checkedListBox.SelectedIndex > -1 && checkedListBox.GetItemChecked(checkedListBox.SelectedIndex)) ? checkedListBox.SelectedIndex.ToString() : string.Empty;
+ }
+ set
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ int index = checkedListBox.Items.IndexOf(value);
+
+ // Если попытаться установить несуществующий элемент
+ if (index == -1)
+ {
+ // Выбрасываем исключение, если элемент не найден в списке
+ throw new InvalidSelectedElementException($"Элемент '{value}' не найден в списке.");
+ }
+
+ checkedListBox.SelectedItem = value;
+ checkedListBox.SetItemCheckState(checkedListBox.SelectedIndex, CheckState.Checked);
+ }
+ }
+ }
+
+
+ private void checkedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
+ {
+ if (e.NewValue == CheckState.Checked && checkedListBox.CheckedItems.Count > 0)
+ {
+ checkedListBox.ItemCheck -= checkedListBox_ItemCheck;
+ checkedListBox.SetItemChecked(checkedListBox.CheckedIndices[0], value: false);
+ checkedListBox.ItemCheck += checkedListBox_ItemCheck;
+ }
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/CustomSelectedCheckedListBoxProperty.resx b/Lab 2/Belianin_2/MyCustomComponents/CustomSelectedCheckedListBoxProperty.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/CustomSelectedCheckedListBoxProperty.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Lab 2/Belianin_2/MyCustomComponents/CustomTreeView.Designer.cs b/Lab 2/Belianin_2/MyCustomComponents/CustomTreeView.Designer.cs
new file mode 100644
index 0000000..35784f9
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/CustomTreeView.Designer.cs
@@ -0,0 +1,55 @@
+namespace MyCustomComponents
+{
+ partial class CustomTreeView
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ 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()
+ {
+ treeView = new TreeView();
+ SuspendLayout();
+ //
+ // treeView
+ //
+ treeView.Location = new Point(3, 3);
+ treeView.Name = "treeView";
+ treeView.Size = new Size(517, 259);
+ treeView.TabIndex = 0;
+ //
+ // CustomTreeCell
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ Controls.Add(treeView);
+ Name = "CustomTreeCell";
+ Size = new Size(525, 269);
+ ResumeLayout(false);
+ }
+
+ #endregion
+
+ private TreeView treeView;
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/CustomTreeView.cs b/Lab 2/Belianin_2/MyCustomComponents/CustomTreeView.cs
new file mode 100644
index 0000000..df80615
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/CustomTreeView.cs
@@ -0,0 +1,168 @@
+using MyCustomComponents.Extensions;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.Button;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement;
+using MyCustomComponents.Attributes;
+using System.Xml.Linq;
+
+namespace MyCustomComponents
+{
+ public partial class CustomTreeView : UserControl
+ {
+ public CustomTreeView()
+ {
+ InitializeComponent();
+ }
+
+ // Свойство для получения и установки выбранного узла в TreeView
+ public int SelectedTreeNode
+ {
+ get
+ {
+ if (treeView.SelectedNode != null)
+ {
+ return treeView.SelectedNode.Index;
+ }
+
+ return -1;
+ }
+ set
+ {
+ if (treeView.Nodes.Count > 0 && value >= 0 && value < treeView.Nodes.Count)
+ {
+ treeView.SelectedNode = treeView.Nodes[value];
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException(nameof(value), $"Индекс {value} выходит за пределы допустимого диапазона. Допустимый диапазон: от 0 до {treeView.Nodes.Count - 1}.");
+ }
+ }
+ }
+
+ public List? hierarchy { get; set; }
+
+ private Dictionary newBranch { get; set; } = new Dictionary();
+
+ // Отдельный публичный метод очистки всех узлов дерева
+ public void Clear()
+ {
+ treeView.Nodes.Clear();
+ }
+
+ // Публичный метод для получения выбранной записи из древовидной структуры
+ public T GetSelectedNode() where T : class, new()
+ {
+ if (hierarchy == null)
+ {
+ throw new HierarchyNullException("Hierarchy is null");
+ }
+
+ if (treeView.SelectedNode == null)
+ {
+ throw new InvalidSelectedElementException("TreeView null");
+ }
+
+ // Проверка, является ли выбранный узел корневым
+ if (treeView.SelectedNode.Parent == null)
+ {
+ // Выбран корневой элемент — возвращаем пустой объект
+ throw new InvalidSelectedElementException("Parent is null");
+ }
+
+ // Если узел выбран и существует, вызываем приватный метод для получения данных узла
+ return _getNode();
+ }
+
+
+ // Приватный метод, идущий по узлам вверх (по иерархии)
+ private T _getNode() where T : new()
+ {
+ TreeNode? node = treeView.SelectedNode;
+
+ var obj = new T();
+ int level = hierarchy.Count - 1;
+
+ // Проходим по иерархии от нижнего уровня к верхнему
+ while (node != null && level >= 0)
+ {
+ var property = hierarchy[level];
+ obj.GetType().GetProperty(property)?.SetValue(obj, node.Text);
+
+ node = node.Parent;
+
+ level--;
+ }
+
+ return obj;
+ }
+
+ /* Параметризированный метод, у которого в передаваемых параметрах
+ * идёт объект какого-то класса и имя свойства/поля, до которого согласно
+ * иерархии будет следовать формирование ветви
+ */
+ public void AddNode(T obj, string propertyName)
+ {
+ if (hierarchy == null)
+ {
+ throw new HierarchyNullException("Hierarchy is null");
+ }
+
+ if (obj == null)
+ {
+ throw new ArgumentNullException("Added object is null");
+ }
+
+ // Получаем первый узел в дереве
+ TreeNode currentNode = null;
+
+ // Проходимся по иерархии
+ foreach (var property in hierarchy)
+ {
+ // Получаем значение свойства
+ var value = obj.GetType().GetProperty(property)?.GetValue(obj, null)?.ToString();
+ bool createNewBranch = newBranch != null && newBranch.ContainsKey(propertyName) && newBranch[propertyName];
+
+ if (currentNode == null)
+ {
+ currentNode = treeView.Nodes.Cast().FirstOrDefault(n => n.Text == value)
+ ?? treeView.Nodes.Add(value);
+ }
+ else
+ {
+ var childNode = currentNode.Nodes.Cast().FirstOrDefault(n => n.Text == value);
+
+ // Проверка нужно ли нам создавать дочерний узел
+ if (childNode == null || createNewBranch)
+ {
+ childNode = currentNode.Nodes.Add(value);
+ }
+
+ // Переходим на уровень этого дочернего узла
+ currentNode = childNode;
+ }
+
+ if (property == propertyName)
+ {
+ break;
+ }
+
+ }
+ }
+
+
+ public void SetHierarchy(List hierarchy, Dictionary newBranch)
+ {
+ this.hierarchy = hierarchy;
+ this.newBranch = newBranch;
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/CustomTreeView.resx b/Lab 2/Belianin_2/MyCustomComponents/CustomTreeView.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/CustomTreeView.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Extensions/HierarchyNullException.cs b/Lab 2/Belianin_2/MyCustomComponents/Extensions/HierarchyNullException.cs
new file mode 100644
index 0000000..1699429
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Extensions/HierarchyNullException.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Extensions
+{
+ public class HierarchyNullException : Exception
+ {
+ public HierarchyNullException() { }
+
+ public HierarchyNullException(string message) : base(message) { }
+
+ public HierarchyNullException(string message, Exception inner) : base(message, inner) { }
+
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Extensions/InvalidSelectedElementException.cs b/Lab 2/Belianin_2/MyCustomComponents/Extensions/InvalidSelectedElementException.cs
new file mode 100644
index 0000000..f5b0986
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Extensions/InvalidSelectedElementException.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Extensions
+{
+ // Исключение, если нет выбранного и отмеченного элемента
+ public class InvalidSelectedElementException : Exception
+ {
+ public InvalidSelectedElementException() { }
+
+ public InvalidSelectedElementException(string message) : base(message)
+ {
+ }
+
+ public InvalidSelectedElementException(string message, Exception inner) : base(message, inner)
+ {
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Extensions/PropertyNullException.cs b/Lab 2/Belianin_2/MyCustomComponents/Extensions/PropertyNullException.cs
new file mode 100644
index 0000000..0de8cea
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Extensions/PropertyNullException.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Extensions
+{
+ public class PropertyNullException : Exception
+ {
+ public PropertyNullException() { }
+
+ public PropertyNullException(string message) : base(message) { }
+
+ public PropertyNullException(string message, Exception inner) : base(message, inner) { }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Extensions/RangeException.cs b/Lab 2/Belianin_2/MyCustomComponents/Extensions/RangeException.cs
new file mode 100644
index 0000000..aa8e00c
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Extensions/RangeException.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Extensions
+{
+ internal class RangeException : Exception
+ {
+ public RangeException() { }
+
+ public RangeException(string message) : base(message)
+ { }
+
+ public RangeException(string message, Exception inner) : base(message, inner)
+ {
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Extensions/ValueOutOfRangeException .cs b/Lab 2/Belianin_2/MyCustomComponents/Extensions/ValueOutOfRangeException .cs
new file mode 100644
index 0000000..91e3b33
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Extensions/ValueOutOfRangeException .cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Extensions
+{
+ // Ошибка неверного значения, когда значение выходит за границы диапазона
+ public class ValueOutOfRangeException : Exception
+ {
+ public ValueOutOfRangeException() { }
+
+ public ValueOutOfRangeException(string message) : base(message)
+ {
+ }
+
+ public ValueOutOfRangeException(string message, Exception inner) : base(message, inner)
+ {
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Helpers/CreatorDiagram.cs b/Lab 2/Belianin_2/MyCustomComponents/Helpers/CreatorDiagram.cs
new file mode 100644
index 0000000..f147081
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Helpers/CreatorDiagram.cs
@@ -0,0 +1,289 @@
+using DocumentFormat.OpenXml;
+using DocumentFormat.OpenXml.Drawing;
+using DocumentFormat.OpenXml.Drawing.Charts;
+using MyCustomComponents.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Helpers
+{
+ // Класс CreatorDiagram отвечает за создание диаграмм
+ public class CreatorDiagram
+ {
+ // Порядок и индекс используются для нумерации серий на диаграмме
+ private static uint order = 0u;
+
+ private static uint index = 1u;
+
+ // Метод GeneratePieChart генерирует круговую диаграмму на основе конфигурации
+ public static DocumentFormat.OpenXml.Drawing.Charts.Chart GeneratePieChart(WordWithDiagramConfig config)
+ {
+ // Создаем объект PieChart
+ PieChart pieChart = new PieChart();
+
+ // Добавляем первую серию данных в диаграмму
+ pieChart.Append(GeneratePieChartSeries(config.Data.First().Key, config.Data.First().Value));
+
+ // Создаем область построения (PlotArea) для диаграммы
+ // Добавляем макет для более гибкого управления размещением элементов. Добавляем круговую диаграмму в область построения
+ PlotArea plotArea = new PlotArea();
+ plotArea.Append(new Layout());
+ plotArea.Append(pieChart);
+
+ // Возвращаем объект диаграммы с заголовком и расположением легенды
+ return GenerateChart(config.ChartTitle, plotArea, config.LegendLocation);
+ }
+
+ private static DocumentFormat.OpenXml.Drawing.Charts.Chart GenerateChart(string titleText, PlotArea plotArea, Location legendLocation)
+ {
+ DocumentFormat.OpenXml.Drawing.Charts.Chart chart = new DocumentFormat.OpenXml.Drawing.Charts.Chart();
+
+ // Проверяем текст заголовка и добавляем его
+ if (titleText.HaveText())
+ {
+ chart.Append(GenerateTitle(titleText));
+ }
+ else
+ {
+ chart.Append(new AutoTitleDeleted
+ {
+ Val = (BooleanValue)true
+ });
+ }
+
+ // Определяем позицию легенды на основе переданного значения
+ LegendPositionValues position = legendLocation switch
+ {
+ Location.Top => LegendPositionValues.Top,
+ Location.Right => LegendPositionValues.Right,
+ Location.Left => LegendPositionValues.Left,
+ _ => LegendPositionValues.Bottom,
+ };
+
+ // Добавляем область построения и легенду к диаграмме
+ chart.Append(plotArea);
+ chart.Append(GenerateLegend(position));
+
+ // Устанавливаем видимость только для отображаемых данных
+ chart.Append(new PlotVisibleOnly
+ {
+ Val = (BooleanValue)true
+ });
+
+ return chart;
+ }
+
+ // Метод создает объект легенды для диаграммы
+ private static Legend GenerateLegend(LegendPositionValues position)
+ {
+ // Свойства текста для легенды
+ ParagraphProperties paragraphProperties = new ParagraphProperties();
+ paragraphProperties.Append(new DefaultRunProperties());
+
+ Paragraph paragraph = new Paragraph();
+ paragraph.Append(paragraphProperties);
+ paragraph.Append(new EndParagraphRunProperties());
+
+ TextProperties textProperties = new TextProperties();
+ textProperties.Append(new BodyProperties());
+ textProperties.Append(new ListStyle());
+ textProperties.Append(paragraph);
+
+ // Создаем объект легенды с заданной позицией
+ Legend legend = new Legend();
+ legend.Append(new LegendPosition
+ {
+ Val = (EnumValue)position
+ });
+
+ legend.Append(new Layout());
+ legend.Append(new Overlay
+ {
+ Val = (BooleanValue)false
+ });
+
+ // Добавляем свойства текста к легенде
+ legend.Append(textProperties);
+
+ return legend;
+ }
+
+ // Метод создает объект заголовка для диаграммы
+ private static Title GenerateTitle(string titleText)
+ {
+ // Создаем объект Run для текста заголовка
+ Run run = new Run();
+ run.Append(new RunProperties
+ {
+ FontSize = (Int32Value)1100
+ });
+
+ run.Append(new Text(titleText)); // Добавялем текст заголовка
+
+ // Свойства абзаца для заголовка
+ ParagraphProperties paragraphProperties = new ParagraphProperties();
+ paragraphProperties.Append(new DefaultRunProperties
+ {
+ FontSize = (Int32Value)1100
+ });
+
+ Paragraph paragraph = new Paragraph();
+ paragraph.Append(paragraphProperties);
+ paragraph.Append(run);
+
+ // Создаем RichText, чтобы включить заголовок в диаграмму
+ RichText richText = new RichText();
+ richText.Append(new BodyProperties());
+ richText.Append(new ListStyle());
+ richText.Append(paragraph);
+
+ ChartText chartText = new ChartText();
+ chartText.Append(richText);
+
+ // Создаем объект Title, содержащий текст заголовка
+ Title title = new Title();
+ title.Append(chartText);
+ title.Append(new Layout()); // Добавляем макет
+
+ // Производим наложение
+ title.Append(new Overlay
+ {
+ Val = (BooleanValue)false
+ });
+
+ return title;
+ }
+
+ // Метод создает текст для серий данных
+ private static SeriesText GenerateSeriesText(string seriesName)
+ {
+ StringPoint stringPoint = new StringPoint
+ {
+ Index = (UInt32Value)0u
+ };
+
+ stringPoint.Append(new NumericValue
+ {
+ Text = seriesName
+ });
+
+ // Кэш строковых значений
+ StringCache stringCache = new StringCache();
+ stringCache.Append(new PointCount
+ {
+ Val = (UInt32Value)1u
+ });
+
+ stringCache.Append(stringPoint);
+
+ StringReference stringReference = new StringReference();
+ stringReference.Append(stringCache);
+
+ SeriesText seriesText = new SeriesText();
+ seriesText.Append(stringReference);
+
+ return seriesText;
+ }
+
+ // Метод создает данные оси категорий
+ private static CategoryAxisData GenerateCategoryAxisData(string[] data)
+ {
+ uint number = (uint)data.Length;
+ NumberingCache numberingCache = GenerateNumberingCache(number);
+
+ for (uint number2 = 0u; number2 < number; number2++)
+ {
+ numberingCache.Append(GenerateNumericPoint(number2, data[number2].ToString()));
+ }
+
+ NumberReference numberReference = new NumberReference();
+ numberReference.Append(numberingCache);
+
+ CategoryAxisData categoryAxisData = new CategoryAxisData();
+ categoryAxisData.Append(numberReference);
+
+ return categoryAxisData;
+ }
+
+ // Метод создает объект значений для диаграммы
+ private static Values GenerateValues(double[] data)
+ {
+ uint number = (uint)data.Length;
+ NumberingCache numberingCache = GenerateNumberingCache(number);
+
+ for (uint number2 = 0u; number2 < number; number2++)
+ {
+ numberingCache.Append(GenerateNumericPoint(number2, data[number2].ToString()));
+ }
+
+ NumberReference numberReference = new NumberReference();
+ numberReference.Append(numberingCache);
+
+ Values values = new Values();
+ values.Append(numberReference);
+
+ return values;
+ }
+
+ // Метод создает кэш для числовых данных
+ private static NumberingCache GenerateNumberingCache(uint numberPoints)
+ {
+ NumberingCache numberingCache = new NumberingCache();
+ numberingCache.Append(new FormatCode
+ {
+ Text = "General"
+ });
+
+ numberingCache.Append(new PointCount
+ {
+ Val = (UInt32Value)numberPoints
+ });
+
+ return numberingCache;
+ }
+
+ // Метод создает числовую точку данных
+ private static NumericPoint GenerateNumericPoint(UInt32Value idx, string text)
+ {
+ NumericPoint numericPoint = new NumericPoint
+ {
+ Index = idx
+ };
+ numericPoint.Append(new NumericValue
+ {
+ Text = text
+ });
+
+ return numericPoint;
+ }
+
+ // Метод создает серию данных для круговой диаграммы
+ private static PieChartSeries GeneratePieChartSeries(string seriesName, List<(int Date, double Value)> data)
+ {
+ // Создаем объект серии для круговой диаграммы
+ PieChartSeries pieChartSeries = new PieChartSeries();
+ pieChartSeries.Append(new DocumentFormat.OpenXml.Drawing.Charts.Index
+ {
+ Val = (UInt32Value)index
+ });
+ pieChartSeries.Append(new Order
+ {
+ Val = (UInt32Value)order
+ });
+
+ // Добавляем текст серии, данные оси категорий и значения
+ pieChartSeries.Append(GenerateSeriesText(seriesName));
+ pieChartSeries.Append(GenerateCategoryAxisData(data.Select(((int Date, double Value) c) => c.Date.ToString()).ToArray()));
+ pieChartSeries.Append(GenerateValues(data.Select(((int Date, double Value) v) => v.Value).ToArray()));
+
+ index++;
+ order++;
+
+ return pieChartSeries;
+ }
+
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Helpers/DiagramService.cs b/Lab 2/Belianin_2/MyCustomComponents/Helpers/DiagramService.cs
new file mode 100644
index 0000000..05faa9d
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Helpers/DiagramService.cs
@@ -0,0 +1,157 @@
+using DocumentFormat.OpenXml.Drawing.Charts;
+using DocumentFormat.OpenXml.Drawing;
+using DocumentFormat.OpenXml.Packaging;
+using DocumentFormat.OpenXml;
+using MyCustomComponents.Models;
+using System;
+using DocumentFormat.OpenXml.Drawing.Wordprocessing;
+using DocumentFormat.OpenXml.Wordprocessing;
+
+namespace MyCustomComponents.Helpers
+{
+ public class DiagramService
+ {
+ // Хранит документ Word
+ private Document _document = null;
+
+ // Хранит тело документа Word
+ private Body _body = null;
+
+ // Хранит диаграмму (график), которая будет добавлена в документ
+ private DocumentFormat.OpenXml.Drawing.Charts.Chart _chart;
+
+ // Свойство для создания или получения документа
+ private Document Document
+ {
+ get
+ {
+ if (_document == null)
+ {
+ _document = new Document();
+ }
+
+ return _document;
+ }
+ }
+
+ // Свойство для создания или получения тела документа
+ private Body Body
+ {
+ get
+ {
+ if (_body == null)
+ {
+ _body = Document.AppendChild(new Body());
+ }
+
+ return _body;
+ }
+ }
+
+ public DiagramService()
+ {
+ _document = new Document();
+ _body = _document.AppendChild(new Body());
+ }
+
+ // Метод для создания документа с диаграммой
+ public void CreateHeader(string header)
+ {
+ DocumentFormat.OpenXml.Wordprocessing.Paragraph paragraph = Body.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Paragraph());
+ DocumentFormat.OpenXml.Wordprocessing.Run run = paragraph.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Run());
+
+ run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.RunProperties(new Bold()));
+ run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Text(header));
+ }
+
+ public void SaveDoc(string filepath)
+ {
+ if (filepath.IsEmpty())
+ {
+ throw new ArgumentNullException("Имя файла не задано");
+ }
+
+ if (_document == null || _body == null)
+ {
+ throw new ArgumentNullException("Документ не сформирован, сохранять нечего");
+ }
+
+ using WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Create(filepath, WordprocessingDocumentType.Document);
+ MainDocumentPart mainDocumentPart = wordprocessingDocument.AddMainDocumentPart();
+ mainDocumentPart.Document = Document;
+
+ if (_chart != null)
+ {
+ ChartPart chartPart = mainDocumentPart.AddNewPart("rId110");
+ ChartSpace chartSpace = new ChartSpace();
+ chartSpace.Append(new EditingLanguage
+ {
+ Val = (StringValue)"en-us"
+ });
+
+ chartSpace.Append(_chart);
+ ChartShapeProperties chartShapeProperties = new ChartShapeProperties();
+ DocumentFormat.OpenXml.Drawing.Outline outline = new DocumentFormat.OpenXml.Drawing.Outline();
+
+ outline.Append(new NoFill());
+ chartShapeProperties.Append(outline);
+ chartSpace.Append(chartShapeProperties);
+ chartPart.ChartSpace = chartSpace;
+
+ GeneratePartContent(mainDocumentPart);
+ }
+ }
+
+ private static void GeneratePartContent(MainDocumentPart mainPart)
+ {
+ DocumentFormat.OpenXml.Wordprocessing.Paragraph paragraph = new DocumentFormat.OpenXml.Wordprocessing.Paragraph
+ {
+ RsidParagraphAddition = (HexBinaryValue)"00C75AEB",
+ RsidRunAdditionDefault = (HexBinaryValue)"000F3EFF"
+ };
+
+ DocumentFormat.OpenXml.Wordprocessing.Run run = new DocumentFormat.OpenXml.Wordprocessing.Run();
+ Drawing drawing = new Drawing();
+ Inline inline = new Inline();
+
+ inline.Append(new Extent
+ {
+ Cx = (Int64Value)5274310L,
+ Cy = (Int64Value)3076575L
+ });
+
+ DocProperties docProperties = new DocProperties
+ {
+ Id = (UInt32Value)1u,
+ Name = (StringValue)"Chart 1"
+ };
+
+ inline.Append(docProperties);
+ Graphic graphic = new Graphic();
+
+ GraphicData graphicData = new GraphicData
+ {
+ Uri = (StringValue)"http://schemas.openxmlformats.org/drawingml/2006/chart"
+ };
+
+ ChartReference chartReference = new ChartReference
+ {
+ Id = (StringValue)"rId110"
+ };
+
+ graphicData.Append(chartReference);
+ graphic.Append(graphicData);
+ inline.Append(graphic);
+ drawing.Append(inline);
+
+ run.Append(drawing);
+ paragraph.Append(run);
+ mainPart.Document.Body!.Append(paragraph);
+ }
+
+ public void CreatePieChart(WordWithDiagramConfig config)
+ {
+ _chart = CreatorDiagram.GeneratePieChart(config);
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Helpers/ExtensionConfig.cs b/Lab 2/Belianin_2/MyCustomComponents/Helpers/ExtensionConfig.cs
new file mode 100644
index 0000000..5cf0531
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Helpers/ExtensionConfig.cs
@@ -0,0 +1,210 @@
+using MyCustomComponents.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Helpers
+{
+ public static class ExtensionConfig
+ {
+ // Проверяет поля в объекте WordConfig
+ public static void CheckFields(this WordConfig config)
+ {
+ if (config.FilePath.IsEmpty())
+ {
+ throw new ArgumentNullException("Имя файла не задано");
+ }
+
+ if (config.Header.IsEmpty())
+ {
+ throw new ArgumentNullException("Заголовок документа не задан");
+ }
+ }
+
+ // Проверяет поля в объекте WordWithDiagramConfig
+ public static void CheckFields(this WordWithDiagramConfig config)
+ {
+ // Используем метод проверки базового WordConfig
+ ((WordConfig)config).CheckFields();
+
+ if (config.ChartTitle.IsEmpty())
+ {
+ throw new ArgumentNullException("Заголовок диаграммы не задан");
+ }
+
+ // Проверка на наличие данных для диаграммы
+ if (config.Data == null || config.Data.Count == 0 || config.Data.Any>>
+ ((KeyValuePair> x) => x.Key.IsEmpty() || x.Value == null || x.Value.Count == 0))
+ {
+ throw new ArgumentNullException("Нет данных для заполнения диаграммы");
+ }
+ }
+
+ // Проверяет поля в объекте WordWithImageConfig
+ public static void CheckFields(this WordWithImageConfig config)
+ {
+ // Используем метод проверки базового WordConfig
+ ((WordConfig)config).CheckFields();
+
+ // Проверка на наличие изображений
+ if (config.Images == null || config.Images.Count == 0 || config.Images.All((byte[] x) => x == null || x.Length == 0))
+ {
+ throw new ArgumentNullException("Нет изображений для вставки в документ");
+ }
+ }
+
+ // Универсальный метод проверки полей для WordWithTableDataConfig
+ public static void CheckFields(this WordWithTableDataConfig config)
+ {
+ WordWithTableDataConfig config2 = config;
+
+ // Используем метод проверки базового WordConfig
+ ((WordConfig)config2).CheckFields();
+
+ // Проверка на наличие данных по ширине колонок
+ if (config2.ColumnsRowsWidth == null || config2.ColumnsRowsWidth.Count == 0)
+ {
+ throw new ArgumentNullException("Нет данных по ширине колонок таблицы");
+ }
+
+ // Проверка на наличие данных по объединению колонок (если используется объединение)
+ if (config2.UseUnion && (config2.ColumnUnion == null || config2.ColumnUnion.Count == 0))
+ {
+ throw new ArgumentNullException("Нет данных по объединению колонок таблицы");
+ }
+
+ // Проверка заголовков таблицы
+ if (config2.Headers == null || config2.Headers.Count == 0 || config2.Headers.Any<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.Header.IsEmpty()))
+ {
+ throw new ArgumentNullException("Нет данных по заголовкам таблицы");
+ }
+
+ // Проверка на наличие данных для таблицы
+ if (config2.Data == null || config2.Data.Count == 0)
+ {
+ throw new ArgumentNullException("Нет данных для заполнения таблицы");
+ }
+
+ // Если объединение колонок не используется, выходим из метода
+ if (!config2.UseUnion)
+ {
+ return;
+ }
+
+ // Проверка на выход объединения ячеек за границы таблицы
+ if (config2.ColumnsRowsWidth.Count < config2.ColumnUnion[config2.ColumnUnion.Count - 1].StartIndex + config2.ColumnUnion[config2.ColumnUnion.Count - 1].Count - 1)
+ {
+ throw new IndexOutOfRangeException("Последнее объединение ячеек выходит за границы таблицы");
+ }
+
+ // Проверка заголовков для колонок до объединений
+ int k;
+ for (k = 0; k < config2.ColumnUnion[0].StartIndex; k++)
+ {
+ int number = config2.Headers.Where<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == k).Count();
+ if (number == 0)
+ {
+ DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(34, 1);
+ defaultInterpolatedStringHandler.AppendLiteral("Для ");
+ defaultInterpolatedStringHandler.AppendFormatted(k);
+ defaultInterpolatedStringHandler.AppendLiteral(" колонки отсутствует заголовок");
+ throw new ArgumentNullException(defaultInterpolatedStringHandler.ToStringAndClear());
+ }
+
+ if (number > 1)
+ {
+ DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(37, 1);
+ defaultInterpolatedStringHandler.AppendLiteral("Для ");
+ defaultInterpolatedStringHandler.AppendFormatted(k);
+ defaultInterpolatedStringHandler.AppendLiteral(" колонки задано более 1 заголовка");
+ throw new ArgumentNullException(defaultInterpolatedStringHandler.ToStringAndClear());
+ }
+ }
+
+ // Проверка объединений колонок на накладки
+ int j;
+ for (j = 0; j < config2.ColumnUnion.Count; j++)
+ {
+ if (j < config2.ColumnUnion.Count - 1 && config2.ColumnUnion[j].StartIndex + config2.ColumnUnion[j].Count - 1 > config2.ColumnUnion[j + 1].StartIndex)
+ {
+ throw new IndexOutOfRangeException("Имеется накладка в объединении ячеек");
+ }
+
+ // Проверка заголовков для колонок 0 и 1 строк
+ int number2 = config2.Headers.Where<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex >= config2.ColumnUnion[j].StartIndex && x.ColumnIndex <= config2.ColumnUnion[j].StartIndex + config2.ColumnUnion[j].Count - 1 && x.RowIndex == 0).Count();
+ if (number2 == 0)
+ {
+ throw new ArgumentNullException("Для колонок 0 строки отсутствует заголовок");
+ }
+
+ if (number2 > 1)
+ {
+ throw new ArgumentNullException("Для колонок 0 строки задано более 1 заголовка");
+ }
+
+ number2 = config2.Headers.Where<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex >= config2.ColumnUnion[j].StartIndex && x.ColumnIndex <= config2.ColumnUnion[j].StartIndex + config2.ColumnUnion[j].Count - 1 && x.RowIndex == 1).Count();
+ if (number2 < config2.ColumnUnion[j].Count)
+ {
+ throw new ArgumentNullException("Для колонок 1 строки не хватает заголовков");
+ }
+
+ if (number2 > config2.ColumnUnion[j].Count)
+ {
+ throw new ArgumentNullException("Для колонок 1 строки задано более требуемого числа заголовков");
+ }
+
+ // Проверка заголовков для колонок между объединениями
+ if (j < config2.ColumnUnion.Count - 1)
+ {
+ number2 = config2.Headers.Where<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex >= config2.ColumnUnion[j].StartIndex + config2.ColumnUnion[j].Count && x.ColumnIndex < config2.ColumnUnion[j + 1].StartIndex && x.RowIndex == 0).Count();
+
+ if (number2 < config2.ColumnUnion[j + 1].StartIndex - (config2.ColumnUnion[j].StartIndex + config2.ColumnUnion[j].Count))
+ {
+ throw new ArgumentNullException("Для колонок не хватает заголовков");
+ }
+
+ if (number2 > config2.ColumnUnion[j + 1].StartIndex - (config2.ColumnUnion[j].StartIndex + config2.ColumnUnion[j].Count))
+ {
+ throw new ArgumentNullException("Для колонок задано более требуемого числа заголовков");
+ }
+
+ number2 = config2.Headers.Where<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex >= config2.ColumnUnion[j].StartIndex + config2.ColumnUnion[j].Count && x.ColumnIndex < config2.ColumnUnion[j + 1].StartIndex && x.RowIndex == 1).Count();
+
+ if (number2 > 0)
+ {
+ throw new ArgumentNullException("Для колонок заданы заголовки 2 уровня, чего быть не должно");
+ }
+ }
+
+ // Проверка заголовков для оставшихся колонок после последнего объединения
+ int i;
+
+ for (i = config2.ColumnUnion[config2.ColumnUnion.Count - 1].StartIndex + config2.ColumnUnion[config2.ColumnUnion.Count - 1].Count; i < config2.ColumnsRowsWidth.Count; i++)
+ {
+ int number3 = config2.Headers.Where<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == i).Count();
+
+ if (number3 == 0)
+ {
+ DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(34, 1);
+ defaultInterpolatedStringHandler.AppendLiteral("Для ");
+ defaultInterpolatedStringHandler.AppendFormatted(i);
+ defaultInterpolatedStringHandler.AppendLiteral(" колонки отсутствует заголовок");
+ throw new ArgumentNullException(defaultInterpolatedStringHandler.ToStringAndClear());
+ }
+
+ if (number3 > 1)
+ {
+ DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(37, 1);
+ defaultInterpolatedStringHandler.AppendLiteral("Для ");
+ defaultInterpolatedStringHandler.AppendFormatted(i);
+ defaultInterpolatedStringHandler.AppendLiteral(" колонки задано более 1 заголовка");
+ throw new ArgumentNullException(defaultInterpolatedStringHandler.ToStringAndClear());
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Helpers/ExtensionString.cs b/Lab 2/Belianin_2/MyCustomComponents/Helpers/ExtensionString.cs
new file mode 100644
index 0000000..d1616e4
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Helpers/ExtensionString.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Helpers
+{
+ public static class ExtensionString
+ {
+ public static bool HaveText(this string str)
+ {
+ return !string.IsNullOrEmpty(str);
+ }
+
+ public static bool IsEmpty(this string str)
+ {
+ return string.IsNullOrEmpty(str);
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Helpers/ImageService.cs b/Lab 2/Belianin_2/MyCustomComponents/Helpers/ImageService.cs
new file mode 100644
index 0000000..def59a4
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Helpers/ImageService.cs
@@ -0,0 +1,209 @@
+using DocumentFormat.OpenXml.Drawing.Wordprocessing;
+using DocumentFormat.OpenXml.Drawing;
+using DocumentFormat.OpenXml;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using DocumentFormat.OpenXml.Packaging;
+using DocumentFormat.OpenXml.Wordprocessing;
+
+namespace MyCustomComponents.Helpers
+{
+ public class ImageService
+ {
+ // Хранит документ Word
+ private Document _document = null;
+
+ // Хранит тело документа Word
+ private Body _body = null;
+
+ // Список байтовых массивов для изображений
+ private List _images = null;
+
+ // Свойство для получения или создания документа Word
+ private Document Document
+ {
+ get
+ {
+ if (_document == null)
+ {
+ _document = new Document();
+ }
+
+ return _document;
+ }
+ }
+
+ // Свойство для получения или создания тела документа Word
+ private Body Body
+ {
+ get
+ {
+ if (_body == null)
+ {
+ _body = Document.AppendChild(new Body());
+ }
+
+ return _body;
+ }
+ }
+
+ // Свойство для получения списка изображений
+ private List Images
+ {
+ get
+ {
+ // Если список изображений еще не создан, инициализируем его
+ if (_images == null)
+ {
+ _images = new List();
+ }
+
+ return _images;
+ }
+ }
+
+ public void CreateHeader(string header)
+ {
+ DocumentFormat.OpenXml.Wordprocessing.Paragraph paragraph = Body.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Paragraph());
+ DocumentFormat.OpenXml.Wordprocessing.Run run = paragraph.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Run());
+ run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.RunProperties(new Bold()));
+ run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Text(header));
+ }
+
+ public void CreateImage(byte[] image)
+ {
+ if (image == null || image.Length == 0)
+ {
+ throw new ArgumentNullException("Картинка не загружена");
+ }
+
+ Images.Add(image);
+ }
+
+ public void SaveDoc(string filepath)
+ {
+ if (filepath.IsEmpty())
+ {
+ throw new ArgumentNullException("Имя файла не задано");
+ }
+
+ if (_document == null || _body == null)
+ {
+ throw new ArgumentNullException("Документ не сформирован, сохранять нечего");
+ }
+
+ using WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Create(filepath, WordprocessingDocumentType.Document);
+ MainDocumentPart mainDocumentPart = wordprocessingDocument.AddMainDocumentPart();
+ mainDocumentPart.Document = Document;
+ if (_images != null)
+ {
+ int num = 0;
+ foreach (byte[] image in _images)
+ {
+ ImagePart imagePart = mainDocumentPart.AddImagePart(ImagePartType.Jpeg);
+ using (MemoryStream memoryStream = new MemoryStream(image))
+ {
+ memoryStream.Position = 0L;
+ imagePart.FeedData(memoryStream);
+ }
+
+ AddImageToBody(mainDocumentPart.GetIdOfPart(imagePart), ++num);
+ }
+ }
+ }
+
+ private void AddImageToBody(string relationshipId, int index)
+ {
+ OpenXmlElement[] array = new OpenXmlElement[1];
+ OpenXmlElement[] obj = new OpenXmlElement[5]
+ {
+ new Extent
+ {
+ Cx = (Int64Value)3000000L,
+ Cy = (Int64Value)3000000L
+ },
+ new EffectExtent
+ {
+ LeftEdge = (Int64Value)0L,
+ TopEdge = (Int64Value)0L,
+ RightEdge = (Int64Value)0L,
+ BottomEdge = (Int64Value)0L
+ },
+ null,
+ null,
+ null
+ };
+ DocProperties obj2 = new DocProperties
+ {
+ Id = (UInt32Value)1u
+ };
+ DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(8, 1);
+ defaultInterpolatedStringHandler.AppendLiteral("Picture ");
+ defaultInterpolatedStringHandler.AppendFormatted(index);
+ obj2.Name = (StringValue)defaultInterpolatedStringHandler.ToStringAndClear();
+ obj[2] = obj2;
+ obj[3] = new DocumentFormat.OpenXml.Drawing.Wordprocessing.NonVisualGraphicFrameDrawingProperties(new GraphicFrameLocks
+ {
+ NoChangeAspect = (BooleanValue)true
+ });
+ OpenXmlElement[] array2 = new OpenXmlElement[1];
+ OpenXmlElement[] array3 = new OpenXmlElement[1];
+ OpenXmlElement[] array4 = new OpenXmlElement[3];
+ OpenXmlElement[] array5 = new OpenXmlElement[2];
+ DocumentFormat.OpenXml.Drawing.Pictures.NonVisualDrawingProperties obj3 = new DocumentFormat.OpenXml.Drawing.Pictures.NonVisualDrawingProperties
+ {
+ Id = (UInt32Value)0u
+ };
+ defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(16, 1);
+ defaultInterpolatedStringHandler.AppendLiteral("New Picture ");
+ defaultInterpolatedStringHandler.AppendFormatted(index);
+ defaultInterpolatedStringHandler.AppendLiteral(".jpg");
+ obj3.Name = (StringValue)defaultInterpolatedStringHandler.ToStringAndClear();
+ array5[0] = obj3;
+ array5[1] = new DocumentFormat.OpenXml.Drawing.Pictures.NonVisualPictureDrawingProperties();
+ array4[0] = new DocumentFormat.OpenXml.Drawing.Pictures.NonVisualPictureProperties(array5);
+ array4[1] = new DocumentFormat.OpenXml.Drawing.Pictures.BlipFill(new Blip(new BlipExtensionList(new BlipExtension
+ {
+ Uri = (StringValue)"{28A0092B-C50C-407E-A947-70E740481C1C}"
+ }))
+ {
+ Embed = (StringValue)relationshipId,
+ CompressionState = (EnumValue)BlipCompressionValues.Print
+ }, new Stretch(new FillRectangle()));
+ array4[2] = new DocumentFormat.OpenXml.Drawing.Pictures.ShapeProperties(new Transform2D(new Offset
+ {
+ X = (Int64Value)0L,
+ Y = (Int64Value)0L
+ }, new Extents
+ {
+ Cx = (Int64Value)990000L,
+ Cy = (Int64Value)792000L
+ }), new PresetGeometry(new AdjustValueList())
+ {
+ Preset = (EnumValue)ShapeTypeValues.Rectangle
+ });
+ array3[0] = new DocumentFormat.OpenXml.Drawing.Pictures.Picture(array4);
+ array2[0] = new GraphicData(array3)
+ {
+ Uri = (StringValue)"http://schemas.openxmlformats.org/drawingml/2006/picture"
+ };
+ obj[4] = new Graphic(array2);
+ array[0] = new Inline(obj)
+ {
+ DistanceFromTop = (UInt32Value)0u,
+ DistanceFromBottom = (UInt32Value)0u,
+ DistanceFromLeft = (UInt32Value)0u,
+ DistanceFromRight = (UInt32Value)0u,
+ EditId = (HexBinaryValue)"50D07946"
+ };
+
+ Drawing drawing = new Drawing(array);
+ Body.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Paragraph(new DocumentFormat.OpenXml.Wordprocessing.Run(drawing)));
+ }
+
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Helpers/TableService.cs b/Lab 2/Belianin_2/MyCustomComponents/Helpers/TableService.cs
new file mode 100644
index 0000000..77002df
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Helpers/TableService.cs
@@ -0,0 +1,288 @@
+using DocumentFormat.OpenXml.Packaging;
+using DocumentFormat.OpenXml.Wordprocessing;
+using DocumentFormat.OpenXml.Drawing;
+using DocumentFormat.OpenXml;
+using MyCustomComponents.Helpers;
+using MyCustomComponents.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Helpers
+{
+ public class TableService
+ {
+ private Document _document = null;
+
+ private Body _body = null;
+
+ private DocumentFormat.OpenXml.Wordprocessing.Table _table = null;
+
+ // Свойство для создания или получения документа
+ private Document Document
+ {
+ get
+ {
+ if (_document == null)
+ {
+ _document = new Document();
+ }
+
+ return _document;
+ }
+ }
+
+ // Свойство для создания или получения содержимого (Body) документа
+ private Body Body
+ {
+ get
+ {
+ if (_body == null)
+ {
+ _body = Document.AppendChild(new Body());
+ }
+
+ return _body;
+ }
+ }
+
+ // Свойство для создания или получения таблицы
+ private DocumentFormat.OpenXml.Wordprocessing.Table Table
+ {
+ get
+ {
+ if (_table == null)
+ {
+ _table = new DocumentFormat.OpenXml.Wordprocessing.Table();
+ }
+
+ return _table;
+ }
+ }
+
+ // Метод для сохранения документа
+ public void SaveDoc(string filepath)
+ {
+ if (filepath.IsEmpty())
+ {
+ throw new ArgumentNullException("Имя файла не задано");
+ }
+
+ if (_document == null || _body == null)
+ {
+ throw new ArgumentNullException("Документ не сформирован, сохранять нечего");
+ }
+
+ if (_table != null)
+ {
+ Body.Append(Table);
+ }
+
+ using WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Create(filepath, WordprocessingDocumentType.Document);
+ MainDocumentPart mainDocumentPart = wordprocessingDocument.AddMainDocumentPart();
+ mainDocumentPart.Document = Document;
+
+ }
+
+ // Метод для загрузки данных в таблицу
+ public void LoadDataToTableWithColumnHeader(string[,] data)
+ {
+ for (int i = 0; i < data.GetLength(0); i++)
+ {
+ DocumentFormat.OpenXml.Wordprocessing.TableRow tableRow = Table.Elements().ElementAt(i);
+
+ for (int j = 0; j < data.GetLength(1); j++)
+ {
+ DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell = new DocumentFormat.OpenXml.Wordprocessing.TableCell();
+ tableCell.Append(new DocumentFormat.OpenXml.Wordprocessing.Paragraph(new DocumentFormat.OpenXml.Wordprocessing.Run(new DocumentFormat.OpenXml.Wordprocessing.Text(data[i, j]))));
+ tableRow.Append(tableCell);
+ }
+ }
+ }
+
+ // Метод для добавления заголовка с объединением колонок
+ private void AddColumnHeaderCellMergeByCols(string header, int rowHeight)
+ {
+ DocumentFormat.OpenXml.Wordprocessing.TableRow tableRow = new DocumentFormat.OpenXml.Wordprocessing.TableRow();
+ int? rowHeight2 = rowHeight;
+
+ DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell = CreateCell(header, null, rowHeight2);
+ tableCell.Append(new HorizontalMerge
+ {
+ Val = (EnumValue)MergedCellValues.Restart
+ });
+
+ tableRow.Append(tableCell);
+ tableCell = new DocumentFormat.OpenXml.Wordprocessing.TableCell(new DocumentFormat.OpenXml.Wordprocessing.Paragraph());
+ tableCell.Append(new HorizontalMerge
+ {
+ Val = (EnumValue)MergedCellValues.Continue
+ });
+
+ tableRow.Append(tableCell);
+ Table.Append(tableRow);
+ }
+
+ // Метод для создания ячейки таблицы
+ private static DocumentFormat.OpenXml.Wordprocessing.TableCell CreateCell(string header, int? columnWidth = null, int? rowHeight = null)
+ {
+ DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell = new DocumentFormat.OpenXml.Wordprocessing.TableCell();
+ DocumentFormat.OpenXml.Wordprocessing.TableCellProperties tableCellProperties = new DocumentFormat.OpenXml.Wordprocessing.TableCellProperties();
+
+ // Задание высоты строки, если указана
+ if (rowHeight.HasValue)
+ {
+ tableCellProperties.Append(new TableRowHeight
+ {
+ Val = (UInt32Value)Convert.ToUInt32(rowHeight)
+ });
+ }
+
+ // Задание ширины колонки, если указана
+ if (columnWidth.HasValue)
+ {
+ tableCellProperties.Append(new TableCellWidth
+ {
+ Width = (StringValue)columnWidth.Value.ToString()
+ });
+ }
+
+ tableCellProperties.Append(new TableCellVerticalAlignment
+ {
+ Val = (EnumValue)TableVerticalAlignmentValues.Center
+ });
+
+ tableCell.Append(tableCellProperties);
+ DocumentFormat.OpenXml.Wordprocessing.Paragraph paragraph = new DocumentFormat.OpenXml.Wordprocessing.Paragraph();
+ DocumentFormat.OpenXml.Wordprocessing.ParagraphProperties paragraphProperties = new DocumentFormat.OpenXml.Wordprocessing.ParagraphProperties();
+
+ paragraphProperties.Append(new Justification
+ {
+ Val = (EnumValue)JustificationValues.Center
+ });
+
+ paragraph.Append(paragraphProperties);
+
+ if (header.HaveText())
+ {
+ DocumentFormat.OpenXml.Wordprocessing.Run run = new DocumentFormat.OpenXml.Wordprocessing.Run();
+ run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.RunProperties(new Bold()));
+ run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Text(header));
+ paragraph.Append(run);
+ }
+
+ tableCell.Append(paragraph);
+ return tableCell;
+ }
+
+ // Метод для создания заголовков колонок
+ public void CreateColumnHeader(WordWithTableConfig config)
+ {
+ // Логика создания заголовков таблицы с объединением ячеек
+ int k;
+ for (k = 0; k < config.ColumnUnion[0].StartIndex; k++)
+ {
+ AddColumnHeaderCellMergeByCols(config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == k).Item3, config.ColumnsRowsWidth[k].Row);
+ }
+
+ int j;
+ for (j = 0; j < config.ColumnUnion.Count; j++)
+ {
+ int l;
+ for (l = config.ColumnUnion[j].StartIndex; l < config.ColumnUnion[j].StartIndex + config.ColumnUnion[j].Count; l++)
+ {
+ DocumentFormat.OpenXml.Wordprocessing.TableRow tableRow = new DocumentFormat.OpenXml.Wordprocessing.TableRow();
+
+ if (l == config.ColumnUnion[j].StartIndex)
+ {
+ DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell = CreateCell(config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == l && x.RowIndex == 0).Item3);
+
+ tableCell.Append(new VerticalMerge
+ {
+ Val = (EnumValue)MergedCellValues.Restart
+ });
+
+ tableRow.Append(tableCell);
+ }
+ else
+ {
+ DocumentFormat.OpenXml.Wordprocessing.TableCell tableCell2 = new DocumentFormat.OpenXml.Wordprocessing.TableCell(new DocumentFormat.OpenXml.Wordprocessing.Paragraph());
+
+ tableCell2.Append(new VerticalMerge
+ {
+ Val = (EnumValue)MergedCellValues.Continue
+ });
+
+ tableRow.Append(tableCell2);
+ }
+
+ OpenXmlElement[] array = new OpenXmlElement[1];
+ string item = config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == l && x.RowIndex == 1).Item3;
+ int? rowHeight = config.ColumnsRowsWidth[l].Row;
+
+ array[0] = CreateCell(item, null, rowHeight);
+ tableRow.Append(array);
+ Table.Append(tableRow);
+ }
+
+ if (j >= config.ColumnUnion.Count - 1)
+ {
+ continue;
+ }
+
+ for (int m = config.ColumnUnion[j].StartIndex + config.ColumnUnion[j].Count; m < config.ColumnUnion[j + 1].StartIndex; m++)
+ {
+ AddColumnHeaderCellMergeByCols(config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == j).Item3, config.ColumnsRowsWidth[j].Row);
+ }
+ }
+
+ int i;
+ for (i = config.ColumnUnion[config.ColumnUnion.Count - 1].StartIndex + config.ColumnUnion[config.ColumnUnion.Count - 1].Count; i < config.ColumnsRowsWidth.Count; i++)
+ {
+ AddColumnHeaderCellMergeByCols(config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == i).Item3, config.ColumnsRowsWidth[i].Row);
+ }
+ }
+
+ // Метод для создания таблицы с заголовком
+ public void CreateTableWithHeader()
+ {
+ Table.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.TableProperties(new TableBorders(new DocumentFormat.OpenXml.Wordprocessing.TopBorder
+ {
+ Val = new EnumValue(BorderValues.Single),
+ Size = (UInt32Value)12u
+ }, new DocumentFormat.OpenXml.Wordprocessing.BottomBorder
+ {
+ Val = new EnumValue(BorderValues.Single),
+ Size = (UInt32Value)12u
+ }, new DocumentFormat.OpenXml.Wordprocessing.LeftBorder
+ {
+ Val = new EnumValue(BorderValues.Single),
+ Size = (UInt32Value)12u
+ }, new DocumentFormat.OpenXml.Wordprocessing.RightBorder
+ {
+ Val = new EnumValue(BorderValues.Single),
+ Size = (UInt32Value)12u
+ }, new DocumentFormat.OpenXml.Wordprocessing.InsideHorizontalBorder
+ {
+ Val = new EnumValue(BorderValues.Single),
+ Size = (UInt32Value)12u
+ }, new DocumentFormat.OpenXml.Wordprocessing.InsideVerticalBorder
+ {
+ Val = new EnumValue(BorderValues.Single),
+ Size = (UInt32Value)12u
+ })));
+ }
+
+ // Метод для создания заголовка документа
+ public void CreateHeader(string header)
+ {
+ DocumentFormat.OpenXml.Wordprocessing.Paragraph paragraph = Body.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Paragraph());
+ DocumentFormat.OpenXml.Wordprocessing.Run run = paragraph.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Run());
+
+ run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.RunProperties(new Bold()));
+ run.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Text(header));
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Models/Location.cs b/Lab 2/Belianin_2/MyCustomComponents/Models/Location.cs
new file mode 100644
index 0000000..5e9180c
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Models/Location.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Models
+{
+ public enum Location
+ {
+ Left,
+ Right,
+ Top,
+ Bottom
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Models/WordConfig.cs b/Lab 2/Belianin_2/MyCustomComponents/Models/WordConfig.cs
new file mode 100644
index 0000000..f065806
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Models/WordConfig.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Models
+{
+ public class WordConfig
+ {
+ public string FilePath { get; set; }
+
+ public string Header { get; set; }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Models/WordWithDiagramConfig.cs b/Lab 2/Belianin_2/MyCustomComponents/Models/WordWithDiagramConfig.cs
new file mode 100644
index 0000000..6302fbf
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Models/WordWithDiagramConfig.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Models
+{
+ public class WordWithDiagramConfig : WordConfig
+ {
+ public string ChartTitle { get; set; }
+
+ public Location LegendLocation { get; set; }
+
+ public Dictionary> Data { get; set; }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Models/WordWithImageConfig.cs b/Lab 2/Belianin_2/MyCustomComponents/Models/WordWithImageConfig.cs
new file mode 100644
index 0000000..c646098
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Models/WordWithImageConfig.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Models
+{
+ public class WordWithImageConfig : WordConfig
+ {
+ public List Images { get; set; }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Models/WordWithTableConfig.cs b/Lab 2/Belianin_2/MyCustomComponents/Models/WordWithTableConfig.cs
new file mode 100644
index 0000000..c6bc3c8
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Models/WordWithTableConfig.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Models
+{
+ public class WordWithTableConfig : WordConfig
+ {
+ public bool UseUnion { get; set; }
+
+ public (int Columns, int Rows) ColumnsRowsDataCount { get; set; }
+
+ public List<(int Column, int Row)> ColumnsRowsWidth { get; set; }
+
+ public List<(int StartIndex, int Count)> ColumnUnion { get; set; }
+
+ public List<(int ColumnIndex, int RowIndex, string Header, string PropertyName)> Headers { get; set; }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/Models/WordWithTableDataConfig.cs b/Lab 2/Belianin_2/MyCustomComponents/Models/WordWithTableDataConfig.cs
new file mode 100644
index 0000000..c2826bd
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/Models/WordWithTableDataConfig.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents.Models
+{
+ public class WordWithTableDataConfig : WordWithTableConfig
+ {
+ public List Data { get; set; }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/MyCustomComponents.csproj b/Lab 2/Belianin_2/MyCustomComponents/MyCustomComponents.csproj
new file mode 100644
index 0000000..736d42d
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/MyCustomComponents.csproj
@@ -0,0 +1,16 @@
+
+
+
+ net6.0-windows
+ enable
+ true
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/Lab 2/Belianin_2/MyCustomComponents/WordWithDiagram.Designer.cs b/Lab 2/Belianin_2/MyCustomComponents/WordWithDiagram.Designer.cs
new file mode 100644
index 0000000..45c7c22
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/WordWithDiagram.Designer.cs
@@ -0,0 +1,36 @@
+namespace MyCustomComponents
+{
+ partial class WordWithDiagram
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ 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/Lab 2/Belianin_2/MyCustomComponents/WordWithDiagram.cs b/Lab 2/Belianin_2/MyCustomComponents/WordWithDiagram.cs
new file mode 100644
index 0000000..74cdc10
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/WordWithDiagram.cs
@@ -0,0 +1,53 @@
+using DocumentFormat.OpenXml.Drawing.Charts;
+using DocumentFormat.OpenXml.Drawing.Wordprocessing;
+using DocumentFormat.OpenXml.Drawing;
+using DocumentFormat.OpenXml.Packaging;
+using DocumentFormat.OpenXml;
+using MyCustomComponents.Helpers;
+using MyCustomComponents.Models;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using DocumentFormat.OpenXml.Wordprocessing;
+
+namespace MyCustomComponents
+{
+ public partial class WordWithDiagram : Component
+ {
+ private DiagramService creator;
+
+ // Конструктор по умолчанию
+ public WordWithDiagram()
+ {
+ InitializeComponent();
+ creator = new DiagramService();
+ }
+
+ // Конструктор с контейнером для компонентов
+ public WordWithDiagram(IContainer container)
+ {
+ container.Add(this);
+
+ InitializeComponent();
+ creator = new DiagramService();
+ }
+
+ public void CreateDoc(WordWithDiagramConfig config)
+ {
+ config.CheckFields();
+
+ // Создание заголовка
+ creator.CreateHeader(config.Header);
+
+ // Создание диаграммы
+ creator.CreatePieChart(config);
+
+ // Сохранение в файл
+ creator.SaveDoc(config.FilePath);
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/WordWithImages.Designer.cs b/Lab 2/Belianin_2/MyCustomComponents/WordWithImages.Designer.cs
new file mode 100644
index 0000000..f647659
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/WordWithImages.Designer.cs
@@ -0,0 +1,36 @@
+namespace MyCustomComponents
+{
+ partial class WordWithImages
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ 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/Lab 2/Belianin_2/MyCustomComponents/WordWithImages.cs b/Lab 2/Belianin_2/MyCustomComponents/WordWithImages.cs
new file mode 100644
index 0000000..9b34690
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/WordWithImages.cs
@@ -0,0 +1,59 @@
+using DocumentFormat.OpenXml.Drawing.Wordprocessing;
+using DocumentFormat.OpenXml.Drawing;
+using DocumentFormat.OpenXml.Packaging;
+using DocumentFormat.OpenXml;
+using MyCustomComponents.Helpers;
+using MyCustomComponents.Models;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using DocumentFormat.OpenXml.Wordprocessing;
+using DocumentFormat.OpenXml.Drawing.Charts;
+using DocumentFormat.OpenXml.Drawing.Diagrams;
+using System.Reflection;
+
+namespace MyCustomComponents
+{
+ public partial class WordWithImages : Component
+ {
+ private ImageService creator;
+
+ // Конструктор по умолчанию
+ public WordWithImages()
+ {
+ InitializeComponent();
+ creator = new ImageService();
+ }
+
+ // Конструктор с контейнером для компонентов
+ public WordWithImages(IContainer container)
+ {
+ container.Add(this);
+ InitializeComponent();
+ creator = new ImageService();
+ }
+
+ // Метод для создания документа Word с изображениями
+ public void CreateDoc(WordWithImageConfig config)
+ {
+ config.CheckFields();
+
+ // Создание заголовка
+ creator.CreateHeader(config.Header);
+
+ // Создание и добавление всех изображений
+ foreach (byte[] image in config.Images)
+ {
+ creator.CreateImage(image);
+ }
+
+ // Сохранение файла
+ creator.SaveDoc(config.FilePath);
+ }
+ }
+}
diff --git a/Lab 2/Belianin_2/MyCustomComponents/WordWithTable.Designer.cs b/Lab 2/Belianin_2/MyCustomComponents/WordWithTable.Designer.cs
new file mode 100644
index 0000000..d0d7fb2
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/WordWithTable.Designer.cs
@@ -0,0 +1,36 @@
+namespace MyCustomComponents
+{
+ partial class WordWithTable
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ 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/Lab 2/Belianin_2/MyCustomComponents/WordWithTable.cs b/Lab 2/Belianin_2/MyCustomComponents/WordWithTable.cs
new file mode 100644
index 0000000..2196225
--- /dev/null
+++ b/Lab 2/Belianin_2/MyCustomComponents/WordWithTable.cs
@@ -0,0 +1,71 @@
+using MyCustomComponents.Helpers;
+using MyCustomComponents.Models;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MyCustomComponents
+{
+ public partial class WordWithTable : Component
+ {
+ private TableService creator;
+
+ // Конструктор
+ public WordWithTable()
+ {
+ InitializeComponent();
+ creator = new TableService();
+ }
+
+ // Конструктор с контейнером
+ public WordWithTable(IContainer container)
+ {
+ container.Add(this);
+
+ InitializeComponent();
+ creator = new TableService();
+ }
+
+ // Метод для создания документа с таблицей
+ public void CreateDoc(WordWithTableDataConfig config)
+ {
+ config.CheckFields();
+ config.ColumnsRowsDataCount = (config.Data.Count + 2, config.ColumnsRowsWidth.Count);
+
+ // Создание заголовка
+ creator.CreateHeader(config.Header);
+
+ // Создание таблицы с заголовком
+ creator.CreateTableWithHeader();
+
+ // Создание заголовков столбцов
+ creator.CreateColumnHeader(config);
+
+ // Создание массива данных для таблицы
+ string[,] array = new string[config.ColumnsRowsWidth.Count, config.Data.Count];
+ for (int j = 0; j < config.Data.Count; j++)
+ {
+ int i;
+
+ for (i = 0; i < config.ColumnsRowsWidth.Count; i++)
+ {
+ (int, int, string, string) tuple = config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == i && x.RowIndex == 1);
+ if (tuple.Equals(default((int, int, string, string))))
+ {
+ tuple = config.Headers.FirstOrDefault<(int, int, string, string)>(((int ColumnIndex, int RowIndex, string Header, string PropertyName) x) => x.ColumnIndex == i && x.RowIndex == 0);
+ }
+
+ array[i, j] = config.Data[j].GetType().GetProperty(tuple.Item4)!.GetValue(config.Data[j], null)!.ToString();
+ }
+ }
+
+ // Загрузка данных в таблицу и последующее сохранение документа
+ creator.LoadDataToTableWithColumnHeader(array);
+ creator.SaveDoc(config.FilePath);
+ }
+ }
+}
diff --git a/Lab 2/WordWithDiagramDocx.docx b/Lab 2/WordWithDiagramDocx.docx
new file mode 100644
index 0000000..38549d9
Binary files /dev/null and b/Lab 2/WordWithDiagramDocx.docx differ
diff --git a/Lab 2/WordWithImageDocx.docx b/Lab 2/WordWithImageDocx.docx
new file mode 100644
index 0000000..b362b51
Binary files /dev/null and b/Lab 2/WordWithImageDocx.docx differ
diff --git a/Lab 2/WordWithTableDocx.docx b/Lab 2/WordWithTableDocx.docx
new file mode 100644
index 0000000..7b48acb
Binary files /dev/null and b/Lab 2/WordWithTableDocx.docx differ