4 Commits

43 changed files with 2148 additions and 90 deletions

View File

@@ -1,6 +1,7 @@
using ProjectTimeTable.Entites.Enums;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -10,10 +11,11 @@ namespace ProjectTimeTable.Entites;
public class Auditorium
{
public int Id { get; private set; }
[DisplayName("Название аудитории")]
public string Name { get; private set; } = string.Empty;
[DisplayName("Тип аудитории")]
public ClassType ClassType { get; private set; }
[DisplayName("Размер аудитории")]
public int Size { get; private set; }
public static Auditorium CreateEntity(int id, string name, ClassType classType, int size)

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -9,6 +10,8 @@ namespace ProjectTimeTable.Entites;
public class Discipline
{
public int ID { get; private set; }
[DisplayName("Наименование дисцпилины")]
public string Name { get; private set; } = string.Empty;
public static Discipline CreateEntity(int id, string name)
{

View File

@@ -10,6 +10,7 @@ public class DisciplinePlan
{
public int PlanId { get; private set; }
public int DisciplineId { get; private set; }
public string DisciplineName { get; private set; } = string.Empty;
public int CountLesson { get; private set; }
public int Course { get; private set; }
@@ -23,9 +24,4 @@ public class DisciplinePlan
Course = course
};
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -9,11 +10,18 @@ namespace ProjectTimeTable.Entites;
public class Group
{
public int Id { get; private set; }
[DisplayName("Название группы")]
public string Name { get; private set; } = string.Empty;
[DisplayName("Курс")]
public int Course { get; private set; }
[DisplayName("Количество людей")]
public int CountPeople { get; private set; }
[Browsable(false)]
public int PlanID { get; private set; }
[DisplayName("План")]
public string PlanName { get; private set; } = string.Empty;
public static Group CreateEntity(int id, string name, int course, int countPeople, int planId)
{
return new

View File

@@ -7,13 +7,15 @@ using System.Threading.Tasks;
namespace ProjectTimeTable.Entites;
public class GroupTimetable
{
public int GroupId { get; private set; }
public int TimeTableId { get; private set; }
public int DisciplineID { get; private set; }
public string DisciplineName { get; private set; } = string.Empty;
public int ClassID { get; private set; }
public string ClassName { get; private set; } = string.Empty;
public int GroupID { get; private set; }
public string GroupName { get; private set; } = string.Empty;
public int TeacherID { get; private set; }
public string TeacherName { get; private set; } = string.Empty;
public static GroupTimetable CreateElement(int idTimeTable, int idDiscipline, int idClass, int idGroup, int idTeacher)
{
@@ -21,7 +23,7 @@ public class GroupTimetable
{
DisciplineID = idDiscipline,
ClassID = idClass,
GroupId = idGroup,
GroupID = idGroup,
TeacherID = idTeacher,
TimeTableId = idTimeTable
};

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -8,8 +9,16 @@ namespace ProjectTimeTable.Entites;
public class Plan
{
public int Id { get; private set; }
public int Id { get; private set; }
[DisplayName("Название плана")]
public string Name { get; private set; } = string.Empty;
[DisplayName("Дисциплины плана")]
public string DisciplineName => DisciplinePlan != null ?
string.Join(", ", DisciplinePlan.Select(x => $"{x.DisciplineName} {x.CountLesson} {x.Course}")) :
string.Empty;
[Browsable(false)]
public IEnumerable<DisciplinePlan> DisciplinePlan
{
get;
@@ -25,4 +34,11 @@ public class Plan
DisciplinePlan = disciplinePlan
};
}
public void SetDisciplinePlan(IEnumerable<DisciplinePlan> disciplinePlans)
{
if (disciplinePlans != null && disciplinePlans.Any())
{
DisciplinePlan = disciplinePlans;
}
}
}

View File

@@ -1,6 +1,7 @@
using ProjectTimeTable.Entites.Enums;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -10,11 +11,15 @@ namespace ProjectTimeTable.Entites;
public class Teacher
{
public int Id { get; private set; }
[DisplayName("Фамилия")]
public string FirstName { get; private set; } = string.Empty;
[DisplayName("Имя")]
public string SecondName { get; private set; } = string.Empty;
[DisplayName("Отчество")]
public string LastName { get; private set; } = string.Empty;
public string FullName => $"{FirstName} {SecondName} {LastName}";
[DisplayName("Ученая степень")]
public TeacherPost TeacherPost { get; private set; }
public static Teacher CreateEntity(int id, string firstname, string secondname, string lastname, TeacherPost teacherPost)
{
@@ -23,6 +28,7 @@ public class Teacher
FirstName = firstname ?? string.Empty,
SecondName = secondname ?? string.Empty,
LastName = lastname ?? string.Empty,
TeacherPost = teacherPost };
TeacherPost = teacherPost
};
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -9,16 +10,25 @@ namespace ProjectTimeTable.Entites;
public class TimeTable
{
public int Id { get; private set; }
[DisplayName("Количество пар")]
public int NumberLesson { get; private set; }
[DisplayName("День")]
public int Day { get; private set; }
[DisplayName("Неделя")]
public int Week { get; private set; }
[Browsable(false)]
public string DisciplineName { get; set; } =string.Empty;
[Browsable(false)]
public IEnumerable<GroupTimetable> GroupTimetable
{
get;
private set;
} = [];
[DisplayName("Расписание")]
public string GroupTime => GroupTimetable != null ?
string.Join(", ", GroupTimetable.Select(x => $"{x.DisciplineName}|{x.ClassName} {x.GroupName} {x.TeacherName}")) :
string.Empty;
public static TimeTable CreateOperation(int id, int numberLesson, int day, int week, IEnumerable<GroupTimetable> groupTimetable)
{
@@ -31,4 +41,11 @@ public class TimeTable
GroupTimetable = groupTimetable
};
}
public void SetTimeTableGroup(IEnumerable<GroupTimetable> grouptts)
{
if (grouptts != null && grouptts.Any())
{
GroupTimetable = grouptts;
}
}
}

View File

@@ -38,6 +38,9 @@
TimeTableToolStripMenuItem = new ToolStripMenuItem();
PlanToolStripMenuItem = new ToolStripMenuItem();
отчетыToolStripMenuItem = new ToolStripMenuItem();
directoryReportToolStripMenuItem = new ToolStripMenuItem();
DistributionNumberLessonToolStripMenuItem = new ToolStripMenuItem();
ReportClockToolStripMenuItem = new ToolStripMenuItem();
menuStrip.SuspendLayout();
SuspendLayout();
//
@@ -61,28 +64,28 @@
// GroupToolStripMenuItem
//
GroupToolStripMenuItem.Name = "GroupToolStripMenuItem";
GroupToolStripMenuItem.Size = new Size(224, 26);
GroupToolStripMenuItem.Size = new Size(201, 26);
GroupToolStripMenuItem.Text = "Группы";
GroupToolStripMenuItem.Click += GroupToolStripMenuItem_Click;
//
// TeacherToolStripMenuItem
//
TeacherToolStripMenuItem.Name = "TeacherToolStripMenuItem";
TeacherToolStripMenuItem.Size = new Size(224, 26);
TeacherToolStripMenuItem.Size = new Size(201, 26);
TeacherToolStripMenuItem.Text = "Преподаватели";
TeacherToolStripMenuItem.Click += TeacherToolStripMenuItem_Click;
//
// DisciplineToolStripMenuItem
//
DisciplineToolStripMenuItem.Name = "DisciplineToolStripMenuItem";
DisciplineToolStripMenuItem.Size = new Size(224, 26);
DisciplineToolStripMenuItem.Size = new Size(201, 26);
DisciplineToolStripMenuItem.Text = "Дисциплины";
DisciplineToolStripMenuItem.Click += DisciplineToolStripMenuItem_Click;
//
// AuditoriumToolStripMenuItem
//
AuditoriumToolStripMenuItem.Name = "AuditoriumToolStripMenuItem";
AuditoriumToolStripMenuItem.Size = new Size(224, 26);
AuditoriumToolStripMenuItem.Size = new Size(201, 26);
AuditoriumToolStripMenuItem.Text = "Аудитории";
AuditoriumToolStripMenuItem.Click += AuditoriumToolStripMenuItem_Click;
//
@@ -96,24 +99,48 @@
// TimeTableToolStripMenuItem
//
TimeTableToolStripMenuItem.Name = "TimeTableToolStripMenuItem";
TimeTableToolStripMenuItem.Size = new Size(224, 26);
TimeTableToolStripMenuItem.Size = new Size(193, 26);
TimeTableToolStripMenuItem.Text = "Расписание";
TimeTableToolStripMenuItem.Click += TimeTableToolStripMenuItem_Click;
//
// PlanToolStripMenuItem
//
PlanToolStripMenuItem.Name = "PlanToolStripMenuItem";
PlanToolStripMenuItem.Size = new Size(224, 26);
PlanToolStripMenuItem.Size = new Size(193, 26);
PlanToolStripMenuItem.Text = "Учебный план";
PlanToolStripMenuItem.Click += PlanToolStripMenuItem_Click;
//
// отчетыToolStripMenuItem
//
отчетыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { directoryReportToolStripMenuItem, DistributionNumberLessonToolStripMenuItem, ReportClockToolStripMenuItem });
отчетыToolStripMenuItem.Name = "отчетыToolStripMenuItem";
отчетыToolStripMenuItem.Size = new Size(73, 24);
отчетыToolStripMenuItem.Text = "Отчеты";
//
// FormTimeTable
// directoryReportToolStripMenuItem
//
directoryReportToolStripMenuItem.Name = "directoryReportToolStripMenuItem";
directoryReportToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.W;
directoryReportToolStripMenuItem.Size = new Size(361, 26);
directoryReportToolStripMenuItem.Text = "Документ со справочниками";
directoryReportToolStripMenuItem.Click += DirectoryReportToolStripMenuItem_Click;
//
// DistributionNumberLessonToolStripMenuItem
//
DistributionNumberLessonToolStripMenuItem.Name = "DistributionNumberLessonToolStripMenuItem";
DistributionNumberLessonToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.P;
DistributionNumberLessonToolStripMenuItem.Size = new Size(361, 26);
DistributionNumberLessonToolStripMenuItem.Text = "Распределение количества пар";
DistributionNumberLessonToolStripMenuItem.Click += DistributionNumberLessonToolStripMenuItem_Click;
//
// ReportClockToolStripMenuItem
//
ReportClockToolStripMenuItem.Name = "ReportClockToolStripMenuItem";
ReportClockToolStripMenuItem.Size = new Size(361, 26);
ReportClockToolStripMenuItem.Text = "Распределение количества часов";
ReportClockToolStripMenuItem.Click += ReportClockToolStripMenuItem_Click;
//
// FormTimeTableMain
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
@@ -122,7 +149,7 @@
ClientSize = new Size(782, 453);
Controls.Add(menuStrip);
MainMenuStrip = menuStrip;
Name = "FormTimeTable";
Name = "FormTimeTableMain";
StartPosition = FormStartPosition.CenterScreen;
Text = "Расписание";
menuStrip.ResumeLayout(false);
@@ -143,5 +170,8 @@
private ToolStripMenuItem TimeTableToolStripMenuItem;
private ToolStripMenuItem PlanToolStripMenuItem;
private ToolStripMenuItem отчетыToolStripMenuItem;
private ToolStripMenuItem directoryReportToolStripMenuItem;
private ToolStripMenuItem DistributionNumberLessonToolStripMenuItem;
private ToolStripMenuItem ReportClockToolStripMenuItem;
}
}

View File

@@ -93,5 +93,44 @@ namespace ProjectTimeTable
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void DirectoryReportToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormDirectoryReport>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void DistributionNumberLessonToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormTimeTableNumberLessonDistributionReport>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ReportClockToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
_container.Resolve<FormPlanReport>().ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

View File

@@ -35,8 +35,11 @@ namespace ProjectTimeTable.Forms
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadList() => dataGridView.DataSource = _auditoriumRepository.ReadAuditorium();
private void LoadList()
{
dataGridView.DataSource = _auditoriumRepository.ReadAuditorium();
dataGridView.Columns["Id"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{
id = 0;
@@ -90,7 +93,6 @@ namespace ProjectTimeTable.Forms
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonUpg_Click(object sender, EventArgs e)
{
if (!TryGetIdentifierFromSelectedRow(out var findId))

View File

@@ -0,0 +1,113 @@
namespace ProjectTimeTable.Forms
{
partial class FormDirectoryReport
{
/// <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()
{
checkBoxGroup = new CheckBox();
checkBoxAuditorium = new CheckBox();
checkBoxTeacher = new CheckBox();
checkBoxDiscipline = new CheckBox();
buttonBuild = new Button();
SuspendLayout();
//
// checkBoxGroup
//
checkBoxGroup.AutoSize = true;
checkBoxGroup.Location = new Point(25, 24);
checkBoxGroup.Name = "checkBoxGroup";
checkBoxGroup.Size = new Size(80, 24);
checkBoxGroup.TabIndex = 0;
checkBoxGroup.Text = "Группа";
checkBoxGroup.UseVisualStyleBackColor = true;
//
// checkBoxAuditorium
//
checkBoxAuditorium.AutoSize = true;
checkBoxAuditorium.Location = new Point(25, 71);
checkBoxAuditorium.Name = "checkBoxAuditorium";
checkBoxAuditorium.Size = new Size(107, 24);
checkBoxAuditorium.TabIndex = 1;
checkBoxAuditorium.Text = "Аудитории";
checkBoxAuditorium.UseVisualStyleBackColor = true;
//
// checkBoxTeacher
//
checkBoxTeacher.AutoSize = true;
checkBoxTeacher.Location = new Point(25, 124);
checkBoxTeacher.Name = "checkBoxTeacher";
checkBoxTeacher.Size = new Size(140, 24);
checkBoxTeacher.TabIndex = 2;
checkBoxTeacher.Text = "Преподаватели";
checkBoxTeacher.UseVisualStyleBackColor = true;
//
// checkBoxDiscipline
//
checkBoxDiscipline.AutoSize = true;
checkBoxDiscipline.Location = new Point(25, 177);
checkBoxDiscipline.Name = "checkBoxDiscipline";
checkBoxDiscipline.Size = new Size(121, 24);
checkBoxDiscipline.TabIndex = 3;
checkBoxDiscipline.Text = "Дисциплины";
checkBoxDiscipline.UseVisualStyleBackColor = true;
//
// buttonBuild
//
buttonBuild.Location = new Point(201, 105);
buttonBuild.Name = "buttonBuild";
buttonBuild.Size = new Size(132, 29);
buttonBuild.TabIndex = 4;
buttonBuild.Text = "Сформировать";
buttonBuild.UseVisualStyleBackColor = true;
buttonBuild.Click += ButtonBuild_Click;
//
// FormDirectoryReport
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(361, 232);
Controls.Add(buttonBuild);
Controls.Add(checkBoxDiscipline);
Controls.Add(checkBoxTeacher);
Controls.Add(checkBoxAuditorium);
Controls.Add(checkBoxGroup);
Name = "FormDirectoryReport";
StartPosition = FormStartPosition.CenterParent;
Text = "Выгрузка справочников";
ResumeLayout(false);
PerformLayout();
}
#endregion
private CheckBox checkBoxGroup;
private CheckBox checkBoxAuditorium;
private CheckBox checkBoxTeacher;
private CheckBox checkBoxDiscipline;
private Button buttonBuild;
}
}

View File

@@ -0,0 +1,65 @@
using ProjectTimeTable.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 ProjectTimeTable.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 (!checkBoxGroup.Checked &&
!checkBoxAuditorium.Checked && !checkBoxTeacher.Checked && !checkBoxDiscipline.Checked)
{
throw new Exception("Не выбран ни один справочник для выгрузки");
}
var sfd = new SaveFileDialog()
{
Filter = "Docx Files | *.docx"
};
if (sfd.ShowDialog() != DialogResult.OK)
{
throw new Exception("Не выбран файла для отчета");
}
if
(_container.Resolve<DocReport>().CreateDoc(sfd.FileName, checkBoxGroup.Checked,
checkBoxTeacher.Checked,
checkBoxAuditorium.Checked, checkBoxDiscipline.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);
}
}
}
}

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

@@ -75,7 +75,6 @@ namespace ProjectTimeTable.Forms
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonCancel_Click(object sender, EventArgs e) => Close();
private Discipline CreateDiscipline(int id) => Discipline.CreateEntity(id, textBoxName.Text);

View File

@@ -110,7 +110,7 @@
Controls.Add(panel1);
Name = "FormDisciplines";
StartPosition = FormStartPosition.CenterParent;
Text = "FormDisciplines";
Text = "Дисциплины";
Load += FormDisciplines_Load;
panel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();

View File

@@ -22,7 +22,6 @@ namespace ProjectTimeTable.Forms
_container = container ?? throw new ArgumentNullException(nameof(container));
_disciplineRepository = disciplineRepository ?? throw new ArgumentNullException(nameof(disciplineRepository));
}
private void FormDisciplines_Load(object sender, EventArgs e)
{
try
@@ -35,7 +34,11 @@ namespace ProjectTimeTable.Forms
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadList() => dataGridView.DataSource = _disciplineRepository.ReadDiscipline();
private void LoadList()
{
dataGridView.DataSource = _disciplineRepository.ReadDiscipline();
dataGridView.Columns["Id"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{
@@ -51,7 +54,6 @@ namespace ProjectTimeTable.Forms
Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
return true;
}
private void ButtonAdd_Click(object sender, EventArgs e)
{
try

View File

@@ -51,10 +51,7 @@ namespace ProjectTimeTable.Forms
comboBoxPlan.DataSource = planRepository.ReadPlan();
comboBoxPlan.DisplayMember = "Name";
comboBoxPlan.ValueMember = "Id";
}
private void ButtonSave_Click(object sender, EventArgs e)
{
try
@@ -86,7 +83,6 @@ namespace ProjectTimeTable.Forms
private Group CreateGroup(int id) => Group.CreateEntity(id, TextBoxName.Text,
Convert.ToInt32(numericUpDownCourse.Value), Convert.ToInt32(numericUpDownCount.Value), (int)comboBoxPlan.SelectedValue!);
private void ButtonCancel_Click(object sender, EventArgs e) => Close();
}
}

View File

@@ -35,7 +35,11 @@ namespace ProjectTimeTable.Forms
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadList() => dataGridView.DataSource = _groupRepository.ReadGroup();
private void LoadList()
{
dataGridView.DataSource = _groupRepository.ReadGroup();
dataGridView.Columns["Id"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{

View File

@@ -89,7 +89,5 @@ namespace ProjectTimeTable.Forms
return list;
}
}
}

View File

@@ -0,0 +1,169 @@
namespace ProjectTimeTable.Forms
{
partial class FormPlanReport
{
/// <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()
{
label1 = new Label();
textBoxFilePath = new TextBox();
ButtonSelectFilePath = new Button();
label2 = new Label();
comboBoxdiscipline = new ComboBox();
label3 = new Label();
numericUpDown = new NumericUpDown();
label4 = new Label();
comboBoxgroup = new ComboBox();
ButtonMakeReport = new Button();
((System.ComponentModel.ISupportInitialize)numericUpDown).BeginInit();
SuspendLayout();
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(18, 43);
label1.Name = "label1";
label1.Size = new Size(109, 20);
label1.TabIndex = 0;
label1.Text = "Путь до файла";
//
// textBoxFilePath
//
textBoxFilePath.Location = new Point(133, 40);
textBoxFilePath.Name = "textBoxFilePath";
textBoxFilePath.Size = new Size(125, 27);
textBoxFilePath.TabIndex = 1;
//
// ButtonSelectFilePath
//
ButtonSelectFilePath.Location = new Point(264, 38);
ButtonSelectFilePath.Name = "ButtonSelectFilePath";
ButtonSelectFilePath.Size = new Size(32, 29);
ButtonSelectFilePath.TabIndex = 2;
ButtonSelectFilePath.Text = "...";
ButtonSelectFilePath.UseVisualStyleBackColor = true;
ButtonSelectFilePath.Click += ButtonSelectFilePath_Click;
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(18, 97);
label2.Name = "label2";
label2.Size = new Size(60, 20);
label2.TabIndex = 3;
label2.Text = "Неделя";
//
// comboBoxdiscipline
//
comboBoxdiscipline.FormattingEnabled = true;
comboBoxdiscipline.Location = new Point(133, 140);
comboBoxdiscipline.Name = "comboBoxdiscipline";
comboBoxdiscipline.Size = new Size(151, 28);
comboBoxdiscipline.TabIndex = 4;
//
// label3
//
label3.AutoSize = true;
label3.Location = new Point(18, 143);
label3.Name = "label3";
label3.Size = new Size(96, 20);
label3.TabIndex = 5;
label3.Text = "Дисциплина";
//
// numericUpDown
//
numericUpDown.Location = new Point(136, 95);
numericUpDown.Maximum = new decimal(new int[] { 2, 0, 0, 0 });
numericUpDown.Minimum = new decimal(new int[] { 1, 0, 0, 0 });
numericUpDown.Name = "numericUpDown";
numericUpDown.Size = new Size(150, 27);
numericUpDown.TabIndex = 6;
numericUpDown.Value = new decimal(new int[] { 1, 0, 0, 0 });
//
// label4
//
label4.AutoSize = true;
label4.Location = new Point(18, 189);
label4.Name = "label4";
label4.Size = new Size(58, 20);
label4.TabIndex = 7;
label4.Text = "Группа";
//
// comboBoxgroup
//
comboBoxgroup.FormattingEnabled = true;
comboBoxgroup.Location = new Point(133, 189);
comboBoxgroup.Name = "comboBoxgroup";
comboBoxgroup.Size = new Size(151, 28);
comboBoxgroup.TabIndex = 8;
//
// ButtonMakeReport
//
ButtonMakeReport.Location = new Point(89, 257);
ButtonMakeReport.Name = "ButtonMakeReport";
ButtonMakeReport.Size = new Size(148, 29);
ButtonMakeReport.TabIndex = 9;
ButtonMakeReport.Text = "Сформировать";
ButtonMakeReport.UseVisualStyleBackColor = true;
ButtonMakeReport.Click += ButtonMakeReport_Click;
//
// FormPlanReport
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(340, 318);
Controls.Add(ButtonMakeReport);
Controls.Add(comboBoxgroup);
Controls.Add(label4);
Controls.Add(numericUpDown);
Controls.Add(label3);
Controls.Add(comboBoxdiscipline);
Controls.Add(label2);
Controls.Add(ButtonSelectFilePath);
Controls.Add(textBoxFilePath);
Controls.Add(label1);
Name = "FormPlanReport";
StartPosition = FormStartPosition.CenterParent;
Text = "FormPlanReport";
((System.ComponentModel.ISupportInitialize)numericUpDown).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private Label label1;
private TextBox textBoxFilePath;
private Button ButtonSelectFilePath;
private Label label2;
private ComboBox comboBoxdiscipline;
private Label label3;
private NumericUpDown numericUpDown;
private Label label4;
private ComboBox comboBoxgroup;
private Button ButtonMakeReport;
}
}

View File

@@ -0,0 +1,87 @@
using ProjectTimeTable.Reports;
using ProjectTimeTable.Repositories;
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 ProjectTimeTable.Forms
{
public partial class FormPlanReport : Form
{
private readonly IUnityContainer _container;
public FormPlanReport(IUnityContainer container, IDisciplineRepositories disciplineRepository, IGroupRepositories groupRepository)
{
InitializeComponent();
_container = container ?? throw new ArgumentNullException(nameof(container));
comboBoxdiscipline.DataSource = disciplineRepository.ReadDiscipline();
comboBoxdiscipline.DisplayMember = "Name";
comboBoxdiscipline.ValueMember = "Id";
comboBoxgroup.DataSource = groupRepository.ReadGroup();
comboBoxgroup.DisplayMember = "Name";
comboBoxgroup.ValueMember = "Id";
}
private void ButtonSelectFilePath_Click(object sender, EventArgs e)
{
var sfd = new SaveFileDialog()
{
Filter = "Excel Files | *.xlsx"
};
if (sfd.ShowDialog() != DialogResult.OK)
{
return;
}
textBoxFilePath.Text = sfd.FileName;
}
private void ButtonMakeReport_Click(object sender, EventArgs e)
{
try
{
if (string.IsNullOrWhiteSpace(textBoxFilePath.Text))
{
throw new Exception("Отсутствует имя файла для отчета");
}
if (comboBoxdiscipline.SelectedIndex < 0 || comboBoxgroup.SelectedIndex < 0)
{
throw new Exception("Не выбраны данные");
}
if
(_container.Resolve<TableReport>().CreateTable(textBoxFilePath.Text, Convert.ToInt32 (numericUpDown.Value),
(int)comboBoxdiscipline.SelectedValue!, (int)comboBoxgroup.SelectedValue!))
{
MessageBox.Show("Документ сформирован",
"Формирование документа",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Возникли ошибки при формировании документа.Подробности в логах",
"Формирование документа",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при создании очета",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

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

@@ -22,7 +22,6 @@ namespace ProjectTimeTable.Forms
_container = container ?? throw new ArgumentNullException(nameof(container));
_planRepository = planRepository ?? throw new ArgumentNullException(nameof(planRepository));
}
private void FormPlans_Load(object sender, EventArgs e)
{
try
@@ -35,7 +34,11 @@ namespace ProjectTimeTable.Forms
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadList() => dataGridView.DataSource = _planRepository.ReadPlan();
private void LoadList()
{
dataGridView.DataSource = _planRepository.ReadPlan();
dataGridView.Columns["Id"].Visible = false;
}
private void ButtonAdd_Click(object sender, EventArgs e)
{

View File

@@ -18,7 +18,6 @@ namespace ProjectTimeTable.Forms
private readonly ITeacherRepositories _teacherRepository;
private int? _teacherId;
public int Id
{
set
@@ -51,7 +50,6 @@ namespace ProjectTimeTable.Forms
comboBoxPost.DataSource =Enum.GetValues(typeof(TeacherPost));
}
private void ButtonSave_Click(object sender, EventArgs e)
{
try
@@ -82,10 +80,7 @@ namespace ProjectTimeTable.Forms
}
}
private void ButtonCancel_Click(object sender, EventArgs e) => Close();
private Teacher CreateTeacher(int id) => Teacher.CreateEntity(id, textBoxFirstName.Text, textBoxSecondName.Text,
textBoxLastName.Text, (TeacherPost)comboBoxPost.SelectedItem!);
}

View File

@@ -23,9 +23,7 @@ namespace ProjectTimeTable.Forms
throw new ArgumentNullException(nameof(container));
_teacherRepository = teacherRepository ??
throw new ArgumentNullException(nameof(teacherRepository));
}
private void ButtonAdd_Click(object sender, EventArgs e)
{
try
@@ -64,7 +62,6 @@ namespace ProjectTimeTable.Forms
MessageBox.Show(ex.Message, "Ошибка при удалении",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void ButtonUpd_Click(object sender, EventArgs e)
{
@@ -85,9 +82,7 @@ namespace ProjectTimeTable.Forms
MessageBox.Show(ex.Message, "Ошибка при изменении",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void FormTeachers_Load(object sender, EventArgs e)
{
try
@@ -99,11 +94,13 @@ namespace ProjectTimeTable.Forms
MessageBox.Show(ex.Message, "Ошибка при загрузке",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadList() => dataGridView.DataSource =_teacherRepository.ReadTeacher();
private void LoadList()
{
dataGridView.DataSource = _teacherRepository.ReadTeacher();
dataGridView.Columns["Id"].Visible = false;
dataGridView.Columns["FullName"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{
id = 0;

View File

@@ -36,7 +36,7 @@ namespace ProjectTimeTable.Forms
ColumnGroup.ValueMember = "Id";
ColumnTeacher.DataSource = teacherRepository.ReadTeacher();
ColumnTeacher.DisplayMember = "FirstName";
ColumnTeacher.DisplayMember = "FullName";
ColumnTeacher.ValueMember = "Id";
}
@@ -49,8 +49,6 @@ namespace ProjectTimeTable.Forms
{
throw new Exception("Имеются незаполненные поля");
}
dataGridViewTimeTable.RowCount--;
_timeTableRepository.CreateTimeTable(TimeTable.CreateOperation(0, Convert.ToInt32(numericUpDownCountLesson.Value),
Convert.ToInt32(numericUpDownDay.Value), Convert.ToInt32(numericUpDownWeek.Value),
CreateListGroupTimeTableFromDataGrid()));
@@ -66,8 +64,6 @@ namespace ProjectTimeTable.Forms
private void ButtonCancel_Click(object sender, EventArgs e) =>
Close();
private List<GroupTimetable> CreateListGroupTimeTableFromDataGrid()
{
var list = new List<GroupTimetable>();
@@ -79,14 +75,10 @@ namespace ProjectTimeTable.Forms
continue;
}
list.Add(GroupTimetable.CreateElement(Convert.ToInt32(comboBoxDiscipline.SelectedIndex), Convert.ToInt32(comboBoxAuditorium.SelectedIndex),
Convert.ToInt32(comboBoxGroup.SelectedIndex), Convert.ToInt32(comboBoxTeacher.SelectedIndex), 0));
list.Add(GroupTimetable.CreateElement(0,Convert.ToInt32(row.Cells["ColumnDiscipline"].Value), Convert.ToInt32(row.Cells["ColumnAuditorium"].Value),
Convert.ToInt32(row.Cells["ColumnGroup"].Value), Convert.ToInt32(row.Cells["ColumnTeacher"].Value)));
}
return list;
}
}
}

View File

@@ -0,0 +1,112 @@
namespace ProjectTimeTable.Forms
{
partial class FormTimeTableNumberLessonDistributionReport
{
/// <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()
{
ButtonSelectFileName = new Button();
labelFileName = new Label();
label2 = new Label();
numericUpDownweek = new NumericUpDown();
ButtonCreate = new Button();
((System.ComponentModel.ISupportInitialize)numericUpDownweek).BeginInit();
SuspendLayout();
//
// ButtonSelectFileName
//
ButtonSelectFileName.Location = new Point(56, 51);
ButtonSelectFileName.Name = "ButtonSelectFileName";
ButtonSelectFileName.Size = new Size(94, 29);
ButtonSelectFileName.TabIndex = 0;
ButtonSelectFileName.Text = "Выбрать";
ButtonSelectFileName.UseVisualStyleBackColor = true;
ButtonSelectFileName.Click += ButtonSelectFileName_Click;
//
// labelFileName
//
labelFileName.AutoSize = true;
labelFileName.Location = new Point(202, 56);
labelFileName.Name = "labelFileName";
labelFileName.Size = new Size(45, 20);
labelFileName.TabIndex = 1;
labelFileName.Text = "Файл";
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(56, 117);
label2.Name = "label2";
label2.Size = new Size(60, 20);
label2.TabIndex = 2;
label2.Text = "Неделя";
//
// numericUpDownweek
//
numericUpDownweek.Location = new Point(202, 110);
numericUpDownweek.Maximum = new decimal(new int[] { 2, 0, 0, 0 });
numericUpDownweek.Minimum = new decimal(new int[] { 1, 0, 0, 0 });
numericUpDownweek.Name = "numericUpDownweek";
numericUpDownweek.Size = new Size(150, 27);
numericUpDownweek.TabIndex = 3;
numericUpDownweek.Value = new decimal(new int[] { 1, 0, 0, 0 });
//
// ButtonCreate
//
ButtonCreate.Location = new Point(122, 173);
ButtonCreate.Name = "ButtonCreate";
ButtonCreate.Size = new Size(125, 29);
ButtonCreate.TabIndex = 4;
ButtonCreate.Text = "Сформировать";
ButtonCreate.UseVisualStyleBackColor = true;
ButtonCreate.Click += ButtonCreate_Click;
//
// FormTimeTableNumberLessonDistributionReport
//
AutoScaleDimensions = new SizeF(8F, 20F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(402, 235);
Controls.Add(ButtonCreate);
Controls.Add(numericUpDownweek);
Controls.Add(label2);
Controls.Add(labelFileName);
Controls.Add(ButtonSelectFileName);
Name = "FormTimeTableNumberLessonDistributionReport";
Text = "Распределние количества дисциплин";
((System.ComponentModel.ISupportInitialize)numericUpDownweek).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private Button ButtonSelectFileName;
private Label labelFileName;
private Label label2;
private NumericUpDown numericUpDownweek;
private Button ButtonCreate;
}
}

View File

@@ -0,0 +1,71 @@
using ProjectTimeTable.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 ProjectTimeTable.Forms
{
public partial class FormTimeTableNumberLessonDistributionReport : Form
{
private string _fileName = string.Empty;
private readonly IUnityContainer _container;
public FormTimeTableNumberLessonDistributionReport(IUnityContainer container)
{
InitializeComponent();
_container = container ?? throw new ArgumentNullException(nameof(container));
}
private void ButtonSelectFileName_Click(object sender, EventArgs e)
{
var sfd = new SaveFileDialog()
{
Filter = "Pdf Files | *.pdf"
};
if (sfd.ShowDialog() == DialogResult.OK)
{
_fileName = sfd.FileName;
labelFileName.Text = Path.GetFileName(_fileName);
}
}
private void ButtonCreate_Click(object sender, EventArgs e)
{
try
{
if (string.IsNullOrWhiteSpace(_fileName))
{
throw new Exception("Отсутствует имя файла для отчета");
}
if
(_container.Resolve<ChartReport>().CreateChart(_fileName, Convert.ToInt32(numericUpDownweek.Value)))
{
MessageBox.Show("Документ сформирован",
"Формирование документа",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
MessageBox.Show("Возникли ошибки при формировании документа.Подробности в логах",
"Формирование документа",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Ошибка при создании очета",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

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

@@ -36,7 +36,11 @@ namespace ProjectTimeTable.Forms
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadList() => dataGridView.DataSource = _timeTableRepository.ReadTimeTable();
private void LoadList()
{
dataGridView.DataSource = _timeTableRepository.ReadTimeTable();
dataGridView.Columns["Id"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{
@@ -79,7 +83,6 @@ namespace ProjectTimeTable.Forms
{
return;
}
try
{
_timeTableRepository.DeleteTimeTable(findId);
@@ -91,7 +94,5 @@ namespace ProjectTimeTable.Forms
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

View File

@@ -10,10 +10,12 @@
<ItemGroup>
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="DocumentFormat.OpenXml" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="PdfSharp.MigraDoc.Standard" Version="1.51.15" />
<PackageReference Include="Serilog" Version="4.1.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.4" />

View File

@@ -0,0 +1,67 @@
using CarpentryWorkshop.Reports;
using Microsoft.Extensions.Logging;
using ProjectTimeTable.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProjectTimeTable.Reports;
internal class ChartReport
{
private readonly ITimeTableRepositories _timetableRepository;
private readonly IDisciplineRepositories _disciplineRepository;
private readonly ILogger<ChartReport> _logger;
public ChartReport(ITimeTableRepositories timetableRepository,
ILogger<ChartReport> logger, IDisciplineRepositories disciplineRepository)
{
_timetableRepository = timetableRepository ??
throw new
ArgumentNullException(nameof(timetableRepository));
_disciplineRepository = disciplineRepository ??
throw new
ArgumentNullException(nameof(timetableRepository));
_logger = logger ??
throw new ArgumentNullException(nameof(logger));
}
public bool CreateChart(string filePath, int week)
{
try
{
new PdfBuilder(filePath)
.AddHeader("Количество дисциплин за неделю")
.AddPieChart("Количество", GetData(week))
.Build();
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при формировании документа");
return false;
}
}
private List<(string Caption, double Value)> GetData(int week)
{
var data = _timetableRepository
.ReadTimeTable(week);
foreach (var row in data)
{
row.DisciplineName = row.GroupTime.Split('|').First();
}
var result = data
.GroupBy(x => x.DisciplineName, (key, group) => new
{
DisciplineName = key,
Count = group.Sum(y => y.NumberLesson)
})
.Select(x => (x.DisciplineName.ToString(), (double)x.Count))
.ToList();
return result;
}
}

View File

@@ -0,0 +1,109 @@
using Microsoft.Extensions.Logging;
using ProjectTimeTable.Repositories;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProjectTimeTable.Reports;
internal class DocReport
{
private readonly IGroupRepositories _groupRepository;
private readonly ITeacherRepositories _teacherRepository;
private readonly IAuditoriumRepositories _auditoriumRepository;
private readonly IDisciplineRepositories _disciplineRepository;
private readonly ILogger<DocReport> _logger;
public DocReport(IGroupRepositories groupRepository, ITeacherRepositories
teacherRepository, IAuditoriumRepositories auditoriumRepository,
IDisciplineRepositories disciplineRepository, ILogger<DocReport> logger)
{
_auditoriumRepository = auditoriumRepository ?? throw new ArgumentNullException(nameof(auditoriumRepository));
_groupRepository = groupRepository ?? throw new ArgumentNullException(nameof(groupRepository));
_disciplineRepository = disciplineRepository ?? throw new ArgumentNullException(nameof(disciplineRepository));
_teacherRepository = teacherRepository ?? throw new ArgumentNullException(nameof(teacherRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public bool CreateDoc(string filePath, bool includeGroup, bool
includeTeacher, bool includeAuditorium, bool includeDiscipline)
{
try
{
var builder = new WordBuilder(filePath)
.AddHeader("Документ со справочниками");
if (includeGroup)
{
builder.AddParagraph("Группы")
.AddTable([2400, 1200, 1200, 1200],
GetGroup());
}
if (includeTeacher)
{
builder.AddParagraph("Преподаватели")
.AddTable([2400, 2400, 2400, 2400], GetTeacher());
}
if (includeAuditorium)
{
builder.AddParagraph("Аудитории")
.AddTable([2400, 2400, 1200], GetAuditorium());
}
if (includeDiscipline)
{
builder.AddParagraph("Дисциплины")
.AddTable([2400], GetDiscipline());
}
builder.Build();
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при формировании документа");
return false;
}
}
private List<string[]> GetGroup()
{
return [
["Название группы", "Курс", "Количество человек", "Номер плана"],
.. _groupRepository
.ReadGroup()
.Select(x => new string[] { x.Name, x.Course.ToString(), x.CountPeople.ToString(), x.PlanID.ToString() }),
];
}
private List<string[]> GetTeacher()
{
return [
["Имя", "Фамилия", "Отчество", "Должность"],
.. _teacherRepository
.ReadTeacher()
.Select(x => new string[] { x.FirstName, x.SecondName, x.LastName, x.TeacherPost.ToString() }),
];
}
private List<string[]> GetAuditorium()
{
return [
["Название", "Тип аудитории", "Размер"],
.. _auditoriumRepository
.ReadAuditorium()
.Select(x => new string[] { x.Name, x.ClassType.ToString(), x.Size.ToString() }),
];
}
private List<string[]> GetDiscipline()
{
return [
["Название"],
.. _disciplineRepository
.ReadDiscipline()
.Select(x => new string[] { x.Name}),
];
}
}

View File

@@ -0,0 +1,347 @@
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProjectTimeTable.Reports;
internal class ExcelBuilder
{
private readonly string _filePath;
private readonly SheetData _sheetData;
private readonly MergeCells _mergeCells;
private readonly Columns _columns;
private uint _rowIndex = 0;
public ExcelBuilder(string filePath)
{
if (string.IsNullOrWhiteSpace(filePath))
{
throw new ArgumentNullException(nameof(filePath));
}
if (File.Exists(filePath))
{
File.Delete(filePath);
}
_filePath = filePath;
_sheetData = new SheetData();
_mergeCells = new MergeCells();
_columns = new Columns();
_rowIndex = 1;
}
public ExcelBuilder AddHeader(string header, int startIndex, int count)
{
CreateCell(startIndex, _rowIndex, header, StyleIndex.BoldTextWithoutBorder);
for (int i = startIndex + 1; i < startIndex + count; ++i)
{
CreateCell(i, _rowIndex, "",StyleIndex.SimpleTextWithoutBorder);
}
_mergeCells.Append(new MergeCell()
{
Reference =
new
StringValue($"{GetExcelColumnName(startIndex)}{_rowIndex}:{GetExcelColumnName(startIndex + count - 1)}{_rowIndex}")
});
_rowIndex++;
return this;
}
public ExcelBuilder AddParagraph(string text, int columnIndex)
{
CreateCell(columnIndex, _rowIndex++, text, StyleIndex.SimpleTextWithoutBorder);
return this;
}
public ExcelBuilder AddTable(int[] columnsWidths, List<string[]> data)
{
if (columnsWidths == null || columnsWidths.Length == 0)
{
throw new ArgumentNullException(nameof(columnsWidths));
}
if (data == null || data.Count == 0)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Any(x => x.Length != columnsWidths.Length))
{
throw new InvalidOperationException("widths.Length != data.Length");
}
uint counter = 1;
int coef = 2;
_columns.Append(columnsWidths.Select(x => new Column
{
Min = counter,
Max = counter++,
Width = x * coef,
CustomWidth = true
}));
// Добавление заголовка
for (var j = 0; j < data.First().Length; ++j)
{
CreateCell(j, _rowIndex, data.First()[j], StyleIndex.BoldTextWithBorder);
}
_rowIndex++;
// Добавление основных данных
for (var i = 1; i < data.Count - 1; ++i)
{
for (var j = 0; j < data[i].Length; ++j)
{
CreateCell(j, _rowIndex, data[i][j], StyleIndex.SimpleTextWithBorder);
}
_rowIndex++;
}
// Добавление итоговой строки
for (var j = 0; j < data.Last().Length; ++j)
{
CreateCell(j, _rowIndex, data.Last()[j], StyleIndex.BoldTextWithBorder);
}
_rowIndex++;
return this;
}
public void Build()
{
using var spreadsheetDocument = SpreadsheetDocument.Create(_filePath,
SpreadsheetDocumentType.Workbook);
var workbookpart = spreadsheetDocument.AddWorkbookPart();
GenerateStyle(workbookpart);
workbookpart.Workbook = new Workbook();
var worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
if (_columns.HasChildren)
{
worksheetPart.Worksheet.Append(_columns);
}
worksheetPart.Worksheet.Append(_sheetData);
var sheets =
spreadsheetDocument.WorkbookPart!.Workbook.AppendChild(new Sheets());
var sheet = new Sheet()
{
Id =
spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart),
SheetId = 1,
Name = "Лист 1"
};
sheets.Append(sheet);
if (_mergeCells.HasChildren)
{
worksheetPart.Worksheet.InsertAfter(_mergeCells,
worksheetPart.Worksheet.Elements<SheetData>().First());
}
}
private static void GenerateStyle(WorkbookPart workbookPart)
{
var workbookStylesPart =
workbookPart.AddNewPart<WorkbookStylesPart>();
workbookStylesPart.Stylesheet = new Stylesheet();
var fonts = new Fonts()
{
Count = 2,
KnownFonts =
BooleanValue.FromBoolean(true)
};
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
{
FontSize = new FontSize() { Val = 11 },
FontName = new FontName() { Val = "Calibri" },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
FontScheme = new FontScheme()
{
Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor)
}
});
// TODO добавить шрифт с жирным
fonts.Append(new DocumentFormat.OpenXml.Spreadsheet.Font
{
FontSize = new FontSize() { Val = 11 },
FontName = new FontName() { Val = "Calibri" },
FontFamilyNumbering = new FontFamilyNumbering() { Val = 2 },
FontScheme = new FontScheme()
{
Val = new EnumValue<FontSchemeValues>(FontSchemeValues.Minor)
},
Bold = new Bold() { Val = true }
});
workbookStylesPart.Stylesheet.Append(fonts);
// Default Fill
var fills = new Fills() { Count = 1 };
fills.Append(new Fill
{
PatternFill = new PatternFill()
{
PatternType = new
EnumValue<PatternValues>(PatternValues.None)
}
});
workbookStylesPart.Stylesheet.Append(fills);
// Default Border
var borders = new Borders() { Count = 2 };
borders.Append(new Border
{
LeftBorder = new LeftBorder(),
RightBorder = new RightBorder(),
TopBorder = new TopBorder(),
BottomBorder = new BottomBorder(),
DiagonalBorder = new DiagonalBorder()
});
// TODO добавить настройку с границами
borders.Append(new Border
{
LeftBorder = new LeftBorder() { Style = BorderStyleValues.Thin },
RightBorder = new RightBorder() { Style = BorderStyleValues.Thin },
TopBorder = new TopBorder() { Style = BorderStyleValues.Thin },
BottomBorder = new BottomBorder() { Style = BorderStyleValues.Thin },
DiagonalBorder = new DiagonalBorder()
});
workbookStylesPart.Stylesheet.Append(borders);
// Default cell format and a date cell format
var cellFormats = new CellFormats() { Count = 4 };
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 0,
BorderId = 0,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Left,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
// TODO дополнить форматы
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 0,
BorderId = 1,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Right,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 1,
BorderId = 0,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Center,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
cellFormats.Append(new CellFormat
{
NumberFormatId = 0,
FormatId = 0,
FontId = 1,
BorderId = 1,
FillId = 0,
Alignment = new Alignment()
{
Horizontal = HorizontalAlignmentValues.Center,
Vertical = VerticalAlignmentValues.Center,
WrapText = true
}
});
workbookStylesPart.Stylesheet.Append(cellFormats);
}
private enum StyleIndex
{
// TODO дополнить стили
SimpleTextWithoutBorder = 0,
SimpleTextWithBorder = 1,
BoldTextWithoutBorder = 2,
BoldTextWithBorder = 3,
}
private void CreateCell(int columnIndex, uint rowIndex, string text,
StyleIndex styleIndex)
{
var columnName = GetExcelColumnName(columnIndex);
var cellReference = columnName + rowIndex;
var row = _sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex!
== rowIndex);
if (row == null)
{
row = new Row() { RowIndex = rowIndex };
_sheetData.Append(row);
}
var newCell = row.Elements<Cell>()
.FirstOrDefault(c => c.CellReference != null &&
c.CellReference.Value == columnName + rowIndex);
if (newCell == null)
{
Cell? refCell = null;
foreach (Cell cell in row.Elements<Cell>())
{
if (cell.CellReference?.Value != null &&
cell.CellReference.Value.Length == cellReference.Length)
{
if (string.Compare(cell.CellReference.Value,
cellReference, true) > 0)
{
refCell = cell;
break;
}
}
}
newCell = new Cell() { CellReference = cellReference };
row.InsertBefore(newCell, refCell);
}
newCell.CellValue = new CellValue(text);
newCell.DataType = CellValues.String;
newCell.StyleIndex = (uint)styleIndex;
}
private static string GetExcelColumnName(int columnNumber)
{
columnNumber += 1;
int dividend = columnNumber;
string columnName = string.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo).ToString() +
columnName;
dividend = (dividend - modulo) / 26;
}
return columnName;
}
}

View File

@@ -0,0 +1,75 @@
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Shapes.Charts;
using MigraDoc.Rendering;
using System.Text;
namespace CarpentryWorkshop.Reports;
internal class PdfBuilder
{
private readonly string _filePath;
private readonly Document _document;
public PdfBuilder(string filePath)
{
if (string.IsNullOrWhiteSpace(filePath))
{
throw new ArgumentNullException(nameof(filePath));
}
if (File.Exists(filePath))
{
File.Delete(filePath);
}
_filePath = filePath;
_document = new Document();
DefineStyles();
}
public PdfBuilder AddHeader(string header)
{
_document.AddSection().AddParagraph(header, "NormalBold");
return this;
}
public PdfBuilder AddPieChart(string title, List<(string Caption, double Value)> data)
{
if (data == null || data.Count == 0)
{
return this;
}
var chart = new Chart(ChartType.Pie2D);
var series = chart.SeriesCollection.AddSeries();
series.Add(data.Select(x => x.Value).ToArray());
var xseries = chart.XValues.AddXSeries();
xseries.Add(data.Select(x => x.Caption).ToArray());
chart.DataLabel.Type = DataLabelType.Percent;
chart.DataLabel.Position = DataLabelPosition.OutsideEnd;
chart.Width = Unit.FromCentimeter(16);
chart.Height = Unit.FromCentimeter(12);
chart.TopArea.AddParagraph(title);
chart.XAxis.MajorTickMark = TickMarkType.Outside;
chart.YAxis.MajorTickMark = TickMarkType.Outside;
chart.YAxis.HasMajorGridlines = true;
chart.PlotArea.LineFormat.Width = 1;
chart.PlotArea.LineFormat.Visible = true;
chart.TopArea.AddLegend();
_document.LastSection.Add(chart);
return this;
}
public void Build()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var renderer = new PdfDocumentRenderer(true)
{
Document = _document
};
renderer.RenderDocument();
renderer.PdfDocument.Save(_filePath);
}
private void DefineStyles()
{
var headerStyle = _document.Styles.AddStyle("NormalBold", "Normal");
headerStyle.Font.Bold = true;
headerStyle.Font.Size = 14;
}
}

View File

@@ -0,0 +1,124 @@
using DocumentFormat.OpenXml.Wordprocessing;
using Microsoft.Extensions.Logging;
using ProjectTimeTable.Entites;
using ProjectTimeTable.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProjectTimeTable.Reports;
internal class TableReport
{
private readonly IPlanRepositories _planRepository;
private readonly ITimeTableRepositories _timeTableRepository;
private readonly IDisciplineRepositories _disciplineRepositories;
private readonly IGroupRepositories _groupRepositories;
private readonly ILogger<TableReport> _logger;
public TableReport(IPlanRepositories planRepository, ITimeTableRepositories timeTableRepository, IDisciplineRepositories disciplineRepositories,
IGroupRepositories groupRepositories, ILogger<TableReport> logger)
{
_planRepository = planRepository ?? throw new ArgumentNullException(nameof(planRepository));
_timeTableRepository = timeTableRepository ?? throw new ArgumentNullException(nameof(timeTableRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_disciplineRepositories = disciplineRepositories ?? throw new ArgumentException(nameof(disciplineRepositories));
_groupRepositories = groupRepositories ?? throw new ArgumentException(nameof(groupRepositories));
}
public bool CreateTable(string filePath, int week, int discilineId, int groupId)
{
try
{
new ExcelBuilder(filePath)
.AddHeader("Сводка по количеству дисциплин на курсе", 0, 3)
.AddParagraph($"По неделе {week}", 0)
.AddTable([10, 10, 15, 10], GetData(week, discilineId, groupId))
.Build();
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при формировании документа");
return false;
}
}
private List<string[]> GetData(int week, int disciplineId, int groupId)
{
var timeTableData = _timeTableRepository
.ReadTimeTable()
.Where(x => x.Week == week)
.Select(x => new
{
Week = (int?)x.Week,
GroupName = (string?)null,
Discipline = (string?)null,
CountLesson = (int?)x.NumberLesson
});
var disciplineData = _disciplineRepositories
.ReadDiscipline()
.Where(x => x.ID == disciplineId)
.Select(x => new
{
Week = (int?)null,
GroupName = (string?)null,
Discipline = (string)x.Name,
CountLesson = (int?)null
});
var groupData = _groupRepositories
.ReadGroup()
.Where(x => x.Id == groupId)
.Select(x => new
{
Week = (int?)null,
GroupName = (string)x.Name,
Discipline = (string?)null,
CountLesson = (int?)null
});
// Объединение данных с использованием CrossJoin
var result = from t in timeTableData
from d in disciplineData
from g in groupData
select new
{
Week = t.Week,
GroupName = g?.GroupName ?? string.Empty,
Discipline = d?.Discipline ?? string.Empty,
CountLesson = t.CountLesson ?? 0
};
// Преобразование данных в строки
var reportData = result
.Select(x => new string[]
{
x.Week.ToString() ?? string.Empty,
x.Discipline,
x.GroupName,
x.CountLesson.ToString()
})
.ToList();
reportData.Insert(0, new string[] { "Неделя", "Дисциплина", "Группа", "Количество пар" });
// Добавление итоговой строки
reportData.Add(new string[]
{
"Всего",
"",
"",
result.Sum(x => x.CountLesson).ToString()
});
return reportData;
}
}

View File

@@ -0,0 +1,142 @@
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 ProjectTimeTable.Reports;
public 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());
// TODO прописать настройки под жирный текст
var runProperties = run.AppendChild(new RunProperties());
runProperties.AppendChild(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<string[]> 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>(BorderValues.Single),
Size = 12
},
new BottomBorder()
{
Val = new
EnumValue<BorderValues>(BorderValues.Single),
Size = 12
},
new LeftBorder()
{
Val = new
EnumValue<BorderValues>(BorderValues.Single),
Size = 12
},
new RightBorder()
{
Val = new
EnumValue<BorderValues>(BorderValues.Single),
Size = 12
},
new InsideHorizontalBorder()
{
Val = new
EnumValue<BorderValues>(BorderValues.Single),
Size = 12
},
new InsideVerticalBorder()
{
Val = new
EnumValue<BorderValues>(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;
}
}

View File

@@ -54,7 +54,6 @@ public class AuditoriumRepositories : IAuditoriumRepositories
throw;
}
}
public IEnumerable<Auditorium> ReadAuditorium()
{
_logger.LogInformation("Получение всех объектов");
@@ -73,7 +72,6 @@ public class AuditoriumRepositories : IAuditoriumRepositories
throw;
}
}
public Auditorium ReadAuditoriumById(int id)
{
_logger.LogInformation("Получение объекта по идентификатору");
@@ -96,8 +94,6 @@ public class AuditoriumRepositories : IAuditoriumRepositories
throw;
}
}
public void UpdateAuditorium(Auditorium classs)
{
_logger.LogInformation("Редактирование объекта");

View File

@@ -63,7 +63,11 @@ public class GroupRepositories : IGroupRepositories
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = "SELECT * FROM Groupp";
var querySelect = @"
SELECT g.*, op.Name AS PlanName
FROM Groupp g
INNER JOIN Plan AS op ON op.ID = g.PlanID";
var group = connection.Query<Group>(querySelect);
_logger.LogDebug("Полученные объекты: {json}",
JsonConvert.SerializeObject(group));

View File

@@ -9,6 +9,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unity;
using DocumentFormat.OpenXml.Drawing.Charts;
using static System.Runtime.InteropServices.JavaScript.JSType;
using System.Numerics;
namespace ProjectTimeTable.Repositories.Implementation;
@@ -55,17 +58,48 @@ public class PlanRepositories : IPlanRepositories
throw;
}
}
public IEnumerable<Plan> ReadPlan(int? groupId = null, int? disciplineId = null)
{
_logger.LogInformation("Получение всех объектов");
try
{
var builder = new QueryBuilder();
if (disciplineId.HasValue)
{
builder.AddCondition("dp.DisciplineID = @disciplineId");
}
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"SELECT * FROM Plan";
var plan = connection.Query<Plan>(querySelect);
_logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(plan));
return plan;
var querySelect = $@"
SELECT p.*, d.Name AS DisciplineName, dp.CountLesson AS CountLesson, dp.Course as Course
FROM Plan p
INNER JOIN DisciplinePlan AS dp ON dp.PlanID = p.Id
INNER JOIN Discipline AS d ON d.ID = dp.DisciplineID
{builder.Build()}";
var planDict = new Dictionary<int, List<DisciplinePlan>>();
var plans =
connection.Query<Plan, DisciplinePlan, Plan>(querySelect, (plan, disciplineplans) =>
{
if (!planDict.TryGetValue(plan.Id, out var frr))
{
frr = [];
planDict.Add(plan.Id, frr);
}
frr.Add(disciplineplans);
return plan;
}, splitOn: "DisciplineName", param: new { disciplineId });
_logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(plans));
return planDict.Select(x =>
{
var fr = plans.First(y => y.Id == x.Key);
fr.SetDisciplinePlan(x.Value);
return fr;
}).ToArray();
}
catch (Exception ex)
{
@@ -73,7 +107,6 @@ public class PlanRepositories : IPlanRepositories
throw;
}
}
public Plan ReadPlanById(int id)
{
_logger.LogInformation("Получение объекта по идентификатору");
@@ -81,7 +114,7 @@ public class PlanRepositories : IPlanRepositories
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"SELECT * FROM teacher WHERE [Id]=@id";
var querySelect = @"SELECT * FROM plan WHERE [Id]=@id";
var plan = connection.QueryFirst<Plan>(querySelect, new
{
id

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProjectTimeTable.Repositories.Implementation;
internal class QueryBuilder
{
private readonly StringBuilder _builder;
public QueryBuilder()
{
_builder = new();
}
public QueryBuilder AddCondition(string condition)
{
if (_builder.Length > 0)
{
_builder.Append(" AND ");
}
_builder.Append(condition);
return this;
}
public string Build()
{
if (_builder.Length == 0)
{
return string.Empty;
}
return $"WHERE {_builder}";
}
}

View File

@@ -34,15 +34,18 @@ public class TimeTableRepositories : ITimeTableRepositories
var queryInsert = @"INSERT INTO TimeTable (NumberLesson, Day, Week)
VALUES (@NumberLesson, @Day, @Week);
SELECT MAX(Id) FROM TimeTable";
var PlanID = connection.QueryFirst<int>(queryInsert, timeTable, transaction);
var querySubInsert = @"INSERT INTO GroupTimetable (GroupId, timeTableId, DisciplineID, ClassID, GroupID, TeacherID)
VALUES (@GroupId, @timeTableId, @DisciplineID, @ClassID, @GroupID, @TeacherID)";
var TimeTableID = connection.QueryFirst<int>(queryInsert, timeTable, transaction);
var querySubInsert = @"INSERT INTO GroupTimetable (timeTableId, DisciplineID, AuditoriumID, GroupID, TeacherID)
VALUES (@timeTableId, @DisciplineID, @AuditoriumID, @GroupID, @TeacherID)";
foreach (var elem in timeTable.GroupTimetable)
{
connection.Execute(querySubInsert, new
{
elem.GroupId,
elem.TimeTableId,
TimeTableID,
elem.DisciplineID,
AuditoriumID = elem.ClassID,
elem.GroupID,
elem.TeacherID
}, transaction);
}
transaction.Commit();
@@ -78,11 +81,43 @@ public class TimeTableRepositories : ITimeTableRepositories
try
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = "SELECT * FROM timetable";
var timetable = connection.Query<TimeTable>(querySelect);
_logger.LogDebug("Полученные объекты: {json}",
JsonConvert.SerializeObject(timetable));
return timetable;
var builder = new QueryBuilder();
if (week.HasValue)
{
builder.AddCondition("tt.Week = @Week");
}
var querySelect = $@"
SELECT tt.*, d.Name AS DisciplineName, a.Name AS ClassName, g.Name AS GroupName, t.FirstName AS TeacherName
FROM TimeTable tt
INNER JOIN GroupTimeTable AS gt ON gt.TimeTableId = tt.Id
INNER JOIN Discipline AS d ON d.ID = gt.DisciplineID
INNER JOIN Auditorium AS a ON a.ID = gt.AuditoriumID
INNER JOIN Groupp AS g ON g.ID = gt.GroupID
INNER JOIN Teacher AS t ON t.ID = gt.TeacherID {builder.Build()}";
var timetableDict = new Dictionary<int, List<GroupTimetable>>();
var timetables =
connection.Query<TimeTable, GroupTimetable, TimeTable>(querySelect, (timetables, grouptimetables) =>
{
if (!timetableDict.TryGetValue(timetables.Id, out var frr))
{
frr = [];
timetableDict.Add(timetables.Id, frr);
}
frr.Add(grouptimetables);
return timetables;
}, splitOn: "DisciplineName", param: new { week,day, groupId, classId, teacherId});
_logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(timetables));
return timetableDict.Select(x =>
{
var fr = timetables.First(y => y.Id == x.Key);
fr.SetTimeTableGroup(x.Value);
return fr;
}).ToArray();
}
catch (Exception ex)
{