359 lines
15 KiB
C#
359 lines
15 KiB
C#
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;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
}
|