359 lines
15 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
2025-01-23 23:41:57 +07:00
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
2025-01-23 23:41:57 +07:00
using OfficeOpenXml;
using OfficeOpenXml;
using System.Text.RegularExpressions;
using System.Diagnostics;
2025-01-23 23:41:57 +07:00
namespace NoDuplicate
{
public partial class Form1 : Form
{
2025-01-23 23:41:57 +07:00
private DataTable emailTable; // Таблица для хранения данных
public Form1()
{
InitializeComponent();
}
2025-01-23 23:41:57 +07:00
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)
2025-01-23 23:41:57 +07:00
{
try
{
if (!Directory.Exists(reportsDirectory))
{
Directory.CreateDirectory(reportsDirectory);
}
string reportFileName = $"EmailReport_{DateTime.Now:yyyyMMdd_HHmmss}.txt";
2025-01-23 23:41:57 +07:00
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}");
2025-01-23 23:41:57 +07:00
foreach (var email in removedEmails)
{
writer.WriteLine(email);
}
}
MessageBox.Show($"Отчёт сохранён в папке: {reportsDirectory}", "Успех");
2025-01-23 23:41:57 +07:00
}
catch (Exception ex)
{
MessageBox.Show($"Ошибка при сохранении отчёта: {ex.Message}", "Ошибка");
}
}
2025-01-23 23:41:57 +07:00
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();
2025-01-23 23:41:57 +07:00
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);
2025-01-23 23:41:57 +07:00
// Обновляем сообщение на форме
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;
}
}
}