2025-01-23 22:41:52 +07:00
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 ;
2025-01-23 22:41:52 +07:00
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 ;
2025-01-24 13:53:57 +07:00
using System.Text.RegularExpressions ;
using System.Diagnostics ;
2025-01-23 23:41:57 +07:00
2025-01-23 22:41:52 +07:00
namespace NoDuplicate
{
public partial class Form1 : Form
{
2025-01-23 23:41:57 +07:00
private DataTable emailTable ; // Таблица для хранения данных
2025-01-23 22:41:52 +07:00
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" ) ; // Путь к папке для отчётов
2025-01-24 14:08:12 +07:00
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 ) ;
}
2025-01-24 14:08:12 +07:00
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 ) )
{
2025-01-24 14:08:12 +07:00
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 ) ;
}
}
2025-01-24 14:08:12 +07:00
MessageBox . Show ( $"Отчёт сохранён в папке: {reportsDirectory}" , "Успех" ) ;
2025-01-23 23:41:57 +07:00
}
catch ( Exception ex )
{
MessageBox . Show ( $"Ошибка при сохранении отчёта: {ex.Message}" , "Ошибка" ) ;
}
}
2025-01-24 14:08:12 +07:00
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 ( ) ;
2025-01-24 14:08:12 +07:00
// Проверяем валидность 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 ;
2025-01-24 14:08:12 +07:00
// Передаем все три списка в метод 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В ы можете открыть эту папку вручную или добавить кнопку для её быстрого открытия." ) ;
}
2025-01-24 13:53:57 +07:00
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 ;
}
2025-01-23 22:41:52 +07:00
}
}