diff --git a/ProjectHorseRacingOrg/Forms/FormDirectoryReport.Designer.cs b/ProjectHorseRacingOrg/Forms/FormDirectoryReport.Designer.cs
new file mode 100644
index 0000000..8e48340
--- /dev/null
+++ b/ProjectHorseRacingOrg/Forms/FormDirectoryReport.Designer.cs
@@ -0,0 +1,99 @@
+namespace ProjectHorseRacingOrg.Forms
+{
+ partial class FormDirectoryReport
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ checkBoxHorses = new CheckBox();
+ checkBoxJockeys = new CheckBox();
+ checkBoxRaces = new CheckBox();
+ buttonBuild = new Button();
+ SuspendLayout();
+ //
+ // checkBoxHorses
+ //
+ checkBoxHorses.AutoSize = true;
+ checkBoxHorses.Location = new Point(39, 33);
+ checkBoxHorses.Name = "checkBoxHorses";
+ checkBoxHorses.Size = new Size(87, 24);
+ checkBoxHorses.TabIndex = 0;
+ checkBoxHorses.Text = "Лошади";
+ checkBoxHorses.UseVisualStyleBackColor = true;
+ //
+ // checkBoxJockeys
+ //
+ checkBoxJockeys.AutoSize = true;
+ checkBoxJockeys.Location = new Point(39, 87);
+ checkBoxJockeys.Name = "checkBoxJockeys";
+ checkBoxJockeys.Size = new Size(77, 24);
+ checkBoxJockeys.TabIndex = 1;
+ checkBoxJockeys.Text = "Жокеи";
+ checkBoxJockeys.UseVisualStyleBackColor = true;
+ //
+ // checkBoxRaces
+ //
+ checkBoxRaces.AutoSize = true;
+ checkBoxRaces.Location = new Point(39, 147);
+ checkBoxRaces.Name = "checkBoxRaces";
+ checkBoxRaces.Size = new Size(134, 24);
+ checkBoxRaces.TabIndex = 2;
+ checkBoxRaces.Text = "Соревнование";
+ checkBoxRaces.UseVisualStyleBackColor = true;
+ //
+ // buttonBuild
+ //
+ buttonBuild.Location = new Point(212, 84);
+ buttonBuild.Name = "buttonBuild";
+ buttonBuild.Size = new Size(132, 29);
+ buttonBuild.TabIndex = 3;
+ buttonBuild.Text = "Сформировать";
+ buttonBuild.UseVisualStyleBackColor = true;
+ buttonBuild.Click += ButtonBuild_Click;
+ //
+ // FormDirectoryReport
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(412, 228);
+ Controls.Add(buttonBuild);
+ Controls.Add(checkBoxRaces);
+ Controls.Add(checkBoxJockeys);
+ Controls.Add(checkBoxHorses);
+ Name = "FormDirectoryReport";
+ Text = "FormDirectoryReport";
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private CheckBox checkBoxHorses;
+ private CheckBox checkBoxJockeys;
+ private CheckBox checkBoxRaces;
+ private Button buttonBuild;
+ }
+}
\ No newline at end of file
diff --git a/ProjectHorseRacingOrg/Forms/FormDirectoryReport.cs b/ProjectHorseRacingOrg/Forms/FormDirectoryReport.cs
new file mode 100644
index 0000000..a8b4e18
--- /dev/null
+++ b/ProjectHorseRacingOrg/Forms/FormDirectoryReport.cs
@@ -0,0 +1,62 @@
+using ProjectHorseRacingOrg.Reports;
+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;
+using Unity;
+
+namespace ProjectHorseRacingOrg.Forms
+{
+ public partial class FormDirectoryReport : Form
+ {
+ private readonly IUnityContainer _container;
+ public FormDirectoryReport(IUnityContainer container)
+ {
+ InitializeComponent();
+ _container = container ??
+ throw new ArgumentNullException(nameof(container));
+ }
+ private void ButtonBuild_Click(object sender, EventArgs e)
+ {
+ try
+ {
+ if (!checkBoxHorses.Checked && !checkBoxJockeys.Checked && !checkBoxRaces.Checked)
+ {
+ throw new Exception("Не выбран ни один справочник для выгрузки");
+ }
+ var sfd = new SaveFileDialog()
+ {
+ Filter = "Docx Files | *.docx"
+ };
+ if (sfd.ShowDialog() != DialogResult.OK)
+ {
+ throw new Exception("Не выбран файла для отчета");
+ }
+ if
+ (_container.Resolve().CreateDoc(sfd.FileName, checkBoxHorses.Checked,
+ checkBoxJockeys.Checked, checkBoxRaces.Checked))
+ {
+ MessageBox.Show("Документ сформирован",
+ "Формирование документа",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Information);
+ }
+ else
+ {
+ MessageBox.Show("Возникли ошибки при формировании документа.Подробности в логах",
+ "Формирование документа", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message, "Ошибка при создании отчета", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ }
+}
diff --git a/ProjectHorseRacingOrg/Forms/FormDirectoryReport.resx b/ProjectHorseRacingOrg/Forms/FormDirectoryReport.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/ProjectHorseRacingOrg/Forms/FormDirectoryReport.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/ProjectHorseRacingOrg/ProjectHorseRacingOrg.csproj b/ProjectHorseRacingOrg/ProjectHorseRacingOrg.csproj
index 9f5aed5..b341f02 100644
--- a/ProjectHorseRacingOrg/ProjectHorseRacingOrg.csproj
+++ b/ProjectHorseRacingOrg/ProjectHorseRacingOrg.csproj
@@ -10,6 +10,7 @@
+
diff --git a/ProjectHorseRacingOrg/Reports/DocReport.cs b/ProjectHorseRacingOrg/Reports/DocReport.cs
new file mode 100644
index 0000000..c808491
--- /dev/null
+++ b/ProjectHorseRacingOrg/Reports/DocReport.cs
@@ -0,0 +1,89 @@
+using Microsoft.Extensions.Logging;
+using ProjectHorseRacingOrg.Repositories;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ProjectHorseRacingOrg.Reports;
+
+internal class DocReport
+{
+ private readonly IHorseRepository _horseRepository;
+ private readonly IJockeyRepository _jockeyRepository;
+ private readonly IRaceRepository _raceRepository;
+
+ private readonly ILogger _logger;
+ public DocReport(IHorseRepository horseRepository, IJockeyRepository jockeyRepository,
+ IRaceRepository raceRepository, ILogger logger)
+ {
+ _horseRepository = horseRepository ?? throw new ArgumentNullException(nameof(horseRepository));
+
+ _jockeyRepository = jockeyRepository ?? throw new ArgumentNullException(nameof(jockeyRepository));
+
+ _raceRepository = raceRepository ?? throw new ArgumentNullException(nameof(raceRepository));
+
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ }
+ public bool CreateDoc(string filePath, bool includeHorses, bool
+ includeJockeys, bool includeRaces)
+ {
+ try
+ {
+ var builder = new WordBuilder(filePath)
+ .AddHeader("Документ со справочниками");
+ if (includeHorses)
+ {
+ builder.AddParagraph("Лошади")
+ .AddTable([2400, 2400, 1200, 1200],
+ GetHorses());
+ }
+ if (includeJockeys)
+ {
+ builder.AddParagraph("Жокеи")
+ .AddTable([2400, 2400, 2400], GetJockeys());
+ }
+ if (includeRaces)
+ {
+ builder.AddParagraph("Соревнование")
+ .AddTable([2400, 2400, 2400], GetRaces());
+ }
+ builder.Build();
+ return true;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка при формировании документа");
+ return false;
+ }
+ }
+ private List GetHorses()
+ {
+ return [
+ ["Вид лошади", "Имя лошади", "Вес", "Возраст"],
+ .. _horseRepository
+ .ReadHorses()
+ .Select(x => new string[] { x.HorseSpecies, x.HorseNickName, x.Weight.ToString(), x.Age.ToString() }),
+ ];
+ }
+ private List GetJockeys()
+ {
+ return [
+ ["Имя", "Фамилия", "Титул"],
+ .. _jockeyRepository
+ .ReadJockeys()
+ .Select(x => new string[] { x.FirstName, x.LastName, x.JockeyTitle.ToString() }),
+ ];
+ }
+
+ private List GetRaces()
+ {
+ return [
+ ["Тип соревнований", "Название", "Описание"],
+ .. _raceRepository
+ .ReadRaces()
+ .Select(x => new string[] { x.RaceType.ToString(), x.Name, x.Description }),
+ ];
+ }
+}
diff --git a/ProjectHorseRacingOrg/Reports/WordBuilder.cs b/ProjectHorseRacingOrg/Reports/WordBuilder.cs
new file mode 100644
index 0000000..4e0ec96
--- /dev/null
+++ b/ProjectHorseRacingOrg/Reports/WordBuilder.cs
@@ -0,0 +1,127 @@
+using DocumentFormat.OpenXml;
+using DocumentFormat.OpenXml.Packaging;
+using DocumentFormat.OpenXml.Wordprocessing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+
+namespace ProjectHorseRacingOrg.Reports;
+
+internal class WordBuilder
+{
+ private readonly string _filePath;
+
+ private readonly Document _document;
+
+ private readonly Body _body;
+ public WordBuilder(string filePath)
+ {
+ if (string.IsNullOrWhiteSpace(filePath))
+ {
+ throw new ArgumentNullException(nameof(filePath));
+ }
+ if (File.Exists(filePath))
+ {
+ File.Delete(filePath);
+ }
+ _filePath = filePath;
+ _document = new Document();
+ _body = _document.AppendChild(new Body());
+ }
+ public WordBuilder AddHeader(string header)
+ {
+ var paragraph = _body.AppendChild(new Paragraph());
+ var run = paragraph.AppendChild(new Run());
+ run.PrependChild(new RunProperties());
+ run.RunProperties.AddChild(new Bold());
+ run.AppendChild(new Text(header));
+ return this;
+ }
+ public WordBuilder AddParagraph(string text)
+ {
+ var paragraph = _body.AppendChild(new Paragraph());
+ var run = paragraph.AppendChild(new Run());
+ run.AppendChild(new Text(text));
+ return this;
+ }
+ public WordBuilder AddTable(int[] widths, List data)
+ {
+ if (widths == null || widths.Length == 0)
+ {
+ throw new ArgumentNullException(nameof(widths));
+ }
+ if (data == null || data.Count == 0)
+ {
+ throw new ArgumentNullException(nameof(data));
+ }
+ if (data.Any(x => x.Length != widths.Length))
+ {
+ throw new InvalidOperationException("widths.Length != data.Length");
+ }
+ var table = new Table();
+ table.AppendChild(new TableProperties(
+ new TableBorders(
+ new TopBorder()
+ {
+ Val = new EnumValue(BorderValues.Single), Size = 12
+ },
+
+ new BottomBorder()
+ {
+ Val = new EnumValue(BorderValues.Single), Size = 12
+ },
+
+ new LeftBorder()
+ {
+ Val = new EnumValue(BorderValues.Single), Size = 12
+ },
+
+ new RightBorder()
+ {
+ Val = new EnumValue(BorderValues.Single), Size = 12
+ },
+
+ new InsideHorizontalBorder()
+ {
+ Val = new EnumValue(BorderValues.Single), Size = 12
+ },
+
+ new InsideVerticalBorder()
+ {
+ Val = new EnumValue(BorderValues.Single), Size = 12
+ }
+ )
+ ));
+
+ // Заголовок
+ var tr = new TableRow();
+ for (var j = 0; j < widths.Length; ++j)
+ {
+ tr.Append(new TableCell(
+ new TableCellProperties(new TableCellWidth()
+ {
+ Width = widths[j].ToString()
+ }),
+
+ new Paragraph(new Run(new RunProperties(new Bold()), new
+ Text(data.First()[j])))));
+ }
+ table.Append(tr);
+
+ // Данные
+ table.Append(data.Skip(1).Select(x =>
+ new TableRow(x.Select(y => new TableCell(new Paragraph(new Run(new Text(y))))))));
+ _body.Append(table);
+ return this;
+ }
+ public void Build()
+ {
+ using var wordDocument = WordprocessingDocument.Create(_filePath, WordprocessingDocumentType.Document);
+ var mainPart = wordDocument.AddMainDocumentPart();
+ mainPart.Document = _document;
+ }
+
+}