Готовая лабораторная работа 2

This commit is contained in:
nikbel2004@outlook.com 2024-10-21 02:57:59 +04:00
parent 5c94bfc598
commit 0247578e56
44 changed files with 3455 additions and 0 deletions

View File

@ -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

View File

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="2.20.0" />
<PackageReference Include="Microsoft.Win32.SystemEvents" Version="7.0.0" />
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyCustomComponents\MyCustomComponents.csproj" />
</ItemGroup>
</Project>

View File

@ -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() { }
}
}

View File

@ -0,0 +1,424 @@
namespace DesktopWithMyVisualComponents
{
partial class FormMain
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
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;
}
}

View File

@ -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<Device> 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<string>() { "Значение 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<string> { "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<Device>();
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<byte[]>();
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<Device>
{
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<string, List<(int Date, double Value)>>
{
{ "Серия 1", new List<(int Date, double Value)> { (1, 20), (2, 30), (3, 50) } }
}
});
}
}
}

View File

@ -0,0 +1,69 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="wordWithImages.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="wordWithTable.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>161, 17</value>
</metadata>
<metadata name="wordWithDiagram.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>295, 17</value>
</metadata>
</root>

View File

@ -0,0 +1,17 @@
namespace DesktopWithMyVisualComponents
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[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());
}
}
}

View File

@ -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() { }
}
}

View File

@ -0,0 +1,59 @@
namespace MyCustomComponents
{
partial class CustomInputRangeNumber
{
/// <summary>
/// Обязательная переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Требуемый метод для поддержки конструктора — не изменяйте
/// содержимое этого метода с помощью редактора кода.
/// </summary>
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;
}
}

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,56 @@
namespace MyCustomComponents
{
partial class CustomSelectedCheckedListBoxProperty
{
/// <summary>
/// Обязательная переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Требуемый метод для поддержки конструктора — не изменяйте
/// содержимое этого метода с помощью редактора кода.
/// </summary>
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;
}
}

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,55 @@
namespace MyCustomComponents
{
partial class CustomTreeView
{
/// <summary>
/// Обязательная переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Требуемый метод для поддержки конструктора — не изменяйте
/// содержимое этого метода с помощью редактора кода.
/// </summary>
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;
}
}

View File

@ -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<string>? hierarchy { get; set; }
private Dictionary<string, bool> newBranch { get; set; } = new Dictionary<string, bool>();
// Отдельный публичный метод очистки всех узлов дерева
public void Clear()
{
treeView.Nodes.Clear();
}
// Публичный метод для получения выбранной записи из древовидной структуры
public T GetSelectedNode<T>() 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<T>();
}
// Приватный метод, идущий по узлам вверх (по иерархии)
private T _getNode<T>() 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>(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<TreeNode>().FirstOrDefault(n => n.Text == value)
?? treeView.Nodes.Add(value);
}
else
{
var childNode = currentNode.Nodes.Cast<TreeNode>().FirstOrDefault(n => n.Text == value);
// Проверка нужно ли нам создавать дочерний узел
if (childNode == null || createNewBranch)
{
childNode = currentNode.Nodes.Add(value);
}
// Переходим на уровень этого дочернего узла
currentNode = childNode;
}
if (property == propertyName)
{
break;
}
}
}
public void SetHierarchy(List<string> hierarchy, Dictionary<string, bool> newBranch)
{
this.hierarchy = hierarchy;
this.newBranch = newBranch;
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -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) { }
}
}

View File

@ -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)
{
}
}
}

View File

@ -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) { }
}
}

View File

@ -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)
{
}
}
}

View File

@ -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)
{
}
}
}

View File

@ -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<LegendPositionValues>)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;
}
}
}

View File

@ -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<ChartPart>("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);
}
}
}

View File

@ -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<string, List<(int, double)>>>
((KeyValuePair<string, List<(int Date, double Value)>> 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<T>(this WordWithTableDataConfig<T> config)
{
WordWithTableDataConfig<T> 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());
}
}
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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<byte[]> _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<byte[]> Images
{
get
{
// Если список изображений еще не создан, инициализируем его
if (_images == null)
{
_images = new List<byte[]>();
}
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>)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>)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)));
}
}
}

View File

@ -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<DocumentFormat.OpenXml.Wordprocessing.TableRow>().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>)MergedCellValues.Restart
});
tableRow.Append(tableCell);
tableCell = new DocumentFormat.OpenXml.Wordprocessing.TableCell(new DocumentFormat.OpenXml.Wordprocessing.Paragraph());
tableCell.Append(new HorizontalMerge
{
Val = (EnumValue<MergedCellValues>)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>)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>)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>)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>)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>(BorderValues.Single),
Size = (UInt32Value)12u
}, new DocumentFormat.OpenXml.Wordprocessing.BottomBorder
{
Val = new EnumValue<BorderValues>(BorderValues.Single),
Size = (UInt32Value)12u
}, new DocumentFormat.OpenXml.Wordprocessing.LeftBorder
{
Val = new EnumValue<BorderValues>(BorderValues.Single),
Size = (UInt32Value)12u
}, new DocumentFormat.OpenXml.Wordprocessing.RightBorder
{
Val = new EnumValue<BorderValues>(BorderValues.Single),
Size = (UInt32Value)12u
}, new DocumentFormat.OpenXml.Wordprocessing.InsideHorizontalBorder
{
Val = new EnumValue<BorderValues>(BorderValues.Single),
Size = (UInt32Value)12u
}, new DocumentFormat.OpenXml.Wordprocessing.InsideVerticalBorder
{
Val = new EnumValue<BorderValues>(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));
}
}
}

View File

@ -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
}
}

View File

@ -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; }
}
}

View File

@ -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<string, List<(int Date, double Value)>> Data { get; set; }
}
}

View File

@ -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<byte[]> Images { get; set; }
}
}

View File

@ -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; }
}
}

View File

@ -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<T> : WordWithTableConfig
{
public List<T> Data { get; set; }
}
}

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="2.20.0" />
<PackageReference Include="Microsoft.Win32.SystemEvents" Version="7.0.0" />
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,36 @@
namespace MyCustomComponents
{
partial class WordWithDiagram
{
/// <summary>
/// Обязательная переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Требуемый метод для поддержки конструктора — не изменяйте
/// содержимое этого метода с помощью редактора кода.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@ -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);
}
}
}

View File

@ -0,0 +1,36 @@
namespace MyCustomComponents
{
partial class WordWithImages
{
/// <summary>
/// Обязательная переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Требуемый метод для поддержки конструктора — не изменяйте
/// содержимое этого метода с помощью редактора кода.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@ -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);
}
}
}

View File

@ -0,0 +1,36 @@
namespace MyCustomComponents
{
partial class WordWithTable
{
/// <summary>
/// Обязательная переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором компонентов
/// <summary>
/// Требуемый метод для поддержки конструктора — не изменяйте
/// содержимое этого метода с помощью редактора кода.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@ -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<T>(WordWithTableDataConfig<T> 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);
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.