diff --git a/ProjectHorseRacing/ProjectHorseRacing/Forms/FormDirectoryReport.Designer.cs b/ProjectHorseRacing/ProjectHorseRacing/Forms/FormDirectoryReport.Designer.cs
new file mode 100644
index 0000000..5472e15
--- /dev/null
+++ b/ProjectHorseRacing/ProjectHorseRacing/Forms/FormDirectoryReport.Designer.cs
@@ -0,0 +1,100 @@
+namespace ProjectHorseRacing.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()
+ {
+ ButtonBuild = new Button();
+ checkBoxHorses = new CheckBox();
+ checkBoxJockeys = new CheckBox();
+ checkBoxRace = new CheckBox();
+ SuspendLayout();
+ //
+ // ButtonBuild
+ //
+ ButtonBuild.Location = new Point(204, 72);
+ ButtonBuild.Name = "ButtonBuild";
+ ButtonBuild.Size = new Size(140, 30);
+ ButtonBuild.TabIndex = 7;
+ ButtonBuild.Text = "Сформировать";
+ ButtonBuild.UseVisualStyleBackColor = true;
+ ButtonBuild.Click += ButtonBuild_Click;
+ //
+ // checkBoxHorses
+ //
+ checkBoxHorses.AutoSize = true;
+ checkBoxHorses.Location = new Point(32, 126);
+ checkBoxHorses.Name = "checkBoxHorses";
+ checkBoxHorses.Size = new Size(87, 24);
+ checkBoxHorses.TabIndex = 6;
+ checkBoxHorses.Text = "Лошади";
+ checkBoxHorses.UseVisualStyleBackColor = true;
+ //
+ // checkBoxJockeys
+ //
+ checkBoxJockeys.AutoSize = true;
+ checkBoxJockeys.Location = new Point(32, 76);
+ checkBoxJockeys.Name = "checkBoxJockeys";
+ checkBoxJockeys.Size = new Size(77, 24);
+ checkBoxJockeys.TabIndex = 5;
+ checkBoxJockeys.Text = "Жокеи";
+ checkBoxJockeys.UseVisualStyleBackColor = true;
+ //
+ // checkBoxRace
+ //
+ checkBoxRace.AutoSize = true;
+ checkBoxRace.Location = new Point(32, 25);
+ checkBoxRace.Name = "checkBoxRace";
+ checkBoxRace.Size = new Size(79, 24);
+ checkBoxRace.TabIndex = 4;
+ checkBoxRace.Text = "Скачки";
+ checkBoxRace.UseVisualStyleBackColor = true;
+ //
+ // FormDirectoryReport
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(376, 175);
+ Controls.Add(ButtonBuild);
+ Controls.Add(checkBoxHorses);
+ Controls.Add(checkBoxJockeys);
+ Controls.Add(checkBoxRace);
+ Name = "FormDirectoryReport";
+ StartPosition = FormStartPosition.CenterParent;
+ Text = "Выгрузка справочников";
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private Button ButtonBuild;
+ private CheckBox checkBoxHorses;
+ private CheckBox checkBoxJockeys;
+ private CheckBox checkBoxRace;
+ }
+}
\ No newline at end of file
diff --git a/ProjectHorseRacing/ProjectHorseRacing/Forms/FormDirectoryReport.cs b/ProjectHorseRacing/ProjectHorseRacing/Forms/FormDirectoryReport.cs
new file mode 100644
index 0000000..81f2c23
--- /dev/null
+++ b/ProjectHorseRacing/ProjectHorseRacing/Forms/FormDirectoryReport.cs
@@ -0,0 +1,63 @@
+using ProjectHorseRacing.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 ProjectHorseRacing.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 (!checkBoxRace.Checked && !checkBoxJockeys.Checked && !checkBoxHorses.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, checkBoxRace.Checked, checkBoxJockeys.Checked, checkBoxHorses.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);
+ }
+ }
+
+ private void checkBoxRace_CheckedChanged(object sender, EventArgs e)
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/ProjectHorseRacing/ProjectHorseRacing/Forms/FormDirectoryReport.resx b/ProjectHorseRacing/ProjectHorseRacing/Forms/FormDirectoryReport.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/ProjectHorseRacing/ProjectHorseRacing/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/ProjectHorseRacing/ProjectHorseRacing/ProjectHorseRacing.csproj b/ProjectHorseRacing/ProjectHorseRacing/ProjectHorseRacing.csproj
index b94bfad..3cd7071 100644
--- a/ProjectHorseRacing/ProjectHorseRacing/ProjectHorseRacing.csproj
+++ b/ProjectHorseRacing/ProjectHorseRacing/ProjectHorseRacing.csproj
@@ -10,11 +10,13 @@
+
+
diff --git a/ProjectHorseRacing/ProjectHorseRacing/Reports/DocReport.cs b/ProjectHorseRacing/ProjectHorseRacing/Reports/DocReport.cs
new file mode 100644
index 0000000..f717ffa
--- /dev/null
+++ b/ProjectHorseRacing/ProjectHorseRacing/Reports/DocReport.cs
@@ -0,0 +1,102 @@
+using Microsoft.Extensions.Logging;
+using ProjectHorseRacing.Repositories;
+using ProjectHorseRacing.Repositories.Implementation;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ProjectHorseRacing.Reports;
+
+internal class DocReport
+{
+ private readonly IRaceRepository _raceRepository;
+ private readonly IJockeyRepository _jockeyRepository;
+ private readonly IHorseRepository _horseRepository;
+
+ private readonly ILogger _logger;
+
+ public DocReport(IRaceRepository raceRepository, IJockeyRepository jockeyRepository,
+ IHorseRepository horseRepository, ILogger logger)
+ {
+ _raceRepository = raceRepository ??
+ throw new ArgumentNullException(nameof(raceRepository));
+ _jockeyRepository = jockeyRepository ??
+ throw new ArgumentNullException(nameof(jockeyRepository));
+ _horseRepository = horseRepository ??
+ throw new ArgumentNullException(nameof(horseRepository));
+ _logger = logger ??
+ throw new ArgumentNullException(nameof(logger));
+ }
+
+ public bool CreateDoc(string filePath, bool includeRaces, bool includeJockeys, bool includeHorses)
+ {
+ try
+ {
+ var builder = new WordBuilder(filePath)
+ .AddHeader("Документ со справочниками");
+
+ if (includeRaces)
+ {
+ builder.AddParagraph("Скачки")
+ .AddTable([2400, 2400], GetRaces());
+ }
+
+ if (includeJockeys)
+ {
+ builder.AddParagraph("Жокеи")
+ .AddTable([2400, 1200, 2400, 2400], GetJockeys());
+ }
+
+ if (includeHorses)
+ {
+ builder.AddParagraph("Лошади")
+ .AddTable([2400, 1200, 2400, 2400], GetHorses());
+ }
+ builder.Build();
+ return true;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка при формировании документа");
+ return false;
+ }
+ }
+
+ private List GetRaces()
+ {
+ return [
+ ["Дата", "Место проведения"],
+ .. _raceRepository
+ .ReadRaces().Select
+ (x => new string[] { x.DateTime.ToString(), x.RacePlaceEvent.ToString() }),
+ ];
+ }
+
+ private List GetJockeys()
+ {
+ return [
+ ["Имя", "Фамилия", "Возраст", "Рейтинг"],
+ .. _jockeyRepository
+ .ReadJockeys().Select
+ (x => new string[] { x.FirstName, x.LastName, x.Age.ToString(),
+ x.Rating.ToString() }),
+ ];
+ }
+
+ private List GetHorses()
+ {
+ return [
+ ["Кличка", "Пол", "Возраст", "Характер"],
+ .. _horseRepository
+ .ReadHorses().Select
+ (x => new string[] { x.Nickname, x.HorseGender.ToString(), x.AgeHorse.ToString(),
+ x.HorseCharacters.ToString() }),
+ ];
+ }
+
+
+
+
+}
diff --git a/ProjectHorseRacing/ProjectHorseRacing/Reports/WordBuilder.cs b/ProjectHorseRacing/ProjectHorseRacing/Reports/WordBuilder.cs
new file mode 100644
index 0000000..4f87aa6
--- /dev/null
+++ b/ProjectHorseRacing/ProjectHorseRacing/Reports/WordBuilder.cs
@@ -0,0 +1,109 @@
+using DocumentFormat.OpenXml.Drawing.Charts;
+using DocumentFormat.OpenXml;
+using DocumentFormat.OpenXml.Wordprocessing;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using DocumentFormat.OpenXml.Packaging;
+
+namespace ProjectHorseRacing.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());
+
+ var runProperties = new RunProperties();
+ runProperties.AppendChild(new Bold());
+ run.RunProperties = runProperties;
+
+ 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;
+ }
+}