2025-01-24 14:08:12 +07:00

359 lines
15 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OfficeOpenXml;
using OfficeOpenXml;
using System.Text.RegularExpressions;
using System.Diagnostics;
namespace NoDuplicate
{
public partial class Form1 : Form
{
private DataTable emailTable; // Таблица для хранения данных
public Form1()
{
InitializeComponent();
}
private void импортToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog
{
Filter = "Excel Files|*.xlsx",
Title = "Выберите файл с email-адресами"
};
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
string filePath = openFileDialog.FileName;
try
{
// Указываем лицензионный контекст для EPPlus
OfficeOpenXml.ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
using (var package = new ExcelPackage(new FileInfo(filePath)))
{
var worksheet = package.Workbook.Worksheets[0]; // Первый лист
int rows = worksheet.Dimension.Rows; // Количество строк
emailTable = new DataTable();
emailTable.Columns.Add("Email", typeof(string));
for (int row = 1; row <= rows; row++)
{
string email = worksheet.Cells[row, 1].Text;
if (!string.IsNullOrEmpty(email))
{
emailTable.Rows.Add(email);
}
}
dataGridView1.DataSource = emailTable;
//MessageBox.Show("Данные успешно загружены!", "Импорт");
}
}
catch (Exception ex)
{
MessageBox.Show($"Ошибка при импорте файла: {ex.Message}", "Ошибка");
}
}
}
private List<string> removedEmails = new List<string>(); // Список для хранения удалённых адресов
private string reportsDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MyAppReports"); // Путь к папке для отчётов
private void SaveReport(List<string> validEmails, List<string> invalidEmails, List<string> removedEmails)
{
try
{
if (!Directory.Exists(reportsDirectory))
{
Directory.CreateDirectory(reportsDirectory);
}
string reportFileName = $"EmailReport_{DateTime.Now:yyyyMMdd_HHmmss}.txt";
string reportPath = Path.Combine(reportsDirectory, reportFileName);
using (StreamWriter writer = new StreamWriter(reportPath))
{
writer.WriteLine($"Отчёт о проверке email-адресов ({DateTime.Now}):");
writer.WriteLine("\nКорректные email:");
writer.WriteLine($"Всего корректных адресов: {validEmails.Count}");
foreach (var email in validEmails)
{
writer.WriteLine(email);
}
writer.WriteLine("\nНевалидные email:");
writer.WriteLine($"Всего невалидных адресов: {invalidEmails.Count}");
foreach (var email in invalidEmails)
{
writer.WriteLine(email);
}
writer.WriteLine("\nУдалённые дубликаты:");
writer.WriteLine($"Всего удалено дубликатов: {removedEmails.Count}");
foreach (var email in removedEmails)
{
writer.WriteLine(email);
}
}
MessageBox.Show($"Отчёт сохранён в папке: {reportsDirectory}", "Успех");
}
catch (Exception ex)
{
MessageBox.Show($"Ошибка при сохранении отчёта: {ex.Message}", "Ошибка");
}
}
private void btnRemoveDuplicates_Click(object sender, EventArgs e)
{
if (emailTable == null || emailTable.Rows.Count == 0)
{
lblStatus.Text = "Таблица пуста или не загружена.";
lblStatus.ForeColor = Color.Red; // Красный цвет для ошибки
return;
}
try
{
var allEmails = emailTable.AsEnumerable()
.Select(row => row.Field<string>("Email").Trim())
.ToList();
// Проверяем валидность email
var validEmails = allEmails.Where(email => IsValidEmail(email)).ToList();
var invalidEmails = allEmails.Except(validEmails).ToList();
var distinctEmails = validEmails.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
removedEmails = allEmails
.GroupBy(email => email, StringComparer.OrdinalIgnoreCase)
.Where(group => group.Count() > 1)
.SelectMany(group => group.Skip(1))
.ToList();
emailTable.Rows.Clear();
foreach (var email in distinctEmails)
{
emailTable.Rows.Add(email);
}
dataGridView1.DataSource = emailTable;
// Передаем все три списка в метод SaveReport
SaveReport(validEmails, invalidEmails, removedEmails);
// Обновляем сообщение на форме
lblStatus.Text = $"Удаление завершено! Удалено {removedEmails.Count} адрес(ов).";
lblStatus.ForeColor = Color.Green; // Зелёный цвет для успеха
}
catch (Exception ex)
{
lblStatus.Text = $"Ошибка: {ex.Message}";
lblStatus.ForeColor = Color.Red; // Красный цвет для ошибки
}
}
private void экспортToolStripMenuItem_Click(object sender, EventArgs e)
{
if (emailTable == null || emailTable.Rows.Count == 0)
{
MessageBox.Show("Нет данных для экспорта.", "Ошибка");
return;
}
// Открываем диалог для выбора места сохранения файла
SaveFileDialog saveFileDialog = new SaveFileDialog
{
Filter = "Excel Files|*.xlsx",
Title = "Сохранить как",
FileName = "Emails.xlsx"
};
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
string filePath = saveFileDialog.FileName;
try
{
OfficeOpenXml.ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
using (var package = new OfficeOpenXml.ExcelPackage())
{
// Создаем новый лист
var worksheet = package.Workbook.Worksheets.Add("Emails");
// Записываем данные из DataTable в Excel
for (int i = 0; i < emailTable.Rows.Count; i++)
{
worksheet.Cells[i + 1, 1].Value = emailTable.Rows[i]["Email"]; // Первая строка без заголовка
}
// Сохраняем файл
package.SaveAs(new FileInfo(filePath));
}
//MessageBox.Show("Данные успешно экспортированы!", "Успех");
}
catch (Exception ex)
{
MessageBox.Show($"Ошибка при экспорте файла: {ex.Message}", "Ошибка");
}
}
}
private void помощьToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Инструкция по работе с программой\r\nПрограмма для работы с email-адресами позволяет удалять дубликаты из списка адресов и создавать отчёты об удалённых данных. Следуйте этим шагам:\r\n\r\n1. Импорт файла\r\nНажмите кнопку \"Импорт\" или выберите пункт меню \"Файл → Импорт\".\r\nВ появившемся окне выберите файл в формате .xlsx, содержащий список email-адресов.\r\nПрограмма загрузит данные и отобразит их в таблице.\r\n2. Удаление дубликатов\r\nПосле импорта нажмите кнопку \"Удалить дубликаты\".\r\nПрограмма автоматически:\r\nУдалит повторяющиеся email-адреса (с учётом регистра и пробелов).\r\nОбновит таблицу, оставив только уникальные адреса.\r\nСоздаст отчёт в папке MyAppReports в \"Моих документах\". Отчёт содержит список удалённых адресов.\r\n3. Экспорт файла\r\nЧтобы сохранить уникальные адреса, нажмите кнопку \"Экспорт\" или выберите пункт меню \"Файл → Экспорт\".\r\nВыберите место и имя для нового файла в формате .xlsx.\r\nПрограмма создаст файл с уникальными адресами.\r\n4. Папка отчётов\r\nВсе отчёты об удалённых адресах сохраняются в папке MyAppReports (расположена в \"Моих документах\").\r\nКаждый отчёт содержит:\r\nОбщее количество удалённых адресов.\r\nПолный список удалённых адресов.\r\nВы можете открыть эту папку вручную или добавить кнопку для её быстрого открытия.");
}
private bool IsValidEmail(string email)
{
if (string.IsNullOrWhiteSpace(email)) return false;
// Регулярное выражение для проверки email
var emailRegex = new Regex(@"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z]{2,}$");
if (!emailRegex.IsMatch(email.Trim())) return false;
// Проверяем валидность домена
string domain = email.Split('@').LastOrDefault();
if (!IsValidDomain(domain)) return false;
// Проверяем, что нет двойной точки в любом месте email
if (email.Contains("..")) return false;
return true;
}
private bool IsValidDomain(string domain)
{
// Список валидных доменных окончаний
string[] validTlds = {
"com", "org", "net", "edu", "gov", "io", "co", "uk", "ru", "de", "fr",
"jp", "cn", "us", "museum", "jobs", "info", "biz", "xyz", "ai", "name"
};
string[] parts = domain.Split('.');
if (parts.Length < 2) return false; // Минимум 2 части: имя домена и TLD
// Проверяем, что каждая часть домена не пуста, не начинается и не заканчивается тире
foreach (string part in parts)
{
if (string.IsNullOrEmpty(part) || part.StartsWith("-") || part.EndsWith("-"))
return false;
}
// Проверяем валидность TLD
string tld = parts.LastOrDefault();
if (!validTlds.Contains(tld)) return false;
return true;
}
private void btnValidateEmails_Click(object sender, EventArgs e)
{
if (emailTable == null || emailTable.Rows.Count == 0)
{
lblStatus.Text = "Таблица пуста или не загружена.";
lblStatus.ForeColor = Color.Red;
return;
}
var validEmails = new List<string>();
var invalidEmails = new List<string>();
foreach (DataRow row in emailTable.Rows)
{
string email = row.Field<string>("Email").Trim(); // Убираем пробелы
bool isValid = IsValidEmail(email);
if (isValid)
{
validEmails.Add(email);
}
else
{
invalidEmails.Add(email);
}
// Отладочный вывод
Debug.WriteLine($"Email: '{email}', Корректный: {isValid}");
}
// Проверяем, что корректные email записываются обратно
Debug.WriteLine("Корректные email:");
foreach (var email in validEmails)
{
Debug.WriteLine(email);
}
Debug.WriteLine("Невалидные email:");
foreach (var email in invalidEmails)
{
Debug.WriteLine(email);
}
// Обновляем основную таблицу (только валидные email)
emailTable.Rows.Clear();
foreach (var email in validEmails)
{
emailTable.Rows.Add(email);
}
dataGridView1.DataSource = emailTable;
// Обновляем таблицу невалидных email
var invalidEmailTable = new DataTable();
invalidEmailTable.Columns.Add("Invalid Emails", typeof(string));
foreach (var email in invalidEmails)
{
invalidEmailTable.Rows.Add(email);
}
dataGridView2.DataSource = invalidEmailTable;
// Обновляем статус
lblStatus.Text = $"Проверка завершена! Корректных адресов: {validEmails.Count}, невалидных: {invalidEmails.Count}.";
lblStatus.ForeColor = Color.Green;
}
}
}