| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- using CsvHelper;
- using Guna.UI2.WinForms;
- using Npgsql;
- using System;
- using System.Data;
- using System.Globalization;
- using System.IO;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- using System.Linq;
- namespace DeanOfficeApp
- {
- public partial class StudentForm : Form
- {
- private Guna2DataGridView dgvStudents;
- private Guna2Button btnImportCsv;
- private Guna2ComboBox cmbGroupFilter;
- private Guna2Button btnRefresh;
- private Guna2HtmlLabel lblFilter;
- private Guna2TextBox txtSearch;
- private DataTable _studentsTable;
- private readonly string _connString = "Host=245e1-rw.db.pub.dbaas.postgrespro.ru;Port=5432;Database=dbpractice;Username=mardasov_mv;Password=A4%2x$$2Ynr";
- public StudentForm()
- {
- InitializeComponent();
- this.Load += async (s, e) => await LoadAllDataAsync();
- }
- private async Task LoadAllDataAsync()
- {
- await LoadGroupsAsync();
- await LoadStudentsAsync();
- }
- private async Task LoadGroupsAsync()
- {
- try
- {
- using (var conn = new NpgsqlConnection(_connString))
- {
- await conn.OpenAsync();
- var cmd = new NpgsqlCommand("SELECT group_id, name FROM \"Group\" ORDER BY name", conn);
- var dt = new DataTable();
- dt.Load(await cmd.ExecuteReaderAsync());
- cmbGroupFilter.DisplayMember = "name";
- cmbGroupFilter.ValueMember = "group_id";
- cmbGroupFilter.DataSource = dt;
- cmbGroupFilter.SelectedIndex = -1;
- }
- }
- catch (Exception ex)
- {
- MessageBox.Show($"Ошибка загрузки групп: {ex.Message}");
- }
- }
- private async Task LoadStudentsAsync(int? groupId = null)
- {
- string sql = @"
- SELECT
- s.record_book,
- s.full_name,
- g.name AS group_name,
- COALESCE(AVG(p.grade), 0) AS average_grade
- FROM Student s
- LEFT JOIN ""Group"" g ON s.group_id = g.group_id
- LEFT JOIN Progress p ON s.record_book = p.record_book
- ";
- if (groupId.HasValue)
- sql += " WHERE g.group_id = @gid";
- sql += " GROUP BY s.record_book, s.full_name, g.name ORDER BY s.full_name";
- try
- {
- Cursor = Cursors.WaitCursor;
- using (var conn = new NpgsqlConnection(_connString))
- {
- await conn.OpenAsync();
- using (var cmd = new NpgsqlCommand(sql, conn))
- {
- if (groupId.HasValue)
- cmd.Parameters.AddWithValue("@gid", groupId.Value);
- var dt = new DataTable();
- dt.Load(await cmd.ExecuteReaderAsync());
- _studentsTable = dt;
- ApplyFilter();
- }
- }
- }
- catch (Exception ex)
- {
- MessageBox.Show($"Ошибка загрузки студентов: {ex.Message}");
- }
- finally
- {
- Cursor = Cursors.Default;
- }
- }
- private void ApplyFilter()
- {
- if (_studentsTable == null) return;
- string filterText = txtSearch.Text.Trim().ToLower();
- if (string.IsNullOrEmpty(filterText))
- {
- dgvStudents.DataSource = _studentsTable;
- }
- else
- {
- var filteredRows = _studentsTable.AsEnumerable()
- .Where(row => row["full_name"].ToString().ToLower().Contains(filterText))
- .CopyToDataTable();
- dgvStudents.DataSource = filteredRows;
- }
- if (dgvStudents.Columns.Contains("record_book"))
- dgvStudents.Columns["record_book"].Visible = false;
- dgvStudents.Columns["average_grade"].HeaderText = "Средний балл";
- dgvStudents.Columns["average_grade"].DefaultCellStyle.Format = "0.00";
- }
- private async void btnRefresh_Click(object sender, EventArgs e)
- {
- int? groupId = cmbGroupFilter.SelectedValue as int?;
- await LoadStudentsAsync(groupId);
- }
- private async void cmbGroupFilter_SelectedIndexChanged(object sender, EventArgs e)
- {
- int? groupId = cmbGroupFilter.SelectedValue as int?;
- await LoadStudentsAsync(groupId);
- }
- private void txtSearch_TextChanged(object sender, EventArgs e)
- {
- ApplyFilter();
- }
- private async void btnImportCsv_Click(object sender, EventArgs e)
- {
- using (OpenFileDialog ofd = new OpenFileDialog())
- {
- ofd.Filter = "CSV files (*.csv)|*.csv";
- if (ofd.ShowDialog() == DialogResult.OK)
- {
- try
- {
- Cursor = Cursors.WaitCursor;
- using (var reader = new StreamReader(ofd.FileName, Encoding.UTF8))
- using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
- {
- var records = csv.GetRecords<dynamic>();
- int inserted = 0, skipped = 0;
- foreach (var rec in records)
- {
- string fullName = rec.full_name;
- string birthDateStr = rec.birth_date;
- string address = rec.address;
- int groupId = int.Parse(rec.group_id);
- using (var conn = new NpgsqlConnection(_connString))
- {
- await conn.OpenAsync();
- var check = new NpgsqlCommand("SELECT COUNT(*) FROM Student WHERE full_name = @name AND birth_date = @birth", conn);
- check.Parameters.AddWithValue("@name", fullName);
- check.Parameters.AddWithValue("@birth", DateTime.Parse(birthDateStr));
- long cnt = (long)await check.ExecuteScalarAsync();
- if (cnt == 0)
- {
- var ins = new NpgsqlCommand("INSERT INTO Student (full_name, birth_date, address, group_id) VALUES (@f, @b, @a, @g)", conn);
- ins.Parameters.AddWithValue("@f", fullName);
- ins.Parameters.AddWithValue("@b", DateTime.Parse(birthDateStr));
- ins.Parameters.AddWithValue("@a", address);
- ins.Parameters.AddWithValue("@g", groupId);
- await ins.ExecuteNonQueryAsync();
- inserted++;
- }
- else skipped++;
- }
- }
- MessageBox.Show($"Импорт завершён.\nДобавлено: {inserted}\nПропущено (дубликаты): {skipped}");
- await LoadStudentsAsync(cmbGroupFilter.SelectedValue as int?);
- }
- }
- catch (Exception ex)
- {
- MessageBox.Show("Ошибка импорта: " + ex.Message);
- }
- finally
- {
- Cursor = Cursors.Default;
- }
- }
- }
- }
- // Дизайнер
- private void InitializeComponent()
- {
- System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
- System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
- System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
- this.dgvStudents = new Guna.UI2.WinForms.Guna2DataGridView();
- this.btnImportCsv = new Guna.UI2.WinForms.Guna2Button();
- this.cmbGroupFilter = new Guna.UI2.WinForms.Guna2ComboBox();
- this.btnRefresh = new Guna.UI2.WinForms.Guna2Button();
- this.lblFilter = new Guna.UI2.WinForms.Guna2HtmlLabel();
- this.txtSearch = new Guna.UI2.WinForms.Guna2TextBox();
- ((System.ComponentModel.ISupportInitialize)(this.dgvStudents)).BeginInit();
- this.SuspendLayout();
- //
- // dgvStudents
- //
- this.dgvStudents.AllowUserToAddRows = false;
- this.dgvStudents.AllowUserToDeleteRows = false;
- dataGridViewCellStyle1.BackColor = System.Drawing.Color.White;
- this.dgvStudents.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1;
- dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
- dataGridViewCellStyle2.BackColor = System.Drawing.Color.FromArgb(100, 88, 255);
- dataGridViewCellStyle2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
- dataGridViewCellStyle2.ForeColor = System.Drawing.Color.White;
- dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight;
- dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
- dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
- this.dgvStudents.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle2;
- this.dgvStudents.ColumnHeadersHeight = 40;
- dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
- dataGridViewCellStyle3.BackColor = System.Drawing.Color.White;
- dataGridViewCellStyle3.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
- dataGridViewCellStyle3.ForeColor = System.Drawing.Color.FromArgb(71, 69, 94);
- dataGridViewCellStyle3.SelectionBackColor = System.Drawing.Color.FromArgb(231, 229, 255);
- dataGridViewCellStyle3.SelectionForeColor = System.Drawing.Color.FromArgb(71, 69, 94);
- dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
- this.dgvStudents.DefaultCellStyle = dataGridViewCellStyle3;
- this.dgvStudents.GridColor = System.Drawing.Color.FromArgb(230, 230, 230);
- this.dgvStudents.Location = new System.Drawing.Point(20, 60);
- this.dgvStudents.Name = "dgvStudents";
- this.dgvStudents.ReadOnly = true;
- this.dgvStudents.RowHeadersVisible = false;
- this.dgvStudents.RowTemplate.Height = 30;
- this.dgvStudents.Size = new System.Drawing.Size(760, 420);
- this.dgvStudents.TabIndex = 0;
- //
- // btnImportCsv
- //
- this.btnImportCsv.BorderRadius = 10;
- this.btnImportCsv.FillColor = System.Drawing.Color.FromArgb(40, 167, 69);
- this.btnImportCsv.Font = new System.Drawing.Font("Segoe UI", 9F);
- this.btnImportCsv.ForeColor = System.Drawing.Color.White;
- this.btnImportCsv.Location = new System.Drawing.Point(620, 12);
- this.btnImportCsv.Name = "btnImportCsv";
- this.btnImportCsv.Size = new System.Drawing.Size(160, 36);
- this.btnImportCsv.TabIndex = 1;
- this.btnImportCsv.Text = "📂 Импорт студентов (CSV)";
- this.btnImportCsv.Click += new System.EventHandler(this.btnImportCsv_Click);
- //
- // cmbGroupFilter
- //
- this.cmbGroupFilter.BackColor = System.Drawing.Color.Transparent;
- this.cmbGroupFilter.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
- this.cmbGroupFilter.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- this.cmbGroupFilter.FocusedColor = System.Drawing.Color.Empty;
- this.cmbGroupFilter.Font = new System.Drawing.Font("Segoe UI", 9F);
- this.cmbGroupFilter.ForeColor = System.Drawing.Color.FromArgb(68, 88, 112);
- this.cmbGroupFilter.ItemHeight = 30;
- this.cmbGroupFilter.Location = new System.Drawing.Point(120, 12);
- this.cmbGroupFilter.Name = "cmbGroupFilter";
- this.cmbGroupFilter.Size = new System.Drawing.Size(180, 36);
- this.cmbGroupFilter.TabIndex = 2;
- this.cmbGroupFilter.SelectedIndexChanged += new System.EventHandler(this.cmbGroupFilter_SelectedIndexChanged);
- //
- // btnRefresh
- //
- this.btnRefresh.BorderRadius = 10;
- this.btnRefresh.FillColor = System.Drawing.Color.FromArgb(52, 73, 94);
- this.btnRefresh.Font = new System.Drawing.Font("Segoe UI", 9F);
- this.btnRefresh.ForeColor = System.Drawing.Color.White;
- this.btnRefresh.Location = new System.Drawing.Point(320, 12);
- this.btnRefresh.Name = "btnRefresh";
- this.btnRefresh.Size = new System.Drawing.Size(100, 36);
- this.btnRefresh.TabIndex = 3;
- this.btnRefresh.Text = "Обновить";
- this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
- //
- // lblFilter
- //
- this.lblFilter.BackColor = System.Drawing.Color.Transparent;
- this.lblFilter.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold);
- this.lblFilter.Location = new System.Drawing.Point(20, 22);
- this.lblFilter.Name = "lblFilter";
- this.lblFilter.Size = new System.Drawing.Size(109, 17);
- this.lblFilter.TabIndex = 4;
- this.lblFilter.Text = "Фильтр по группе:";
- //
- // txtSearch
- //
- this.txtSearch.Cursor = System.Windows.Forms.Cursors.IBeam;
- this.txtSearch.DefaultText = "";
- this.txtSearch.Font = new System.Drawing.Font("Segoe UI", 9F);
- this.txtSearch.Location = new System.Drawing.Point(440, 12);
- this.txtSearch.Name = "txtSearch";
- this.txtSearch.PlaceholderText = "🔍 Поиск по фамилии...";
- this.txtSearch.Size = new System.Drawing.Size(150, 36);
- this.txtSearch.TabIndex = 5;
- this.txtSearch.TextChanged += new System.EventHandler(this.txtSearch_TextChanged);
- //
- // StudentForm
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.BackColor = System.Drawing.Color.FromArgb(240, 242, 245);
- this.ClientSize = new System.Drawing.Size(800, 500);
- this.Controls.Add(this.txtSearch);
- this.Controls.Add(this.lblFilter);
- this.Controls.Add(this.btnRefresh);
- this.Controls.Add(this.cmbGroupFilter);
- this.Controls.Add(this.btnImportCsv);
- this.Controls.Add(this.dgvStudents);
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
- this.MaximizeBox = false;
- this.Name = "StudentForm";
- this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
- this.Text = "Управление студентами и средний балл";
- ((System.ComponentModel.ISupportInitialize)(this.dgvStudents)).EndInit();
- this.ResumeLayout(false);
- this.PerformLayout();
- }
- }
- }
|