使用C#將幾個Excel文件合并去重分類
需要將幾個Excel表格里面的數據去重,然后將每個站點的數據另存為一張Sheet上。
幾個表格如下所示:


實現效果如下所示:

具體實現
需要使用EPPlus操作Excel
安裝EPPlus如下所示:

為了更好的演示與說明,把步驟進行了拆分,先導入Excel數據,再去重,再進行數據分類,最后再導出為Excel數據,設計了一個窗體,如下所示:

導入Excel數據
首先定義一個類,用來保存相關數據,類的設計如下:
public class WaterData
{
public int Id { get; set; }
public string? Name { get; set; }
public string? WaterLevel { get; set; }
public string? WaterChange { get; set; }
public string? Source { get; set; }
}
點擊導入Excel數據按鈕的代碼如下:
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Excel Files (*.xlsx; *.xls;*.csv)|*.xlsx; *.xls;*.csv";
openFileDialog.FilterIndex = 1;
openFileDialog.Multiselect = false;
?
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
filePath = openFileDialog.FileName;
ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
using (ExcelPackage package = new ExcelPackage(filePath))
{
?
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
?
//獲取表格的列數和行數
int rowCount = worksheet.Dimension.Rows;
int colCount = worksheet.Dimension.Columns;
?
for (int i = 0; i < rowCount - 1; i++)
{
//創建一個realData類保存數據
var data = new WaterData();
data.Id = n;
data.Name = (string)worksheet.Cells[i + 2, 3].Value;
data.WaterLevel = Convert.ToString(worksheet.Cells[i + 2, 4].Value);
data.WaterChange = Convert.ToString(worksheet.Cells[i + 2, 5].Value);
data.Source = (string)worksheet.Cells[i + 2, 2].Value;
waterList.Add(data);
n++;
}
package.Save();
?
}
}
else
{
?
MessageBox.Show("您本次沒有選擇任何文件!!!");
}
}
上面的n是static int,初始值為0。
導入Excel數據的效果如下所示:

數據去重
執行數據去重,依據的是C#LINQ中的DistinctBy方法,本例中不使用id是因為每條數據id都不一樣,即使是重復的數據但是id也不一樣,本例依據的中Name屬性和Soure屬性,只要這兩個數據一樣,就認為是重復數據。
點擊數據去重按鈕的代碼如下:
private void button2_Click(object sender, EventArgs e)
{
distinctList = waterList.DistinctBy(x => new { x.Name, x.Source }).ToList();
}
只需要一行代碼:
distinctList = waterList.DistinctBy(x => new { x.Name, x.Source }).ToList();
執行去重的效果如下所示:

執行數據分類
本例中要求將同一個站點的數據放在同一張Sheet上,那么首先需要知道到底有多少個不同的站名,代碼如下:
var Names = distinctList.Select(x => x.Name).Distinct().ToList();
實現效果如下:

由于這些數據是由圖片文字識別而來的,因此可能識別有誤,如果一個站名的數據不足50條,就不需要,代碼如下:
for (int i = 0; i < Names.Count; i++)
{
var nameList = distinctList.Where(x => x.Name == Names[i]).ToList();
if (nameList.Count > 50)
{
list.Add(nameList);
}
}
實現數據分類也只需要一行代碼:
var nameList = distinctList.Where(x => x.Name == Names[i]).ToList();
實現效果如下所示:

導出為Excel文件
本例中導出為Excel文件的思路是先讓用戶選定一個文件夾,然后就將導出的Excel文件保存在這個文件夾下面,導出為Excel文件的代碼如下:
private void button4_Click(object sender, EventArgs e)
{
// 創建一個FolderBrowserDialog對象
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
?
// 設置對話框的標題
folderBrowserDialog.Description = "選擇保存各站點數據的文件夾";
?
// 設置默認的根文件夾,如果需要的話
// folderBrowserDialog.RootFolder = Environment.SpecialFolder.MyComputer;
?
// 顯示文件夾選擇對話框
DialogResult result = folderBrowserDialog.ShowDialog();
?
if (result == DialogResult.OK)
{
// 用戶選擇了一個文件夾
selectedFolderPath = folderBrowserDialog.SelectedPath;
richTextBox1.Text += $"選擇的Excel保存文件夾為:{selectedFolderPath}\r\n";
richTextBox1.Text += "正在執行導出為Excel文件...";
using (ExcelPackage excelPackage = new ExcelPackage())
{
for(int i =0; i < list.Count; i++)
{
ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add(list[i][0].Name);
for (int j = 0; j < list[i].Count; j++)
{
worksheet.Cells[j + 1, 1].Value = list[i][j].Id;
worksheet.Cells[j + 1, 2].Value = list[i][j].Name;
worksheet.Cells[j + 1, 3].Value = list[i][j].WaterLevel;
worksheet.Cells[j + 1, 4].Value = list[i][j].WaterChange;
worksheet.Cells[j + 1, 5].Value = list[i][j].Source;
}
}
?
// 保存 Excel 文件
FileInfo excelFile = new FileInfo($"{selectedFolderPath}\\各站點數據.xlsx");
excelPackage.SaveAs(excelFile);
richTextBox1.Text += "導出為Excel文件完成\r\n";
}
}
}
實現效果如下所示:

最后
操作Excel大家一般使用VBA、Python比較多,本文通過一個實例演示了如何通過C#來簡化我們的辦公(處理Excel數據)。
本實例全部源代碼如下:
using OfficeOpenXml;
using System.Collections;
using System.Collections.Generic;
?
namespace Excel數據處理
{
public partial class Form1 : Form
{
string filePath;
string selectedFolderPath;
static int n = 0;
List<WaterData> waterList = new List<WaterData>();
List<WaterData> distinctList = new List<WaterData>();
List<List<WaterData>> list = new List<List<WaterData>>();
public class WaterData
{
public int Id { get; set; }
public string? Name { get; set; }
public string? WaterLevel { get; set; }
public string? WaterChange { get; set; }
public string? Source { get; set; }
?
}
?
?
public Form1()
{
InitializeComponent();
}
?
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Excel Files (*.xlsx; *.xls;*.csv)|*.xlsx; *.xls;*.csv";
openFileDialog.FilterIndex = 1;
openFileDialog.Multiselect = false;
?
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
filePath = openFileDialog.FileName;
richTextBox1.Text += $"您選中的文件路徑為:{filePath}\r\n";
richTextBox1.Text += $"正在導入Excel數據...\r\n";
ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
using (ExcelPackage package = new ExcelPackage(filePath))
{
?
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
?
//獲取表格的列數和行數
int rowCount = worksheet.Dimension.Rows;
int colCount = worksheet.Dimension.Columns;
?
for (int i = 0; i < rowCount - 1; i++)
{
//創建一個realData類保存數據
var data = new WaterData();
data.Id = n;
data.Name = (string)worksheet.Cells[i + 2, 3].Value;
data.WaterLevel = Convert.ToString(worksheet.Cells[i + 2, 4].Value);
data.WaterChange = Convert.ToString(worksheet.Cells[i + 2, 5].Value);
data.Source = (string)worksheet.Cells[i + 2, 2].Value;
waterList.Add(data);
n++;
}
richTextBox1.Text += $"導入Excel數據成功,數據量為:{rowCount - 1}\r\n";
package.Save();
?
}
}
else
{
?
MessageBox.Show("您本次沒有選擇任何文件!!!");
}
}
?
private void button2_Click(object sender, EventArgs e)
{
richTextBox1.Text += "正在執行數據去重...\r\n";
distinctList = waterList.DistinctBy(x => new { x.Name, x.Source }).ToList();
richTextBox1.Text += $"數據去重已完成,去重后數據量為:{distinctList.Count}\r\n";
}
?
private void button3_Click(object sender, EventArgs e)
{
richTextBox1.Text += "正在執行數據分類...\r\n";
var Names = distinctList.Select(x => x.Name).Distinct().ToList();
for (int i = 0; i < Names.Count; i++)
{
var nameList = distinctList.Where(x => x.Name == Names[i]).ToList();
if (nameList.Count > 50)
{
list.Add(nameList);
}
}
richTextBox1.Text += $"執行數據分類完成,類數為:{list.Count}\r\n";
}
?
private void button4_Click(object sender, EventArgs e)
{
// 創建一個FolderBrowserDialog對象
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
?
// 設置對話框的標題
folderBrowserDialog.Description = "選擇保存各站點數據的文件夾";
?
// 設置默認的根文件夾,如果需要的話
// folderBrowserDialog.RootFolder = Environment.SpecialFolder.MyComputer;
?
// 顯示文件夾選擇對話框
DialogResult result = folderBrowserDialog.ShowDialog();
?
if (result == DialogResult.OK)
{
// 用戶選擇了一個文件夾
selectedFolderPath = folderBrowserDialog.SelectedPath;
richTextBox1.Text += $"選擇的Excel保存文件夾為:{selectedFolderPath}\r\n";
richTextBox1.Text += "正在執行導出為Excel文件...";
using (ExcelPackage excelPackage = new ExcelPackage())
{
for(int i =0; i < list.Count; i++)
{
ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add(list[i][0].Name);
for (int j = 0; j < list[i].Count; j++)
{
worksheet.Cells[j + 1, 1].Value = list[i][j].Id;
worksheet.Cells[j + 1, 2].Value = list[i][j].Name;
worksheet.Cells[j + 1, 3].Value = list[i][j].WaterLevel;
worksheet.Cells[j + 1, 4].Value = list[i][j].WaterChange;
worksheet.Cells[j + 1, 5].Value = list[i][j].Source;
}
}
?
// 保存 Excel 文件
FileInfo excelFile = new FileInfo($"{selectedFolderPath}\\各站點數據.xlsx");
excelPackage.SaveAs(excelFile);
richTextBox1.Text += "導出為Excel文件完成\r\n";
}
}
}
}
}
如果你也對C#感興趣,歡迎關注微信公眾號DotNet學習交流~

浙公網安備 33010602011771號