diff --git a/Hospital/HospitalBusinessLogics/BusinessLogics/ReportLogic.cs b/Hospital/HospitalBusinessLogics/BusinessLogics/ReportLogic.cs
new file mode 100644
index 0000000..c1ff9eb
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/BusinessLogics/ReportLogic.cs
@@ -0,0 +1,276 @@
+using HospitalBusinessLogics.OfficePackage;
+using HospitalBusinessLogics.OfficePackage.HelperModels;
+using HospitalContracts.BindingModels;
+using HospitalContracts.BusinessLogicsContracts;
+using HospitalContracts.SearchModels;
+using HospitalContracts.StoragesContracts;
+using HospitalContracts.ViewModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.BusinessLogics
+{
+ ///
+ /// Бизнес-логика для отчетов
+ ///
+ public class ReportLogic : IReportLogic
+ {
+ ///
+ /// Хранилище для сущности "Пациент"
+ ///
+ private readonly IPatientStorage _patientStorage;
+
+ ///
+ /// Хранилище для сущности "Рецепт"
+ ///
+ private readonly IRecipeStorage _recipeStorage;
+
+ ///
+ /// Хранилище для сущности "Процедура"
+ ///
+ private readonly IProcedureStorage _procedureStorage;
+
+ ///
+ /// Хранилище для сущности "Лекарство"
+ ///
+ private readonly IMedicineStorage _medicineStorage;
+
+ ///
+ /// Хранилище для сущности "Болезнь"
+ ///
+ private readonly IDiseaseStorage _diseaseStorage;
+
+ ///
+ /// Взаимодействие с отчетами в формате Word
+ ///
+ private readonly AbstractSaveToWord _saveToWord;
+
+ ///
+ /// Взаимодействие с отчетами в формате Excel
+ ///
+ private readonly AbstractSaveToExcel _saveToExcel;
+
+ ///
+ /// Взаимодействие с отчетами в формате Pdf
+ ///
+ private readonly AbstractSaveToPdf _saveToPdf;
+
+ ///
+ /// Конструктор
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ReportLogic(IPatientStorage patientStorage,
+ IRecipeStorage recipeStorage,
+ IProcedureStorage procedureStorage,
+ IMedicineStorage medicineStorage,
+ IDiseaseStorage diseaseStorage,
+ AbstractSaveToWord saveToWord,
+ AbstractSaveToExcel saveToExcel,
+ AbstractSaveToPdf saveToPdf)
+ {
+ _patientStorage = patientStorage;
+ _recipeStorage = recipeStorage;
+ _procedureStorage = procedureStorage;
+ _medicineStorage = medicineStorage;
+ _diseaseStorage = diseaseStorage;
+
+ _saveToWord = saveToWord;
+ _saveToExcel = saveToExcel;
+ _saveToPdf = saveToPdf;
+ }
+
+ ///
+ /// Получить список рецептов с расшифровкой по процедурам
+ ///
+ ///
+ ///
+ public List GetRecipeProcedures(ReportBindingModel model)
+ {
+ var result = new List();
+
+ // Получаем список рецептов по идентификатору врача
+ var recipes = _recipeStorage.GetFilteredList(new RecipeSearchModel
+ {
+ DoctorId = model.DoctorId
+ });
+
+ // Получаем список всех пациентов,
+ // так как рецепты и процедуры связаны через сущность "Пациент"
+ var patients = _patientStorage.GetFullList();
+
+ // Проходим по списку полученных рецептов
+ foreach (var recipe in recipes)
+ {
+ // Создаём запись
+ var record = new ReportRecipeProceduresViewModel
+ {
+ Recipe = recipe,
+ // HashSet используется для того, чтобы не повторялись процедуры
+ Procedures = new HashSet()
+ };
+
+ // Проходим по списку всех пациентов
+ foreach (var patient in patients)
+ {
+ // Проверяем есть ли у пациента текущий рецепт
+ if (patient.PatientRecipes.ContainsKey(recipe.Id))
+ {
+ // Если есть, то проходим по списку всех процедур пациента
+ foreach (var procedureId in patient.PatientProcedures.Keys)
+ {
+ // Находим процедуру и добавляем в список процедур
+ var procedure = _procedureStorage.GetElement(new ProcedureSearchModel
+ {
+ Id = procedureId
+ });
+ record.Procedures.Add(procedure!);
+ }
+ }
+ }
+
+ // Добавляем запись
+ result.Add(record);
+ }
+
+ return result;
+ }
+
+ ///
+ /// Получить список пациентов с расшифровкой по лекарствам и болезням
+ ///
+ ///
+ ///
+ public List GetPatientsInfo(ReportBindingModel model)
+ {
+ var result = new List();
+
+ // Получаем список рецептов по идентификатору врача
+ // и за определенный период
+ var recipes = _recipeStorage.GetFilteredList(new RecipeSearchModel
+ {
+ DoctorId = model.DoctorId,
+ DateFrom = model.DateFrom,
+ DateTo = model.DateTo
+ });
+
+ // Получаем список всех пациентов
+ var patients = _patientStorage.GetFullList();
+
+ // Сразу получаем список всех заболеваний,
+ // чтобы не запрашивать каждый раз в цикле
+ var diseases = _diseaseStorage.GetFullList();
+
+ // Проходим по списку всех пациентов
+ foreach (var patient in patients)
+ {
+ // Создаем запись
+ var record = new ReportPatientsViewModel
+ {
+ Patient = patient,
+ // HashSet используется для того, чтобы не повторялись лекарства
+ Medicines = new HashSet(),
+ // HashSet используется для того, чтобы не повторялись болезни
+ Diseases = new HashSet()
+ };
+ // Обращался ли пациент в больницу в указанный период
+ bool flag = false;
+
+ // Проходим по списку полученных рецептов
+ foreach (var recipe in recipes)
+ {
+ // Проверяем есть ли у пациента текущий рецепт
+ if (patient.PatientRecipes.ContainsKey(recipe.Id))
+ {
+ // Пациент обращался в больницу в указанный период
+ flag = true;
+
+ // Если есть, то проходим по списку лекарств, связанных с рецептом
+ foreach (var medicineId in recipe.RecipeMedicines.Keys)
+ {
+ // Находим лекарство и добавляем в список лекарств
+ var medicine = _medicineStorage.GetElement(new MedicineSearchModel
+ {
+ Id = medicineId,
+ });
+ record.Medicines.Add(medicine!);
+ }
+
+ // Так же проходим по списку болезней
+ foreach (var disease in diseases)
+ {
+ // Если болезнь относится к текущему рецепту
+ if (disease.RecipeId.Equals(recipe.Id))
+ {
+ // Добавляем в список болезней
+ record.Diseases.Add(disease);
+ }
+ }
+ }
+ }
+
+ // Если пациент обращался в больницу в указанный период,
+ // добавляем запись в отчет
+ if (flag)
+ {
+ result.Add(record);
+ }
+ }
+
+ return result;
+ }
+
+ ///
+ /// Сохранить список рецептов с расшифровкой по процедурам в файл Word
+ ///
+ ///
+ public void SaveRecipeProceduresToWordFile(ReportBindingModel model)
+ {
+ _saveToWord.CreateReport(new WordInfo
+ {
+ FileName = model.FileName,
+ Title = "Список процедур.",
+ RecipeProcedures = GetRecipeProcedures(model)
+ });
+ }
+
+ ///
+ /// Сохранить список рецептов с расшифровкой по процедурам в файл Excel
+ ///
+ ///
+ public void SaveRecipeProceduresToExcelFile(ReportBindingModel model)
+ {
+ _saveToExcel.CreateReport(new ExcelInfo
+ {
+ FileName = model.FileName,
+ Title = "Список процедур.",
+ RecipeProcedures = GetRecipeProcedures(model)
+ });
+ }
+
+ ///
+ /// Сохранить список пациентов с расшифровкой по лекарствам и болезням в Pdf файл
+ ///
+ ///
+ public void SavePatientsInfoToPdfFile(ReportBindingModel model)
+ {
+ _saveToPdf.CreateReport(new PdfInfo
+ {
+ FileName= model.FileName,
+ Title = "Сведения о пациентах.",
+ DateFrom = model.DateFrom!.Value,
+ DateTo = model.DateTo!.Value,
+ PatientsInfo = GetPatientsInfo(model)
+ });
+ }
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/HospitalBusinessLogics.csproj b/Hospital/HospitalBusinessLogics/HospitalBusinessLogics.csproj
index 49d19fc..6455fe3 100644
--- a/Hospital/HospitalBusinessLogics/HospitalBusinessLogics.csproj
+++ b/Hospital/HospitalBusinessLogics/HospitalBusinessLogics.csproj
@@ -7,7 +7,9 @@
+
+
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/AbstractSaveToExcel.cs b/Hospital/HospitalBusinessLogics/OfficePackage/AbstractSaveToExcel.cs
new file mode 100644
index 0000000..8ade3a4
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/AbstractSaveToExcel.cs
@@ -0,0 +1,141 @@
+using DocumentFormat.OpenXml.Presentation;
+using HospitalBusinessLogics.OfficePackage.HelperEnums;
+using HospitalBusinessLogics.OfficePackage.HelperModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage
+{
+ ///
+ /// Абстрактный класс для создания отчета Excel
+ ///
+ public abstract class AbstractSaveToExcel
+ {
+ ///
+ /// Создать отчет Excel
+ ///
+ ///
+ public void CreateReport(ExcelInfo info)
+ {
+ // Создаем файл
+ CreateExcel(info);
+
+ // Создаем заголовок таблицы
+ // "Список процедур."
+ InsertCellInWorksheet(new ExcelCellParameters
+ {
+ ColumnName = "A",
+ RowIndex = 1,
+ Text = info.Title,
+ StyleInfo = ExcelStyleInfoType.Title
+ });
+ // Объединяем ячейки A1:D1 для заголовка таблицы
+ MergeCells(new ExcelMergeParameters
+ {
+ CellFromName = "A1",
+ CellToName = "D1"
+ });
+
+ // Записываем основную информацию
+ uint rowIndex = 2;
+ foreach (var view in info.RecipeProcedures)
+ {
+ // "Рецепт:"
+ InsertCellInWorksheet(new ExcelCellParameters
+ {
+ ColumnName = "A",
+ RowIndex = rowIndex,
+ Text = "Рецепт:",
+ StyleInfo = ExcelStyleInfoType.SubtitleWithBorder
+ });
+
+ // Номер рецепта "№X"
+ InsertCellInWorksheet(new ExcelCellParameters
+ {
+ ColumnName = "B",
+ RowIndex = rowIndex,
+ Text = $"№{view.Recipe.Id}",
+ StyleInfo = ExcelStyleInfoType.TextWithBorder
+ });
+
+ // "Дата выписки:"
+ InsertCellInWorksheet(new ExcelCellParameters
+ {
+ ColumnName = "C",
+ RowIndex = rowIndex,
+ Text = "Дата выписки:",
+ StyleInfo = ExcelStyleInfoType.SubtitleWithBorder
+ });
+
+ // Дата "XX.XX.XXXX"
+ InsertCellInWorksheet(new ExcelCellParameters
+ {
+ ColumnName = "D",
+ RowIndex = rowIndex,
+ Text = $"{view.Recipe.IssueDate.ToShortDateString()}",
+ StyleInfo = ExcelStyleInfoType.TextWithBorder
+ });
+
+ rowIndex++;
+ // "Процедуры:"
+ InsertCellInWorksheet(new ExcelCellParameters
+ {
+ ColumnName = "A",
+ RowIndex = rowIndex,
+ Text = "Процедуры:",
+ StyleInfo = ExcelStyleInfoType.Subtitle
+ });
+
+ // Список процедур
+ foreach (var procedure in view.Procedures)
+ {
+ // "Название процедуры"
+ InsertCellInWorksheet(new ExcelCellParameters
+ {
+ ColumnName = "B",
+ RowIndex = rowIndex,
+ Text = $"{procedure.Name}",
+ StyleInfo = ExcelStyleInfoType.Text
+ });
+ // Объединяем ячейки BX:DX для названия процедуры
+ MergeCells(new ExcelMergeParameters
+ {
+ CellFromName = "B" + rowIndex,
+ CellToName = "D" + rowIndex
+ });
+
+ rowIndex++;
+ }
+ }
+
+ SaveExcel(info);
+ }
+
+ ///
+ /// Создать файл Excel
+ ///
+ ///
+ protected abstract void CreateExcel(ExcelInfo info);
+
+ ///
+ /// Добавить новую ячейку в лист
+ ///
+ ///
+ protected abstract void InsertCellInWorksheet(ExcelCellParameters excelParams);
+
+ ///
+ /// Объединить ячейки
+ ///
+ ///
+ protected abstract void MergeCells(ExcelMergeParameters excelParams);
+
+ ///
+ /// Сохранить файл Excel
+ ///
+ ///
+ protected abstract void SaveExcel(ExcelInfo info);
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/AbstractSaveToPdf.cs b/Hospital/HospitalBusinessLogics/OfficePackage/AbstractSaveToPdf.cs
new file mode 100644
index 0000000..fc03766
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/AbstractSaveToPdf.cs
@@ -0,0 +1,114 @@
+using HospitalBusinessLogics.OfficePackage.HelperEnums;
+using HospitalBusinessLogics.OfficePackage.HelperModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage
+{
+ ///
+ /// Абстрактный класс для создания отчета Pdf
+ ///
+ public abstract class AbstractSaveToPdf
+ {
+ ///
+ /// Создать отчет Pdf
+ ///
+ ///
+ public void CreateReport(PdfInfo info)
+ {
+ // Создаем файл
+ CreatePdf(info);
+
+ // Создаем заголовок
+ // "Сведения по пациентам."
+ CreateParagraph(new PdfParagraph
+ {
+ Text = info.Title,
+ Style = "NormalTitle"
+ });
+
+ // Период выборки данных
+ // "с XX.XX.XXXX по XX.XX.XXXX"
+ CreateParagraph(new PdfParagraph
+ {
+ Text = $"с {info.DateFrom.ToShortDateString()} по {info.DateTo.ToShortDateString()}",
+ Style = "Normal"
+ });
+
+ // Создаем таблицу с тремя колонками
+ CreateTable(new List { "7cm", "4cm", "4cm" });
+
+ // Создаем заголовок таблицы
+ // "Пациент" | "Лекарства" | "Болезни"
+ CreateRow(new PdfRowParameters
+ {
+ Texts = new List { "Пациент", "Лекарства", "Болезни" },
+ Style = "NormalTitle",
+ ParagraphAlignment = PdfParagraphAlignmentType.Center
+ });
+
+ // Записываем основную информацию
+ foreach (var view in info.PatientsInfo)
+ {
+ // Записываем имя пациента в первую колонку
+ CreateRow(new PdfRowParameters
+ {
+ Texts= new List { view.Patient.FullName, "", "" },
+ Style = "Normal",
+ ParagraphAlignment = PdfParagraphAlignmentType.Left
+ });
+
+ // Записываем названия лекарств во 2 колонку
+ // и названия лекарств в 3 колонку
+ int maxLength = Math.Max(view.Medicines.Count, view.Diseases.Count);
+ for (int i = 0; i < maxLength; i++)
+ {
+ string medicine = (i < view.Medicines.Count) ? view.Medicines[i].Name : "";
+ string disease = (i < view.Diseases.Count) ? view.Diseases[i].Name : "";
+ CreateRow(new PdfRowParameters
+ {
+ Texts = new List { "", medicine, disease },
+ Style = "Normal",
+ ParagraphAlignment = PdfParagraphAlignmentType.Left
+ });
+ }
+ }
+
+ // Сохраняем файл
+ SavePdf(info);
+ }
+
+ ///
+ /// Создать файл Pdf
+ ///
+ ///
+ protected abstract void CreatePdf(PdfInfo info);
+
+ ///
+ /// Создать абзац с текстом
+ ///
+ ///
+ protected abstract void CreateParagraph(PdfParagraph paragraph);
+
+ ///
+ /// Создать таблицу
+ ///
+ ///
+ protected abstract void CreateTable(List columns);
+
+ ///
+ /// Создать и заполнить строку
+ ///
+ ///
+ protected abstract void CreateRow(PdfRowParameters rowParameters);
+
+ ///
+ /// Сохранить файл Pdf
+ ///
+ ///
+ protected abstract void SavePdf(PdfInfo info);
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/AbstractSaveToWord.cs b/Hospital/HospitalBusinessLogics/OfficePackage/AbstractSaveToWord.cs
new file mode 100644
index 0000000..5b7a084
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/AbstractSaveToWord.cs
@@ -0,0 +1,114 @@
+using HospitalBusinessLogics.OfficePackage.HelperEnums;
+using HospitalBusinessLogics.OfficePackage.HelperModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage
+{
+ ///
+ /// Абстрактный класс для создания отчета Word
+ ///
+ public abstract class AbstractSaveToWord
+ {
+ ///
+ /// Создать отчет Word
+ ///
+ ///
+ public void CreateReport(WordInfo info)
+ {
+ // Создаем файл
+ CreateWord(info);
+
+ // Создаем заголовок
+ // "Список процедур."
+ CreateParagraph(new WordParagraph
+ {
+ Texts = new List<(string, WordTextProperties)>
+ {
+ (info.Title, new WordTextProperties { Bold = true, Size = "24" })
+ },
+ TextProperties = new WordTextProperties
+ {
+ Size = "24",
+ JustificationType = WordJustificationType.Center
+ }
+ });
+
+ // Записываем основную информацию
+ foreach (var view in info.RecipeProcedures)
+ {
+ // "Рецепт №X. Дата выписки: XX.XX.XXXX"
+ CreateParagraph(new WordParagraph
+ {
+ Texts = new List<(string, WordTextProperties)>
+ {
+ ($"Рецепт №{view.Recipe.Id}. ", new WordTextProperties { Bold = true, Size = "24" }),
+ ($"Дата выписки: ", new WordTextProperties { Bold = true, Size = "24" }),
+ (view.Recipe.IssueDate.ToShortDateString(), new WordTextProperties { Bold = false, Size = "24" })
+ },
+ TextProperties = new WordTextProperties
+ {
+ Size = "24",
+ JustificationType = WordJustificationType.Both
+ }
+ });
+
+ // "Процедуры:"
+ CreateParagraph(new WordParagraph
+ {
+ Texts = new List<(string, WordTextProperties)>
+ {
+ ("Процедуры:", new WordTextProperties { Bold = true, Size = "24" })
+ },
+ TextProperties = new WordTextProperties
+ {
+ Size = "24",
+ JustificationType = WordJustificationType.Both
+ }
+ });
+
+ // Список процедур
+ foreach (var procedure in view.Procedures)
+ {
+ // "Название процедуры"
+ CreateParagraph(new WordParagraph
+ {
+ Texts = new List<(string, WordTextProperties)>
+ {
+ (procedure.Name.ToString(), new WordTextProperties { Bold = false, Size = "24" })
+ },
+ TextProperties = new WordTextProperties
+ {
+ Size = "24",
+ JustificationType = WordJustificationType.Both
+ }
+ });
+ }
+ }
+
+ // Сохраняем файл
+ SaveWord(info);
+ }
+
+ ///
+ /// Создать файл Word
+ ///
+ ///
+ protected abstract void CreateWord(WordInfo info);
+
+ ///
+ /// Создать абзац с текстом
+ ///
+ ///
+ protected abstract void CreateParagraph(WordParagraph paragraph);
+
+ ///
+ /// Сохранить файл Word
+ ///
+ ///
+ protected abstract void SaveWord(WordInfo info);
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/HelperEnums/ExcelStyleInfoType.cs b/Hospital/HospitalBusinessLogics/OfficePackage/HelperEnums/ExcelStyleInfoType.cs
new file mode 100644
index 0000000..3220af6
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/HelperEnums/ExcelStyleInfoType.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.HelperEnums
+{
+ ///
+ /// Тип стиля текста Excel
+ ///
+ public enum ExcelStyleInfoType
+ {
+ ///
+ /// Заголовок
+ ///
+ Title,
+
+ ///
+ /// Подзаголовок
+ ///
+ Subtitle,
+
+ ///
+ /// Обычный текст
+ ///
+ Text,
+
+ ///
+ /// Обычный текст с границами
+ ///
+ TextWithBorder,
+
+ ///
+ /// Подзаголовок с границами
+ ///
+ SubtitleWithBorder
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/HelperEnums/PdfParagraphAlignmentType.cs b/Hospital/HospitalBusinessLogics/OfficePackage/HelperEnums/PdfParagraphAlignmentType.cs
new file mode 100644
index 0000000..9f74402
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/HelperEnums/PdfParagraphAlignmentType.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.HelperEnums
+{
+ ///
+ /// Тип выравнивания текста Pdf
+ ///
+ public enum PdfParagraphAlignmentType
+ {
+ ///
+ /// По центру
+ ///
+ Center,
+
+ ///
+ /// По левому краю
+ ///
+ Left,
+
+ ///
+ /// По правому краю
+ ///
+ Right
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/HelperEnums/WordJustificationType.cs b/Hospital/HospitalBusinessLogics/OfficePackage/HelperEnums/WordJustificationType.cs
new file mode 100644
index 0000000..bc068b9
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/HelperEnums/WordJustificationType.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.HelperEnums
+{
+ ///
+ /// Тип выравнивания текста Word
+ ///
+ public enum WordJustificationType
+ {
+ ///
+ /// По центру
+ ///
+ Center,
+
+ ///
+ /// По ширине
+ ///
+ Both
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/ExcelCellParameters.cs b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/ExcelCellParameters.cs
new file mode 100644
index 0000000..bdf8244
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/ExcelCellParameters.cs
@@ -0,0 +1,40 @@
+using HospitalBusinessLogics.OfficePackage.HelperEnums;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.HelperModels
+{
+ ///
+ /// Модель для описания свойств ячейки Excel
+ ///
+ public class ExcelCellParameters
+ {
+ ///
+ /// Название колонки
+ ///
+ public string ColumnName { get; set; } = string.Empty;
+
+ ///
+ /// Номер строки
+ ///
+ public uint RowIndex { get; set; }
+
+ ///
+ /// Текст ячейки
+ ///
+ public string Text { get; set; } = string.Empty;
+
+ ///
+ /// Получение ячейки
+ ///
+ public string CellReference => $"{ColumnName}{RowIndex}";
+
+ ///
+ /// Стиль ячейки
+ ///
+ public ExcelStyleInfoType StyleInfo { get; set; }
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/ExcelInfo.cs b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/ExcelInfo.cs
new file mode 100644
index 0000000..6d49e38
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/ExcelInfo.cs
@@ -0,0 +1,30 @@
+using HospitalContracts.ViewModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.HelperModels
+{
+ ///
+ /// Модель для создания отчета Excel
+ ///
+ public class ExcelInfo
+ {
+ ///
+ /// Название файла
+ ///
+ public string FileName { get; set; } = string.Empty;
+
+ ///
+ /// Заголовок
+ ///
+ public string Title { get; set; } = string.Empty;
+
+ ///
+ /// Информация
+ ///
+ public List RecipeProcedures { get; set; } = new();
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/ExcelMergeParameters.cs b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/ExcelMergeParameters.cs
new file mode 100644
index 0000000..141b3d0
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/ExcelMergeParameters.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.HelperModels
+{
+ ///
+ /// Модель для описания объединенных ячеек Excel
+ ///
+ public class ExcelMergeParameters
+ {
+ ///
+ /// Начальная ячейка
+ ///
+ public string CellFromName { get; set; } = string.Empty;
+
+ ///
+ /// Конечная ячейка
+ ///
+ public string CellToName { get; set; } = string.Empty;
+
+ ///
+ /// Получить диапазон объединения ячеек
+ ///
+ public string Merge => $"{CellFromName}:{CellToName}";
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/PdfInfo.cs b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/PdfInfo.cs
new file mode 100644
index 0000000..f84a090
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/PdfInfo.cs
@@ -0,0 +1,40 @@
+using HospitalContracts.ViewModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.HelperModels
+{
+ ///
+ /// Модель для создания отчета Pdf
+ ///
+ public class PdfInfo
+ {
+ ///
+ /// Название файла
+ ///
+ public string FileName { get; set; } = string.Empty;
+
+ ///
+ /// Заголовок
+ ///
+ public string Title { get; set; } = string.Empty;
+
+ ///
+ /// Начало периода выборки данных
+ ///
+ public DateTime DateFrom { get; set; }
+
+ ///
+ /// Конец периода выборки данных
+ ///
+ public DateTime DateTo { get; set; }
+
+ ///
+ /// Информация
+ ///
+ public List PatientsInfo { get; set; } = new();
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/PdfParagraph.cs b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/PdfParagraph.cs
new file mode 100644
index 0000000..a87cca9
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/PdfParagraph.cs
@@ -0,0 +1,30 @@
+using HospitalBusinessLogics.OfficePackage.HelperEnums;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.HelperModels
+{
+ ///
+ /// Модель для создания абзаца Pdf
+ ///
+ public class PdfParagraph
+ {
+ ///
+ /// Текст абзаца
+ ///
+ public string Text { get; set; } = string.Empty;
+
+ ///
+ /// Стиль текста
+ ///
+ public string Style { get; set; } = string.Empty;
+
+ ///
+ /// Тип выравнивания текста
+ ///
+ public PdfParagraphAlignmentType ParagraphAlignment { get; set; }
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/PdfRowParameters.cs b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/PdfRowParameters.cs
new file mode 100644
index 0000000..9169d75
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/PdfRowParameters.cs
@@ -0,0 +1,30 @@
+using HospitalBusinessLogics.OfficePackage.HelperEnums;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.HelperModels
+{
+ ///
+ /// Модель для создания строки Pdf
+ ///
+ public class PdfRowParameters
+ {
+ ///
+ /// Список текстов
+ ///
+ public List Texts { get; set; } = new();
+
+ ///
+ /// Стиль текста
+ ///
+ public string Style { get; set; } = string.Empty;
+
+ ///
+ /// Тип выравнивания текста
+ ///
+ public PdfParagraphAlignmentType ParagraphAlignment { get; set; }
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/WordInfo.cs b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/WordInfo.cs
new file mode 100644
index 0000000..eef2ec0
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/WordInfo.cs
@@ -0,0 +1,30 @@
+using HospitalContracts.ViewModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.HelperModels
+{
+ ///
+ /// Модель для создания отчета Word
+ ///
+ public class WordInfo
+ {
+ ///
+ /// Название файла
+ ///
+ public string FileName { get; set; } = string.Empty;
+
+ ///
+ /// Заголовок
+ ///
+ public string Title { get; set; } = string.Empty;
+
+ ///
+ /// Информация
+ ///
+ public List RecipeProcedures { get; set; } = new();
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/WordParagraph.cs b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/WordParagraph.cs
new file mode 100644
index 0000000..73a46c6
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/WordParagraph.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.HelperModels
+{
+ ///
+ /// Модель для создания абзаца Word
+ ///
+ public class WordParagraph
+ {
+ ///
+ /// Список текстов в абзаце
+ ///
+ public List<(string, WordTextProperties)> Texts { get; set; } = new();
+
+ ///
+ /// Свойства абзаца
+ ///
+ public WordTextProperties? TextProperties { get; set; }
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/WordTextProperties.cs b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/WordTextProperties.cs
new file mode 100644
index 0000000..96c2a8d
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/HelperModels/WordTextProperties.cs
@@ -0,0 +1,30 @@
+using HospitalBusinessLogics.OfficePackage.HelperEnums;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.HelperModels
+{
+ ///
+ /// Модель для описания свойств абзаца Word
+ ///
+ public class WordTextProperties
+ {
+ ///
+ /// Размер шрифта
+ ///
+ public string Size { get; set; } = string.Empty;
+
+ ///
+ /// Толщина шрифта
+ ///
+ public bool Bold { get; set; }
+
+ ///
+ /// Тип выравнивания текста
+ ///
+ public WordJustificationType JustificationType { get; set; }
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/Implements/SaveToExcel.cs b/Hospital/HospitalBusinessLogics/OfficePackage/Implements/SaveToExcel.cs
new file mode 100644
index 0000000..678df60
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/Implements/SaveToExcel.cs
@@ -0,0 +1,355 @@
+using DocumentFormat.OpenXml;
+using DocumentFormat.OpenXml.Office2010.Excel;
+using DocumentFormat.OpenXml.Office2013.Excel;
+using DocumentFormat.OpenXml.Packaging;
+using DocumentFormat.OpenXml.Spreadsheet;
+using HospitalBusinessLogics.OfficePackage.HelperEnums;
+using HospitalBusinessLogics.OfficePackage.HelperModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.Implements
+{
+ ///
+ /// Реализация абстрактного класса для создания отчета Excel
+ ///
+ public class SaveToExcel : AbstractSaveToExcel
+ {
+ ///
+ /// Документ
+ ///
+ private SpreadsheetDocument? _spreadsheetDocument;
+
+ ///
+ /// Таблица общих строк
+ ///
+ private SharedStringTablePart? _shareStringPart;
+
+ ///
+ /// Рабочий лист
+ ///
+ private Worksheet? _worksheet;
+
+ ///
+ /// Настроить стили для файла
+ ///
+ ///
+ private static void CreateStyles(WorkbookPart workbookPart)
+ {
+ var sp = workbookPart.AddNewPart();
+ sp.Stylesheet = new Stylesheet();
+
+ // Создание шрифтов
+ var fonts = new Fonts() { Count = 2U, KnownFonts = true };
+
+ // Шрифт обычного текста
+ var fontUsual = new Font();
+ fontUsual.Append(new FontSize() { Val = 12D });
+ fontUsual.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Theme = 1U });
+ fontUsual.Append(new FontName() { Val = "Times New Roman" });
+ fontUsual.Append(new FontFamilyNumbering() { Val = 2 });
+ fontUsual.Append(new FontScheme() { Val = FontSchemeValues.Minor });
+
+ // Шрифт заголовка
+ var fontTitle = new Font();
+ fontTitle.Append(new Bold());
+ fontTitle.Append(new FontSize() { Val = 14D });
+ fontTitle.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Theme = 1U });
+ fontTitle.Append(new FontName() { Val = "Times New Roman" });
+ fontTitle.Append(new FontFamilyNumbering() { Val = 2 });
+ fontTitle.Append(new FontScheme() { Val = FontSchemeValues.Minor });
+
+ fonts.Append(fontUsual);
+ fonts.Append(fontTitle);
+
+ // Создание заливок
+ var fills = new Fills() { Count = 1U };
+
+ // Пустая заливка
+ var fillNone = new Fill();
+ fillNone.Append(new PatternFill() { PatternType = PatternValues.None });
+
+ fills.Append(fillNone);
+
+ // Создание границ
+ var borders = new Borders() { Count = 3U };
+
+ // Пустая граница
+ var borderNoBorder = new Border();
+ borderNoBorder.Append(new LeftBorder());
+ borderNoBorder.Append(new RightBorder());
+ borderNoBorder.Append(new TopBorder());
+ borderNoBorder.Append(new BottomBorder());
+ borderNoBorder.Append(new DiagonalBorder());
+
+ // Толстая граница
+ var borderThick = new Border();
+ var leftBorderThick = new LeftBorder() { Style = BorderStyleValues.Thick };
+ leftBorderThick.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U });
+
+ var rightBorderThick = new RightBorder() { Style = BorderStyleValues.Thick };
+ rightBorderThick.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U });
+
+ var topBorderThick = new TopBorder() { Style = BorderStyleValues.Thick };
+ topBorderThick.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U });
+
+ var bottomBorderThick = new BottomBorder() { Style = BorderStyleValues.Thick };
+ bottomBorderThick.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U });
+
+ borderThick.Append(leftBorderThick);
+ borderThick.Append(rightBorderThick);
+ borderThick.Append(topBorderThick);
+ borderThick.Append(bottomBorderThick);
+ borderThick.Append(new DiagonalBorder());
+
+ // Верхняя толстая граница и нижняя тонкая граница
+ var borderCombo = new Border();
+
+ var topBorderCombo = new TopBorder() { Style = BorderStyleValues.Thick };
+ topBorderCombo.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U });
+
+ var bottomBorderCombo = new BottomBorder() { Style = BorderStyleValues.Thin };
+ bottomBorderCombo.Append(new DocumentFormat.OpenXml.Office2010.Excel.Color() { Indexed = 64U });
+
+ borderCombo.Append(new LeftBorder());
+ borderCombo.Append(new RightBorder());
+ borderCombo.Append(topBorderCombo);
+ borderCombo.Append(bottomBorderCombo);
+ borderCombo.Append(new DiagonalBorder());
+
+ borders.Append(borderNoBorder);
+ borders.Append(borderThick);
+ borders.Append(borderCombo);
+
+ // Создаем форматы стилей ячеек
+ var cellStyleFormats = new CellStyleFormats() { Count = 1U };
+ var cellFormatStyle = new CellFormat() { NumberFormatId = 0U, FontId = 0U, FillId = 0U, BorderId = 0U };
+ cellStyleFormats.Append(cellFormatStyle);
+
+ // Создаем форматы ячеек
+ var cellFormats = new CellFormats() { Count = 5U };
+ var cellFormatFont = new CellFormat() { NumberFormatId = 0U, FontId = 0U, FillId = 0U, BorderId = 0U, FormatId = 0U, ApplyFont = true };
+ var cellFormatFontAndBorder = new CellFormat() { NumberFormatId = 0U, FontId = 0U, FillId = 0U, BorderId = 2U, FormatId = 0U, ApplyFont = true, ApplyBorder = true };
+ var cellFormatSubtitleAndBorder = new CellFormat() { NumberFormatId = 0U, FontId = 1U, FillId = 0U, BorderId = 2U, FormatId = 0U, ApplyFont = true, ApplyBorder = true };
+ var cellFormatSubtitle = new CellFormat() { NumberFormatId = 0U, FontId = 1U, FillId = 0U, BorderId = 0U, FormatId = 0U, ApplyFont = true };
+ var cellFormatTitle = new CellFormat() { NumberFormatId = 0U, FontId = 1U, FillId = 0U, BorderId = 1U, FormatId = 0U, Alignment = new Alignment() { Vertical = VerticalAlignmentValues.Center, WrapText = true, Horizontal = HorizontalAlignmentValues.Center }, ApplyFont = true, ApplyBorder = true };
+
+ cellFormats.Append(cellFormatFont);
+ cellFormats.Append(cellFormatFontAndBorder);
+ cellFormats.Append(cellFormatSubtitleAndBorder);
+ cellFormats.Append(cellFormatSubtitle);
+ cellFormats.Append(cellFormatTitle);
+
+ // Создаем стили ячеек
+ var cellStyles = new CellStyles() { Count = 1U };
+ cellStyles.Append(new CellStyle() { Name = "Normal", FormatId = 0U, BuiltinId = 0U });
+
+ var differentialFormats = new DocumentFormat.OpenXml.Office2013.Excel.DifferentialFormats() { Count = 0U };
+ var tableStyles = new TableStyles() { Count = 0U, DefaultTableStyle = "TableStyleMedium2", DefaultPivotStyle = "PivotStyleLight16" };
+
+ // Список расширений стилей
+ var stylesheetExtensionList = new StylesheetExtensionList();
+
+ var stylesheetExtension1 = new StylesheetExtension() { Uri = "{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}" };
+ stylesheetExtension1.AddNamespaceDeclaration("x14", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main");
+ stylesheetExtension1.Append(new SlicerStyles() { DefaultSlicerStyle = "SlicerStyleLight1" });
+
+ var stylesheetExtension2 = new StylesheetExtension() { Uri = "{9260A510-F301-46a8-8635-F512D64BE5F5}" };
+ stylesheetExtension2.AddNamespaceDeclaration("x15", "http://schemas.microsoft.com/office/spreadsheetml/2010/11/main");
+ stylesheetExtension2.Append(new TimelineStyles() { DefaultTimelineStyle = "TimeSlicerStyleLight1" });
+
+ stylesheetExtensionList.Append(stylesheetExtension1);
+ stylesheetExtensionList.Append(stylesheetExtension2);
+
+ // Добавляем все стили
+ sp.Stylesheet.Append(fonts);
+ sp.Stylesheet.Append(fills);
+ sp.Stylesheet.Append(borders);
+ sp.Stylesheet.Append(cellStyleFormats);
+ sp.Stylesheet.Append(cellFormats);
+ sp.Stylesheet.Append(cellStyles);
+ sp.Stylesheet.Append(differentialFormats);
+ sp.Stylesheet.Append(tableStyles);
+ sp.Stylesheet.Append(stylesheetExtensionList);
+ }
+
+ ///
+ /// Получить номер стиля по типу
+ ///
+ ///
+ ///
+ private static uint GetStyleValue(ExcelStyleInfoType styleInfo)
+ {
+ return styleInfo switch
+ {
+ ExcelStyleInfoType.Title => 4U,
+ ExcelStyleInfoType.Subtitle => 3U,
+ ExcelStyleInfoType.SubtitleWithBorder => 2U,
+ ExcelStyleInfoType.TextWithBorder => 1U,
+ ExcelStyleInfoType.Text => 0U,
+ _ => 0U,
+ };
+ }
+
+ ///
+ /// Создать файл Excel
+ ///
+ ///
+ protected override void CreateExcel(ExcelInfo info)
+ {
+ _spreadsheetDocument = SpreadsheetDocument.Create(info.FileName, SpreadsheetDocumentType.Workbook);
+ // Создаем книгу (в ней хранятся листы)
+ var workbookpart = _spreadsheetDocument.AddWorkbookPart();
+ workbookpart.Workbook = new Workbook();
+
+ // Настраиваем стили
+ CreateStyles(workbookpart);
+
+ // Получаем/создаем хранилище текстов для книги
+ _shareStringPart = _spreadsheetDocument.WorkbookPart!.GetPartsOfType().Any()
+ ? _spreadsheetDocument.WorkbookPart.GetPartsOfType().First()
+ : _spreadsheetDocument.WorkbookPart.AddNewPart();
+
+ // Создаем SharedStringTable, если его нет
+ if (_shareStringPart.SharedStringTable == null)
+ {
+ _shareStringPart.SharedStringTable = new SharedStringTable();
+ }
+
+ // Создаем лист в книгу
+ var worksheetPart = workbookpart.AddNewPart();
+ worksheetPart.Worksheet = new Worksheet(new SheetData());
+
+ // Добавляем лист в книгу
+ var sheets = _spreadsheetDocument.WorkbookPart.Workbook.AppendChild(new Sheets());
+ var sheet = new Sheet()
+ {
+ Id = _spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
+ SheetId = 1,
+ Name = "Лист"
+ };
+ sheets.Append(sheet);
+
+ _worksheet = worksheetPart.Worksheet;
+ }
+
+ ///
+ /// Добавить новую ячейку в лист
+ ///
+ ///
+ protected override void InsertCellInWorksheet(ExcelCellParameters excelParams)
+ {
+ if (_worksheet == null || _shareStringPart == null)
+ {
+ return;
+ }
+
+ var sheetData = _worksheet.GetFirstChild();
+ if (sheetData == null)
+ {
+ return;
+ }
+
+ // Ищем строку, либо добавляем ее
+ Row row;
+ if (sheetData.Elements().Where(r => r.RowIndex! == excelParams.RowIndex).Any())
+ {
+ row = sheetData.Elements().Where(r => r.RowIndex! == excelParams.RowIndex).First();
+ }
+ else
+ {
+ row = new Row() { RowIndex = excelParams.RowIndex };
+ sheetData.Append(row);
+ }
+
+ // Ищем нужную ячейку
+ Cell cell;
+ if (row.Elements().Where(c => c.CellReference!.Value == excelParams.CellReference).Any())
+ {
+ cell = row.Elements().Where(c => c.CellReference!.Value == excelParams.CellReference).First();
+ }
+ else
+ {
+ // Все ячейки должны быть последовательно расположены друг за другом
+ // нужно определить, после какой вставлять
+ Cell? refCell = null;
+ foreach (Cell rowCell in row.Elements())
+ {
+ if (string.Compare(rowCell.CellReference!.Value, excelParams.CellReference, true) > 0)
+ {
+ refCell = rowCell;
+ break;
+ }
+ }
+
+ var newCell = new Cell() { CellReference = excelParams.CellReference };
+ row.InsertBefore(newCell, refCell);
+
+ cell = newCell;
+ }
+
+ // Вставляем новый текст
+ _shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new Text(excelParams.Text)));
+ _shareStringPart.SharedStringTable.Save();
+
+ cell.CellValue = new CellValue((_shareStringPart.SharedStringTable.Elements().Count() - 1).ToString());
+ cell.DataType = new EnumValue(CellValues.SharedString);
+ cell.StyleIndex = GetStyleValue(excelParams.StyleInfo);
+ }
+
+ ///
+ /// Объединить ячейки
+ ///
+ ///
+ protected override void MergeCells(ExcelMergeParameters excelParams)
+ {
+ if (_worksheet == null)
+ {
+ return;
+ }
+
+ MergeCells mergeCells;
+ if (_worksheet.Elements().Any())
+ {
+ mergeCells = _worksheet.Elements().First();
+ }
+ else
+ {
+ mergeCells = new MergeCells();
+
+ if (_worksheet.Elements().Any())
+ {
+ _worksheet.InsertAfter(mergeCells, _worksheet.Elements().First());
+ }
+ else
+ {
+ _worksheet.InsertAfter(mergeCells, _worksheet.Elements().First());
+ }
+ }
+
+ var mergeCell = new MergeCell()
+ {
+ Reference = new StringValue(excelParams.Merge)
+ };
+ mergeCells.Append(mergeCell);
+ }
+
+ ///
+ /// Сохранить файл Excel
+ ///
+ ///
+ protected override void SaveExcel(ExcelInfo info)
+ {
+ if (_spreadsheetDocument == null)
+ {
+ return;
+ }
+
+ _spreadsheetDocument.WorkbookPart!.Workbook.Save();
+ _spreadsheetDocument.Dispose();
+ }
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/Implements/SaveToPdf.cs b/Hospital/HospitalBusinessLogics/OfficePackage/Implements/SaveToPdf.cs
new file mode 100644
index 0000000..cf9359d
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/Implements/SaveToPdf.cs
@@ -0,0 +1,157 @@
+using HospitalBusinessLogics.OfficePackage.HelperEnums;
+using HospitalBusinessLogics.OfficePackage.HelperModels;
+using MigraDoc.DocumentObjectModel;
+using MigraDoc.DocumentObjectModel.Tables;
+using MigraDoc.Rendering;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.Implements
+{
+ ///
+ /// Реализация абстрактного класса для создания отчета Word
+ ///
+ public class SaveToPdf : AbstractSaveToPdf
+ {
+ ///
+ /// Документ
+ ///
+ private Document? _document;
+
+ ///
+ /// Секция
+ ///
+ private Section? _section;
+
+ ///
+ /// Таблица
+ ///
+ private Table? _table;
+
+ ///
+ /// Получить тип выравнивания текста
+ ///
+ ///
+ ///
+ private static ParagraphAlignment GetParagraphAlignment(PdfParagraphAlignmentType type)
+ {
+ return type switch
+ {
+ PdfParagraphAlignmentType.Center => ParagraphAlignment.Center,
+ PdfParagraphAlignmentType.Left => ParagraphAlignment.Left,
+ PdfParagraphAlignmentType.Right => ParagraphAlignment.Right,
+ _ => ParagraphAlignment.Justify,
+ };
+ }
+
+ ///
+ /// Настройки стилей
+ ///
+ ///
+ private static void DefineStyles(Document document)
+ {
+ var style = document.Styles["Normal"];
+ style.Font.Name = "Times New Roman";
+ style.Font.Size = 14;
+
+ style = document.Styles.AddStyle("NormalTitle", "Normal");
+ style.Font.Bold = true;
+ }
+
+ ///
+ /// Создать файл Pdf
+ ///
+ ///
+ protected override void CreatePdf(PdfInfo info)
+ {
+ _document = new Document();
+ DefineStyles(_document);
+ _section = _document.AddSection();
+ }
+
+ ///
+ /// Создать абзац с текстом
+ ///
+ ///
+ protected override void CreateParagraph(PdfParagraph pdfParagraph)
+ {
+ if (_section == null)
+ {
+ return;
+ }
+
+ var paragraph = _section.AddParagraph(pdfParagraph.Text);
+ paragraph.Format.SpaceAfter = "1cm";
+ paragraph.Format.Alignment = GetParagraphAlignment(pdfParagraph.ParagraphAlignment);
+ paragraph.Style = pdfParagraph.Style;
+ }
+
+ ///
+ /// Создать таблицу
+ ///
+ ///
+ protected override void CreateTable(List columns)
+ {
+ if (_document == null)
+ {
+ return;
+ }
+
+ _table = _document.LastSection.AddTable();
+ foreach (var column in columns)
+ {
+ _table.AddColumn(column);
+ }
+ }
+
+ ///
+ /// Создать и заполнить строку
+ ///
+ ///
+ protected override void CreateRow(PdfRowParameters rowParameters)
+ {
+ if (_table == null)
+ {
+ return;
+ }
+
+ var row = _table.AddRow();
+ for (int i = 0; i < rowParameters.Texts.Count; ++i)
+ {
+ row.Cells[i].AddParagraph(rowParameters.Texts[i]);
+
+ if (!string.IsNullOrEmpty(rowParameters.Style))
+ {
+ row.Cells[i].Style = rowParameters.Style;
+ }
+
+ Unit borderWidth = 0.5;
+
+ row.Cells[i].Borders.Left.Width = borderWidth;
+ row.Cells[i].Borders.Right.Width = borderWidth;
+ row.Cells[i].Borders.Top.Width = borderWidth;
+ row.Cells[i].Borders.Bottom.Width = borderWidth;
+
+ row.Cells[i].Format.Alignment = GetParagraphAlignment(rowParameters.ParagraphAlignment);
+ row.Cells[i].VerticalAlignment = VerticalAlignment.Center;
+ }
+ }
+
+ ///
+ /// Сохранить файл Pdf
+ ///
+ ///
+ protected override void SavePdf(PdfInfo info)
+ {
+ var renderer = new PdfDocumentRenderer(true)
+ {
+ Document = _document
+ };
+ renderer.RenderDocument();
+ renderer.PdfDocument.Save(info.FileName);
+ }
+ }
+}
diff --git a/Hospital/HospitalBusinessLogics/OfficePackage/Implements/SaveToWord.cs b/Hospital/HospitalBusinessLogics/OfficePackage/Implements/SaveToWord.cs
new file mode 100644
index 0000000..75ae7be
--- /dev/null
+++ b/Hospital/HospitalBusinessLogics/OfficePackage/Implements/SaveToWord.cs
@@ -0,0 +1,163 @@
+using DocumentFormat.OpenXml;
+using DocumentFormat.OpenXml.Packaging;
+using DocumentFormat.OpenXml.Wordprocessing;
+using HospitalBusinessLogics.OfficePackage.HelperEnums;
+using HospitalBusinessLogics.OfficePackage.HelperModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalBusinessLogics.OfficePackage.Implements
+{
+ ///
+ /// Реализация абстрактного класса для создания отчета Word
+ ///
+ public class SaveToWord : AbstractSaveToWord
+ {
+ ///
+ /// Документ
+ ///
+ private WordprocessingDocument? _wordDocument;
+
+ ///
+ /// Тело документа
+ ///
+ private Body? _docBody;
+
+ ///
+ /// Получить тип выравнивания текста
+ ///
+ ///
+ ///
+ private static JustificationValues GetJustificationValues(WordJustificationType type)
+ {
+ return type switch
+ {
+ WordJustificationType.Both => JustificationValues.Both,
+ WordJustificationType.Center => JustificationValues.Center,
+ _ => JustificationValues.Left,
+ };
+ }
+
+ ///
+ /// Настройки станицы
+ ///
+ ///
+ private static SectionProperties CreateSectionProperties()
+ {
+ var properties = new SectionProperties();
+
+ var pageSize = new PageSize
+ {
+ Orient = PageOrientationValues.Portrait
+ };
+
+ properties.AppendChild(pageSize);
+ return properties;
+ }
+
+ ///
+ /// Задать форматирование для абзаца
+ ///
+ ///
+ ///
+ private static ParagraphProperties? CreateParagraphProperties(WordTextProperties? paragraphProperties)
+ {
+ if (paragraphProperties == null)
+ {
+ return null;
+ }
+
+ var properties = new ParagraphProperties();
+
+ properties.AppendChild(new Justification()
+ {
+ Val = GetJustificationValues(paragraphProperties.JustificationType)
+ });
+
+ properties.AppendChild(new SpacingBetweenLines
+ {
+ LineRule = LineSpacingRuleValues.Auto
+ });
+
+ properties.AppendChild(new Indentation());
+
+ var paragraphMarkRunProperties = new ParagraphMarkRunProperties();
+ if (!string.IsNullOrEmpty(paragraphProperties.Size))
+ {
+ paragraphMarkRunProperties.AppendChild(new FontSize { Val = paragraphProperties.Size });
+ }
+ properties.AppendChild(paragraphMarkRunProperties);
+
+ return properties;
+ }
+
+ ///
+ /// Создать файл Word
+ ///
+ ///
+ protected override void CreateWord(WordInfo info)
+ {
+ _wordDocument = WordprocessingDocument.Create(info.FileName, WordprocessingDocumentType.Document);
+ MainDocumentPart mainPart = _wordDocument.AddMainDocumentPart();
+ mainPart.Document = new Document();
+ _docBody = mainPart.Document.AppendChild(new Body());
+ }
+
+ ///
+ /// Создать абзац с текстом
+ ///
+ ///
+ protected override void CreateParagraph(WordParagraph paragraph)
+ {
+ if (_docBody == null || paragraph == null)
+ {
+ return;
+ }
+
+ var docParagraph = new Paragraph();
+ docParagraph.AppendChild(CreateParagraphProperties(paragraph.TextProperties));
+
+ foreach (var run in paragraph.Texts)
+ {
+ var docRun = new Run();
+
+ var properties = new RunProperties();
+ properties.AppendChild(new FontSize { Val = run.Item2.Size });
+ if (run.Item2.Bold)
+ {
+ properties.AppendChild(new Bold());
+ }
+ docRun.AppendChild(properties);
+
+ docRun.AppendChild(new Text
+ {
+ Text = run.Item1,
+ Space = SpaceProcessingModeValues.Preserve
+ });
+
+ docParagraph.AppendChild(docRun);
+ }
+
+ _docBody.AppendChild(docParagraph);
+ }
+
+ ///
+ /// Сохранить файл Word
+ ///
+ ///
+ protected override void SaveWord(WordInfo info)
+ {
+ if (_docBody == null || _wordDocument == null)
+ {
+ return;
+ }
+
+ _docBody.AppendChild(CreateSectionProperties());
+ _wordDocument.MainDocumentPart!.Document.Save();
+ _wordDocument.Dispose();
+ }
+ }
+}
diff --git a/Hospital/HospitalContracts/BindingModels/ReportBindingModel.cs b/Hospital/HospitalContracts/BindingModels/ReportBindingModel.cs
new file mode 100644
index 0000000..eafe06d
--- /dev/null
+++ b/Hospital/HospitalContracts/BindingModels/ReportBindingModel.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalContracts.BindingModels
+{
+ ///
+ /// Модель привязки для создания отчета
+ ///
+ public class ReportBindingModel
+ {
+ ///
+ /// Название файла
+ ///
+ public string FileName { get; set; } = string.Empty;
+
+ ///
+ /// Начало периода выборки данных
+ ///
+ public DateTime? DateFrom { get; set; }
+
+ ///
+ /// Конец периода выборки данных
+ ///
+ public DateTime? DateTo { get; set; }
+
+ ///
+ /// Идентификатор врача
+ ///
+ public int DoctorId { get; set; }
+ }
+}
diff --git a/Hospital/HospitalContracts/BusinessLogicsContracts/IReportLogic.cs b/Hospital/HospitalContracts/BusinessLogicsContracts/IReportLogic.cs
new file mode 100644
index 0000000..bc382c9
--- /dev/null
+++ b/Hospital/HospitalContracts/BusinessLogicsContracts/IReportLogic.cs
@@ -0,0 +1,48 @@
+using HospitalContracts.BindingModels;
+using HospitalContracts.ViewModels;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalContracts.BusinessLogicsContracts
+{
+ ///
+ /// Интерфейс для описания работы бизнес-логики для отчетов
+ ///
+ public interface IReportLogic
+ {
+ ///
+ /// Получить список рецептов с расшифровкой по процедурам
+ ///
+ ///
+ ///
+ List GetRecipeProcedures(ReportBindingModel model);
+
+ ///
+ /// Получить список пациентов с расшифровкой по лекарствам и болезням
+ ///
+ ///
+ ///
+ List GetPatientsInfo(ReportBindingModel model);
+
+ ///
+ /// Сохранить список рецептов с расшифровкой по процедурам в файл Word
+ ///
+ ///
+ void SaveRecipeProceduresToWordFile(ReportBindingModel model);
+
+ ///
+ /// Сохранить список рецептов с расшифровкой по процедурам в файл Excel
+ ///
+ ///
+ void SaveRecipeProceduresToExcelFile(ReportBindingModel model);
+
+ ///
+ /// Сохранить список пациентов с расшифровкой по лекарствам и болезням в Pdf файл
+ ///
+ ///
+ void SavePatientsInfoToPdfFile(ReportBindingModel model);
+ }
+}
diff --git a/Hospital/HospitalContracts/ViewModels/ReportPatientsViewModel.cs b/Hospital/HospitalContracts/ViewModels/ReportPatientsViewModel.cs
new file mode 100644
index 0000000..278c609
--- /dev/null
+++ b/Hospital/HospitalContracts/ViewModels/ReportPatientsViewModel.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalContracts.ViewModels
+{
+ ///
+ /// Модель представления для отчета
+ /// по пациентам с расшифровкой по лекарствам и болезням
+ ///
+ public class ReportPatientsViewModel
+ {
+ ///
+ /// Пациент
+ ///
+ public PatientViewModel Patient { get; set; } = new();
+
+ ///
+ /// Список лекарств
+ ///
+ public HashSet Medicines { get; set; } = new();
+
+ ///
+ /// Список болезней
+ ///
+ public HashSet Diseases { get; set; } = new();
+ }
+}
diff --git a/Hospital/HospitalContracts/ViewModels/ReportRecipeProceduresViewModel.cs b/Hospital/HospitalContracts/ViewModels/ReportRecipeProceduresViewModel.cs
new file mode 100644
index 0000000..2a55e24
--- /dev/null
+++ b/Hospital/HospitalContracts/ViewModels/ReportRecipeProceduresViewModel.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HospitalContracts.ViewModels
+{
+ ///
+ /// Модель представления для отчета
+ /// по рецептам с расшифровкой по процедурам
+ ///
+ public class ReportRecipeProceduresViewModel
+ {
+ ///
+ /// Рецепт
+ ///
+ public RecipeViewModel Recipe { get; set; } = new();
+
+ ///
+ /// Список процедур
+ ///
+ public HashSet Procedures { get; set; } = new();
+ }
+}
| | |