1013 lines
42 KiB
C#
1013 lines
42 KiB
C#
using System;
|
||
using System.Data;
|
||
using System.Windows.Forms;
|
||
using System.Data.SQLite;
|
||
using System.IO;
|
||
using OfficeOpenXml;
|
||
using System.Collections.Generic;
|
||
using System.Threading;
|
||
using System.Management;
|
||
using System.Linq;
|
||
|
||
namespace ПХД
|
||
{
|
||
public partial class Form1 : Form
|
||
{
|
||
private DatabaseManager dbManager;
|
||
private bool isUnlocked = false;
|
||
private string requiredKeyContent = "ключь доступа";
|
||
private Thread usbMonitorThread;
|
||
private bool monitoringActive = true;
|
||
|
||
public Form1()
|
||
{
|
||
InitializeComponent();
|
||
dbManager = new DatabaseManager();
|
||
SetupDataGridView();
|
||
|
||
// Запускаем мониторинг сразу
|
||
StartUsbMonitoring();
|
||
|
||
// Проверяем ключ
|
||
CheckForUsbKey();
|
||
}
|
||
|
||
private void Form1_Load(object sender, EventArgs e)
|
||
{
|
||
// Проверяем ключ при загрузке формы
|
||
if (!isUnlocked)
|
||
{
|
||
LockApplication("Вставьте USB-ключ для доступа к программе");
|
||
}
|
||
else
|
||
{
|
||
dbManager.InitializeDatabase();
|
||
LoadEngines();
|
||
txtReason.Enabled = false;
|
||
datePickerOutOfOrder.Enabled = false;
|
||
}
|
||
}
|
||
|
||
private void LockApplication(string message)
|
||
{
|
||
// Создаем или используем существующую панель блокировки
|
||
Panel lockPanel = Controls.Find("lockPanel", false).Length > 0 ?
|
||
(Panel)Controls.Find("lockPanel", false)[0] : new Panel();
|
||
|
||
if (lockPanel.Name != "lockPanel")
|
||
{
|
||
lockPanel.Name = "lockPanel";
|
||
lockPanel.Dock = DockStyle.Fill;
|
||
lockPanel.BackColor = System.Drawing.Color.FromArgb(240, 240, 240);
|
||
|
||
Label lockMessage = new Label();
|
||
lockMessage.Name = "lockMessage";
|
||
lockMessage.Text = message;
|
||
lockMessage.AutoSize = false;
|
||
lockMessage.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||
lockMessage.Dock = DockStyle.None;
|
||
lockMessage.Size = new System.Drawing.Size(600, 80); // Увеличены размеры для размещения длинного текста
|
||
lockMessage.Font = new System.Drawing.Font("Arial", 16, System.Drawing.FontStyle.Bold);
|
||
// Размещаем по центру
|
||
lockMessage.Location = new System.Drawing.Point(
|
||
(this.ClientSize.Width - lockMessage.Width) / 2,
|
||
(this.ClientSize.Height - lockMessage.Height) / 2 - 50);
|
||
|
||
Button retryButton = new Button();
|
||
retryButton.Name = "retryButton";
|
||
retryButton.Text = "Проверить наличие ключа вручную";
|
||
retryButton.Size = new System.Drawing.Size(250, 40);
|
||
retryButton.Location = new System.Drawing.Point(
|
||
(this.ClientSize.Width - retryButton.Width) / 2,
|
||
lockMessage.Bottom + 20);
|
||
retryButton.Font = new System.Drawing.Font("Arial", 11, System.Drawing.FontStyle.Regular);
|
||
retryButton.Click += (s, e) => {
|
||
CheckForUsbKey();
|
||
// Если ключ найден, разблокируем приложение
|
||
if (isUnlocked)
|
||
{
|
||
UnlockApplication();
|
||
// Инициализируем приложение
|
||
dbManager.InitializeDatabase();
|
||
LoadEngines();
|
||
txtReason.Enabled = false;
|
||
datePickerOutOfOrder.Enabled = false;
|
||
}
|
||
else
|
||
{
|
||
// Обновляем сообщение, если ключ не найден
|
||
Label msg = lockPanel.Controls["lockMessage"] as Label;
|
||
if (msg != null)
|
||
{
|
||
msg.Text = "Ключ не найден. Программа будет разблокирована автоматически при обнаружении ключа.";
|
||
}
|
||
}
|
||
};
|
||
|
||
Label autoCheckLabel = new Label();
|
||
autoCheckLabel.Name = "autoCheckLabel";
|
||
autoCheckLabel.Text = "Программа автоматически проверяет наличие ключа...";
|
||
autoCheckLabel.AutoSize = false;
|
||
autoCheckLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||
autoCheckLabel.Size = new System.Drawing.Size(500, 30); // Увеличен размер
|
||
autoCheckLabel.Font = new System.Drawing.Font("Arial", 9, System.Drawing.FontStyle.Italic);
|
||
autoCheckLabel.Location = new System.Drawing.Point(
|
||
(this.ClientSize.Width - autoCheckLabel.Width) / 2,
|
||
retryButton.Bottom + 10);
|
||
|
||
lockPanel.Controls.Add(lockMessage);
|
||
lockPanel.Controls.Add(retryButton);
|
||
lockPanel.Controls.Add(autoCheckLabel);
|
||
|
||
// Добавляем панель блокировки на форму
|
||
this.Controls.Add(lockPanel);
|
||
lockPanel.BringToFront();
|
||
}
|
||
else
|
||
{
|
||
// Если панель уже существует, обновляем сообщение и убеждаемся, что размер достаточен
|
||
Label msg = lockPanel.Controls.OfType<Label>().FirstOrDefault(l => l.Name == "lockMessage");
|
||
if (msg != null)
|
||
{
|
||
// Увеличиваем размер существующей метки при необходимости
|
||
if (message.Length > 50 && msg.Width < 600)
|
||
{
|
||
msg.Size = new System.Drawing.Size(600, 80);
|
||
msg.Location = new System.Drawing.Point(
|
||
(this.ClientSize.Width - msg.Width) / 2,
|
||
(this.ClientSize.Height - msg.Height) / 2 - 50);
|
||
}
|
||
msg.Text = message;
|
||
}
|
||
}
|
||
|
||
// Показываем панель блокировки и скрываем основные элементы управления
|
||
lockPanel.Visible = true;
|
||
foreach (Control c in this.Controls)
|
||
{
|
||
if (c != lockPanel)
|
||
c.Visible = false;
|
||
}
|
||
}
|
||
|
||
private void StartUsbMonitoring()
|
||
{
|
||
// Останавливаем предыдущий поток мониторинга, если он существует
|
||
if (usbMonitorThread != null && usbMonitorThread.IsAlive)
|
||
{
|
||
monitoringActive = false;
|
||
usbMonitorThread.Join(1000);
|
||
}
|
||
|
||
monitoringActive = true;
|
||
usbMonitorThread = new Thread(() =>
|
||
{
|
||
try
|
||
{
|
||
// Используем таймер для периодической проверки
|
||
while (monitoringActive)
|
||
{
|
||
// Проверяем наличие ключа
|
||
bool wasUnlocked = isUnlocked;
|
||
|
||
// Не блокируем UI-поток для проверки
|
||
DriveInfo[] drives = DriveInfo.GetDrives();
|
||
bool keyFound = false;
|
||
|
||
foreach (DriveInfo drive in drives)
|
||
{
|
||
if (drive.DriveType == DriveType.Removable && drive.IsReady)
|
||
{
|
||
try
|
||
{
|
||
string keyPath = Path.Combine(drive.RootDirectory.FullName, "key.txt");
|
||
if (File.Exists(keyPath))
|
||
{
|
||
string content = File.ReadAllText(keyPath).Trim();
|
||
if (content == requiredKeyContent)
|
||
{
|
||
keyFound = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
|
||
isUnlocked = keyFound;
|
||
|
||
// Если статус разблокировки изменился, обновляем UI
|
||
if (wasUnlocked != isUnlocked)
|
||
{
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
if (isUnlocked)
|
||
{
|
||
// Если приложение было заблокировано, разблокируем его и загружаем данные
|
||
UnlockApplication();
|
||
if (!dbManager.IsDatabaseInitialized)
|
||
{
|
||
dbManager.InitializeDatabase();
|
||
LoadEngines();
|
||
txtReason.Enabled = false;
|
||
datePickerOutOfOrder.Enabled = false;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
LockApplication("USB-ключ был извлечен. Программа будет разблокирована автоматически при обнаружении ключа.");
|
||
}
|
||
}));
|
||
}
|
||
|
||
Thread.Sleep(1000); // Проверяем каждую секунду для быстрого отклика
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
this.Invoke(new Action(() =>
|
||
{
|
||
MessageBox.Show($"Ошибка в мониторинге USB: {ex.Message}", "Ошибка",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}));
|
||
}
|
||
});
|
||
|
||
usbMonitorThread.IsBackground = true;
|
||
usbMonitorThread.Start();
|
||
}
|
||
|
||
private void UnlockApplication()
|
||
{
|
||
// Скрываем панель блокировки и показываем основные элементы управления
|
||
Panel lockPanel = Controls.Find("lockPanel", false).Length > 0 ?
|
||
(Panel)Controls.Find("lockPanel", false)[0] : null;
|
||
|
||
if (lockPanel != null)
|
||
{
|
||
lockPanel.Visible = false;
|
||
}
|
||
|
||
foreach (Control c in this.Controls)
|
||
{
|
||
if (c != lockPanel)
|
||
c.Visible = true;
|
||
}
|
||
}
|
||
|
||
private void CheckForUsbKey()
|
||
{
|
||
DriveInfo[] drives = DriveInfo.GetDrives();
|
||
bool keyFound = false;
|
||
|
||
foreach (DriveInfo drive in drives)
|
||
{
|
||
if (drive.DriveType == DriveType.Removable && drive.IsReady)
|
||
{
|
||
try
|
||
{
|
||
string keyPath = Path.Combine(drive.RootDirectory.FullName, "key.txt");
|
||
if (File.Exists(keyPath))
|
||
{
|
||
string content = File.ReadAllText(keyPath).Trim();
|
||
if (content == requiredKeyContent)
|
||
{
|
||
keyFound = true;
|
||
MessageBox.Show($"Ключ доступа найден на устройстве {drive.Name}", "Доступ разрешен",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"Ошибка при проверке диска {drive.Name}: {ex.Message}");
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
|
||
isUnlocked = keyFound;
|
||
if (isUnlocked)
|
||
{
|
||
UnlockApplication();
|
||
}
|
||
else
|
||
{
|
||
LockApplication("Вставьте USB-ключ для доступа к программе");
|
||
}
|
||
}
|
||
|
||
|
||
private void LoadEngines()
|
||
{
|
||
try
|
||
{
|
||
dataGridView1.DataSource = dbManager.GetAllEngines();
|
||
CheckVerificationDates();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"Ошибка загрузки данных: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private void btnSave_Click(object sender, EventArgs e)
|
||
{
|
||
try
|
||
{
|
||
string registrationDate = datePickerRegistration.Value.ToString("yyyy-MM-dd");
|
||
string engineType = cmbEngineType.Text;
|
||
double power = double.Parse(txtPower.Text);
|
||
int rpm = int.Parse(cmbRPM.Text);
|
||
string mountingType = cmbMountingType.Text;
|
||
string uniqueNumber = txtUniqueNumber.Text;
|
||
string factoryNumber = txtFactoryNumber.Text;
|
||
string partNumber = txtPartNumber.Text;
|
||
string installationSite = txtInstallationSite.Text;
|
||
bool isOutOfOrder = chkOutOfOrder.Checked;
|
||
string reason = isOutOfOrder ? txtReason.Text : null;
|
||
string outOfOrderDate = isOutOfOrder ? datePickerOutOfOrder.Value.ToString("yyyy-MM-dd") : null;
|
||
string verificationDate = datePickerVerification.Value.ToString("yyyy-MM-dd");
|
||
|
||
dbManager.AddEngine(
|
||
registrationDate, engineType, power, rpm, mountingType,
|
||
uniqueNumber, factoryNumber, partNumber, installationSite,
|
||
isOutOfOrder, reason, outOfOrderDate, verificationDate
|
||
);
|
||
|
||
LoadEngines();
|
||
MessageBox.Show("Запись успешно сохранена!");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"Произошла ошибка: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private void SetupDataGridView()
|
||
{
|
||
dataGridView1.AutoGenerateColumns = false;
|
||
dataGridView1.Columns.Clear();
|
||
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
Name = "Id",
|
||
HeaderText = "ID",
|
||
DataPropertyName = "Id",
|
||
Width = 50
|
||
});
|
||
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
HeaderText = "Дата постановки",
|
||
DataPropertyName = "RegistrationDate",
|
||
Width = 120
|
||
});
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
HeaderText = "Тип двигателя",
|
||
DataPropertyName = "EngineType",
|
||
Width = 100
|
||
});
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
HeaderText = "Мощность (кВт)",
|
||
DataPropertyName = "Power",
|
||
Width = 100
|
||
});
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
HeaderText = "Обороты",
|
||
DataPropertyName = "RPM",
|
||
Width = 100
|
||
});
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
HeaderText = "Монтажное исполнение",
|
||
DataPropertyName = "MountingType",
|
||
Width = 150
|
||
});
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
HeaderText = "Уникальный номер",
|
||
DataPropertyName = "UniqueNumber",
|
||
Width = 150
|
||
});
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
HeaderText = "Заводской номер",
|
||
DataPropertyName = "FactoryNumber",
|
||
Width = 150
|
||
});
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
HeaderText = "Номер номенклатуры",
|
||
DataPropertyName = "PartNumber",
|
||
Width = 150
|
||
});
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
HeaderText = "Место установки",
|
||
DataPropertyName = "InstallationSite",
|
||
Width = 150
|
||
});
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
Name = "IsOutOfOrder", // Имя столбца в DataGridView
|
||
HeaderText = "Вышел из строя",
|
||
DataPropertyName = "IsOutOfOrder", // Имя столбца в DataTable/базе данных
|
||
Width = 120
|
||
});
|
||
|
||
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
HeaderText = "Причина",
|
||
DataPropertyName = "Reason",
|
||
Width = 150
|
||
});
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
HeaderText = "Дата выхода из строя",
|
||
DataPropertyName = "OutOfOrderDate",
|
||
Width = 150
|
||
});
|
||
|
||
dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
|
||
{
|
||
Name = "VerificationDate",
|
||
HeaderText = "Дата поверки",
|
||
DataPropertyName = "VerificationDate",
|
||
Width = 120
|
||
});
|
||
}
|
||
|
||
private void btnDelete_Click(object sender, EventArgs e)
|
||
{
|
||
try
|
||
{
|
||
if (dataGridView1.SelectedRows.Count > 0)
|
||
{
|
||
// Получаем ID выбранной строки
|
||
var idCell = dataGridView1.SelectedRows[0].Cells["Id"];
|
||
if (idCell != null && idCell.Value != null)
|
||
{
|
||
int id = Convert.ToInt32(idCell.Value);
|
||
|
||
// Подтверждение удаления
|
||
var result = MessageBox.Show("Вы уверены, что хотите удалить эту запись?",
|
||
"Подтверждение удаления",
|
||
MessageBoxButtons.YesNo,
|
||
MessageBoxIcon.Question);
|
||
if (result == DialogResult.Yes)
|
||
{
|
||
dbManager.DeleteEngine(id);
|
||
LoadEngines(); // Обновляем таблицу
|
||
MessageBox.Show("Запись успешно удалена!");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("Не удалось определить ID записи.");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("Пожалуйста, выберите запись для удаления.");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"Произошла ошибка при удалении записи: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private void chkOutOfOrder_CheckedChanged(object sender, EventArgs e)
|
||
{
|
||
// Поля блокируются, если чекбокс не установлен
|
||
bool isEnabled = chkOutOfOrder.Checked;
|
||
txtReason.Enabled = isEnabled;
|
||
datePickerOutOfOrder.Enabled = isEnabled;
|
||
}
|
||
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
||
{
|
||
// Проверяем, что это столбец "Id"
|
||
if (dataGridView1.Columns[e.ColumnIndex].Name == "Id")
|
||
{
|
||
var row = dataGridView1.Rows[e.RowIndex];
|
||
|
||
// Проверяем существование столбца "IsOutOfOrder" и его значения
|
||
if (row.Cells["IsOutOfOrder"] != null && row.Cells["IsOutOfOrder"].Value != null)
|
||
{
|
||
string value = row.Cells["IsOutOfOrder"].Value.ToString();
|
||
|
||
// Пытаемся преобразовать значение в bool
|
||
if (bool.TryParse(value, out bool isOutOfOrder))
|
||
{
|
||
// Подсвечиваем цвет, если двигатель вышел из строя
|
||
if (isOutOfOrder)
|
||
{
|
||
e.CellStyle.BackColor = System.Drawing.Color.LightCoral;
|
||
}
|
||
else
|
||
{
|
||
e.CellStyle.BackColor = System.Drawing.Color.White;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Если преобразование не удалось, используем белый фон
|
||
e.CellStyle.BackColor = System.Drawing.Color.White;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Если значение отсутствует, используем белый фон
|
||
e.CellStyle.BackColor = System.Drawing.Color.White;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void btnClear_Click(object sender, EventArgs e)
|
||
{
|
||
// Очистка текстовых полей
|
||
txtPower.Text = string.Empty;
|
||
txtUniqueNumber.Text = string.Empty;
|
||
txtFactoryNumber.Text = string.Empty;
|
||
txtPartNumber.Text = string.Empty;
|
||
txtInstallationSite.Text = string.Empty;
|
||
txtReason.Text = string.Empty;
|
||
|
||
// Сброс выпадающих списков
|
||
cmbEngineType.SelectedIndex = -1; // Сбрасывает выбор
|
||
cmbRPM.SelectedIndex = -1;
|
||
cmbMountingType.SelectedIndex = -1;
|
||
|
||
// Сброс чекбоксов
|
||
chkOutOfOrder.Checked = false;
|
||
|
||
// Сброс дат
|
||
datePickerRegistration.Value = DateTime.Now;
|
||
datePickerOutOfOrder.Value = DateTime.Now;
|
||
|
||
// Блокировка полей "Неисправность"
|
||
txtReason.Enabled = false;
|
||
datePickerOutOfOrder.Enabled = false;
|
||
LoadEngines();
|
||
|
||
}
|
||
|
||
private void btnSearch_Click(object sender, EventArgs e)
|
||
{
|
||
try
|
||
{
|
||
// Формируем SQL-запрос с фильтрацией
|
||
string query = "SELECT * FROM Engines WHERE 1=1"; // Условие 1=1 позволяет добавлять фильтры динамически
|
||
|
||
if (!string.IsNullOrWhiteSpace(txtPower.Text))
|
||
{
|
||
query += $" AND Power = {txtPower.Text}";
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(cmbEngineType.Text))
|
||
{
|
||
query += $" AND EngineType LIKE '%{cmbEngineType.Text}%'";
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(txtUniqueNumber.Text))
|
||
{
|
||
query += $" AND UniqueNumber LIKE '%{txtUniqueNumber.Text}%'";
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(txtFactoryNumber.Text))
|
||
{
|
||
query += $" AND FactoryNumber LIKE '%{txtFactoryNumber.Text}%'";
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(txtPartNumber.Text))
|
||
{
|
||
query += $" AND PartNumber LIKE '%{txtPartNumber.Text}%'";
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(txtInstallationSite.Text))
|
||
{
|
||
query += $" AND InstallationSite LIKE '%{txtInstallationSite.Text}%'";
|
||
}
|
||
|
||
if (chkOutOfOrder.Checked)
|
||
{
|
||
query += " AND IsOutOfOrder = 1";
|
||
}
|
||
|
||
// Выполняем запрос
|
||
DataTable searchResults = dbManager.ExecuteQuery(query);
|
||
dataGridView1.DataSource = searchResults; // Отображаем результаты поиска
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"Произошла ошибка при поиске: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private void экспортToolStripMenuItem_Click(object sender, EventArgs e)
|
||
{
|
||
try
|
||
{
|
||
using (var saveFileDialog = new SaveFileDialog())
|
||
{
|
||
saveFileDialog.Filter = "Excel Files|*.xlsx";
|
||
saveFileDialog.Title = "Сохранить таблицу как Excel файл";
|
||
saveFileDialog.FileName = "Engines.xlsx";
|
||
|
||
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
// Получаем данные из DataGridView
|
||
DataTable table = (DataTable)dataGridView1.DataSource;
|
||
|
||
// Экспортируем в Excel
|
||
ExportToExcel(table, saveFileDialog.FileName);
|
||
|
||
MessageBox.Show("Данные успешно экспортированы!", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"Произошла ошибка при экспорте: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
}
|
||
|
||
private void ExportToExcel(DataTable table, string filePath)
|
||
{
|
||
// Указываем контекст лицензии
|
||
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
|
||
|
||
using (var package = new OfficeOpenXml.ExcelPackage())
|
||
{
|
||
// Создаем новый лист
|
||
var worksheet = package.Workbook.Worksheets.Add("Engines");
|
||
|
||
// Заголовки столбцов из DataGridView
|
||
for (int col = 0; col < dataGridView1.Columns.Count; col++)
|
||
{
|
||
worksheet.Cells[1, col + 1].Value = dataGridView1.Columns[col].HeaderText; // Используем HeaderText
|
||
}
|
||
|
||
// Данные из DataTable
|
||
for (int row = 0; row < table.Rows.Count; row++)
|
||
{
|
||
for (int col = 0; col < table.Columns.Count; col++)
|
||
{
|
||
worksheet.Cells[row + 2, col + 1].Value = table.Rows[row][col];
|
||
}
|
||
}
|
||
|
||
// Авторазмер столбцов
|
||
worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();
|
||
|
||
// Сохраняем файл
|
||
package.SaveAs(new FileInfo(filePath));
|
||
}
|
||
}
|
||
|
||
private void импортToolStripMenuItem_Click(object sender, EventArgs e)
|
||
{
|
||
try
|
||
{
|
||
using (var openFileDialog = new OpenFileDialog())
|
||
{
|
||
openFileDialog.Filter = "Excel Files|*.xlsx";
|
||
openFileDialog.Title = "Выберите Excel файл для импорта";
|
||
|
||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||
{
|
||
// Импортируем данные из Excel
|
||
DataTable importedTable = ImportFromExcel(openFileDialog.FileName);
|
||
|
||
// Проверяем, содержит ли таблица строки
|
||
if (importedTable.Rows.Count == 0)
|
||
{
|
||
MessageBox.Show("Файл Excel не содержит данных для импорта.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||
return;
|
||
}
|
||
|
||
// Сохраняем импортированные данные в базу данных
|
||
foreach (DataRow row in importedTable.Rows)
|
||
{
|
||
// Обработка столбца IsOutOfOrder
|
||
bool isOutOfOrder = false;
|
||
if (row["IsOutOfOrder"] != null && !string.IsNullOrWhiteSpace(row["IsOutOfOrder"].ToString()))
|
||
{
|
||
// Попытка преобразования строки в bool
|
||
if (!bool.TryParse(row["IsOutOfOrder"].ToString(), out isOutOfOrder))
|
||
{
|
||
// Проверяем числовые значения ("1" => true, "0" => false)
|
||
isOutOfOrder = row["IsOutOfOrder"].ToString() == "1";
|
||
}
|
||
}
|
||
|
||
// Добавляем запись в базу данных
|
||
dbManager.AddEngine(
|
||
row["RegistrationDate"].ToString(),
|
||
row["EngineType"].ToString(),
|
||
double.Parse(row["Power"].ToString()),
|
||
int.Parse(row["RPM"].ToString()),
|
||
row["MountingType"].ToString(),
|
||
row["UniqueNumber"].ToString(),
|
||
row["FactoryNumber"].ToString(),
|
||
row["PartNumber"].ToString(),
|
||
row["InstallationSite"].ToString(),
|
||
isOutOfOrder,
|
||
row["Reason"].ToString(),
|
||
row["OutOfOrderDate"].ToString(),
|
||
row["VerificationDate"].ToString()
|
||
);
|
||
}
|
||
|
||
// Обновляем DataGridView
|
||
LoadEngines();
|
||
|
||
MessageBox.Show("Данные успешно импортированы и сохранены в базу данных!", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"Произошла ошибка при импорте: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
private DataTable ImportFromExcel(string filePath)
|
||
{
|
||
DataTable table = new DataTable();
|
||
|
||
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
|
||
|
||
using (var package = new OfficeOpenXml.ExcelPackage(new FileInfo(filePath)))
|
||
{
|
||
// Получаем первый лист из файла
|
||
var worksheet = package.Workbook.Worksheets[0];
|
||
if (worksheet == null)
|
||
{
|
||
throw new Exception("В файле отсутствуют листы.");
|
||
}
|
||
|
||
// Создаем DataTable на основе столбцов DataGridView
|
||
foreach (DataGridViewColumn column in dataGridView1.Columns)
|
||
{
|
||
table.Columns.Add(column.DataPropertyName);
|
||
}
|
||
|
||
// Проверяем наличие заголовков в Excel
|
||
Dictionary<string, int> excelColumnIndices = new Dictionary<string, int>();
|
||
for (int col = 1; col <= worksheet.Dimension.End.Column; col++)
|
||
{
|
||
string columnHeader = worksheet.Cells[1, col].Text.Trim();
|
||
foreach (DataGridViewColumn dgvColumn in dataGridView1.Columns)
|
||
{
|
||
if (dgvColumn.HeaderText == columnHeader)
|
||
{
|
||
excelColumnIndices[dgvColumn.DataPropertyName] = col;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Читаем данные начиная со второй строки
|
||
for (int row = 2; row <= worksheet.Dimension.End.Row; row++)
|
||
{
|
||
DataRow newRow = table.NewRow();
|
||
foreach (var mapping in excelColumnIndices)
|
||
{
|
||
newRow[mapping.Key] = worksheet.Cells[row, mapping.Value].Text.Trim();
|
||
}
|
||
table.Rows.Add(newRow);
|
||
}
|
||
}
|
||
|
||
return table;
|
||
}
|
||
|
||
|
||
private void CheckVerificationDates()
|
||
{
|
||
txtNotification.Clear();
|
||
txtNotification.ForeColor = System.Drawing.Color.Black;
|
||
var engines = dbManager.GetAllEngines();
|
||
|
||
foreach (DataRow row in engines.Rows)
|
||
{
|
||
if (DateTime.TryParse(row["VerificationDate"].ToString(), out DateTime verificationDate))
|
||
{
|
||
if (verificationDate <= DateTime.Now.AddMonths(1) && verificationDate > DateTime.Now)
|
||
{
|
||
txtNotification.ForeColor = System.Drawing.Color.Red;
|
||
txtNotification.AppendText(
|
||
$"Двигатель с заводским номером {row["FactoryNumber"]} нуждается в поверке {verificationDate:dd-MM-yyyy}.\r\n");
|
||
}
|
||
}
|
||
}
|
||
if (string.IsNullOrEmpty(txtNotification.Text))
|
||
{
|
||
txtNotification.ForeColor = System.Drawing.Color.Black; // Нет уведомлений — чёрный текст
|
||
txtNotification.Text = "Уведомлений нет.";
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
private class DatabaseManager
|
||
{
|
||
private string connectionString = "Data Source=Engines.db;Version=3;";
|
||
private bool isDatabaseInitialized = false;
|
||
public bool IsDatabaseInitialized => isDatabaseInitialized;
|
||
public void InitializeDatabase()
|
||
{
|
||
using (var connection = new SQLiteConnection(connectionString))
|
||
{
|
||
connection.Open();
|
||
string createTableQuery = @"
|
||
CREATE TABLE IF NOT EXISTS Engines (
|
||
Id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
RegistrationDate TEXT NOT NULL,
|
||
EngineType TEXT NOT NULL,
|
||
Power REAL NOT NULL,
|
||
RPM INTEGER NOT NULL,
|
||
MountingType TEXT NOT NULL,
|
||
UniqueNumber TEXT NOT NULL,
|
||
FactoryNumber TEXT NOT NULL,
|
||
PartNumber TEXT NOT NULL,
|
||
InstallationSite TEXT NOT NULL,
|
||
IsOutOfOrder INTEGER NOT NULL,
|
||
Reason TEXT,
|
||
OutOfOrderDate TEXT
|
||
)";
|
||
SQLiteCommand command = new SQLiteCommand(createTableQuery, connection);
|
||
command.ExecuteNonQuery();
|
||
|
||
// Проверяем наличие столбца VerificationDate
|
||
string checkColumnQuery = "PRAGMA table_info(Engines)";
|
||
command = new SQLiteCommand(checkColumnQuery, connection);
|
||
SQLiteDataReader reader = command.ExecuteReader();
|
||
bool columnExists = false;
|
||
while (reader.Read())
|
||
{
|
||
if (reader["name"].ToString() == "VerificationDate")
|
||
{
|
||
columnExists = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Добавляем столбец VerificationDate, если он отсутствует
|
||
if (!columnExists)
|
||
{
|
||
string addColumnQuery = @"
|
||
ALTER TABLE Engines ADD COLUMN VerificationDate TEXT";
|
||
command = new SQLiteCommand(addColumnQuery, connection);
|
||
command.ExecuteNonQuery();
|
||
}
|
||
}
|
||
isDatabaseInitialized = true;
|
||
}
|
||
|
||
|
||
|
||
public void AddEngine(
|
||
string registrationDate, string engineType, double power, int rpm,
|
||
string mountingType, string uniqueNumber, string factoryNumber,
|
||
string partNumber, string installationSite, bool isOutOfOrder,
|
||
string reason, string outOfOrderDate, string verificationDate)
|
||
{
|
||
using (var connection = new SQLiteConnection(connectionString))
|
||
{
|
||
connection.Open();
|
||
string insertQuery = @"
|
||
INSERT INTO Engines
|
||
(RegistrationDate, EngineType, Power, RPM, MountingType,
|
||
UniqueNumber, FactoryNumber, PartNumber, InstallationSite,
|
||
IsOutOfOrder, Reason, OutOfOrderDate, VerificationDate)
|
||
VALUES
|
||
(@RegistrationDate, @EngineType, @Power, @RPM, @MountingType,
|
||
@UniqueNumber, @FactoryNumber, @PartNumber, @InstallationSite,
|
||
@IsOutOfOrder, @Reason, @OutOfOrderDate, @VerificationDate)";
|
||
|
||
SQLiteCommand command = new SQLiteCommand(insertQuery, connection);
|
||
command.Parameters.AddWithValue("@RegistrationDate", registrationDate);
|
||
command.Parameters.AddWithValue("@EngineType", engineType);
|
||
command.Parameters.AddWithValue("@Power", power);
|
||
command.Parameters.AddWithValue("@RPM", rpm);
|
||
command.Parameters.AddWithValue("@MountingType", mountingType);
|
||
command.Parameters.AddWithValue("@UniqueNumber", uniqueNumber);
|
||
command.Parameters.AddWithValue("@FactoryNumber", factoryNumber);
|
||
command.Parameters.AddWithValue("@PartNumber", partNumber);
|
||
command.Parameters.AddWithValue("@InstallationSite", installationSite);
|
||
command.Parameters.AddWithValue("@IsOutOfOrder", isOutOfOrder ? 1 : 0);
|
||
command.Parameters.AddWithValue("@Reason", reason ?? (object)DBNull.Value);
|
||
command.Parameters.AddWithValue("@OutOfOrderDate", outOfOrderDate ?? (object)DBNull.Value);
|
||
command.Parameters.AddWithValue("@VerificationDate", verificationDate ?? (object)DBNull.Value);
|
||
|
||
command.ExecuteNonQuery();
|
||
}
|
||
}
|
||
|
||
public DataTable GetAllEngines()
|
||
{
|
||
using (var connection = new SQLiteConnection(connectionString))
|
||
{
|
||
connection.Open();
|
||
|
||
string selectQuery = @"
|
||
SELECT
|
||
Id, RegistrationDate, EngineType, Power, RPM, MountingType,
|
||
UniqueNumber, FactoryNumber, PartNumber, InstallationSite,
|
||
IsOutOfOrder, Reason, OutOfOrderDate, VerificationDate
|
||
FROM Engines";
|
||
|
||
|
||
|
||
SQLiteDataAdapter adapter = new SQLiteDataAdapter(selectQuery, connection);
|
||
DataTable table = new DataTable();
|
||
adapter.Fill(table);
|
||
return table;
|
||
}
|
||
}
|
||
|
||
public void DeleteEngine(int id)
|
||
{
|
||
using (var connection = new SQLiteConnection(connectionString))
|
||
{
|
||
connection.Open();
|
||
string deleteQuery = "DELETE FROM Engines WHERE Id = @Id";
|
||
SQLiteCommand command = new SQLiteCommand(deleteQuery, connection);
|
||
command.Parameters.AddWithValue("@Id", id);
|
||
command.ExecuteNonQuery();
|
||
}
|
||
}
|
||
|
||
public DataTable ExecuteQuery(string query)
|
||
{
|
||
using (var connection = new SQLiteConnection(connectionString))
|
||
{
|
||
connection.Open();
|
||
SQLiteDataAdapter adapter = new SQLiteDataAdapter(query, connection);
|
||
DataTable table = new DataTable();
|
||
adapter.Fill(table);
|
||
return table;
|
||
}
|
||
}
|
||
|
||
public void UpdateDatabaseSchema()
|
||
{
|
||
using (var connection = new SQLiteConnection(connectionString))
|
||
{
|
||
connection.Open();
|
||
string addColumnQuery = @"
|
||
ALTER TABLE Engines ADD COLUMN VerificationDate TEXT";
|
||
|
||
try
|
||
{
|
||
SQLiteCommand command = new SQLiteCommand(addColumnQuery, connection);
|
||
command.ExecuteNonQuery();
|
||
}
|
||
catch (SQLiteException ex)
|
||
{
|
||
if (!ex.Message.Contains("duplicate column name")) // Игнорируем, если столбец уже существует
|
||
{
|
||
throw;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
}
|
||
}
|
||
}
|