本文主要是介绍C#利用NPOI实现跨Excel数据查找(备件筛选工具),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
备件筛选工具,软件试用链接:https://download.csdn.net/download/weixin_44834086/12404203
备件筛选工具试用链接:https://download.csdn.net/download/weixin_44834086/12404203
软件演示视频链接:https://www.bilibili.com/video/BV145411s7fu/
设备工程师最常见的一项工作就是备件清单梳理,每次当供应商提供一份元器件清单给我我们后,我们会先进行初步筛选,选出哪些是我们需要的,形成初步的备件清单,但这个清单不能直接提交给采购部,因为这个清单里可能存在库房里已经有的备件,这部分已经有的备件是不需要买的,我们必须把它们筛选出来删掉,才能提交给采购部购买。
怎样才能知道哪些备件是库房里已经有的呢?
你是不是会一个个的在库房台账Excel里按Ctrl+F查找?
或者你把初版备件清单复制到库房台账的Excel里,标记重复项?
当然,这是其中的两种方法,可是你有没有想过,这两种方法是不是就一定能达到我们的目的?
你想想下面这种情况:一个备件供应商提供的型号是“QSL-1/4-10”,但库房台账里的型号却是“QSL 1/4-10”,型号里只是多一个“-”,此时用上述的两种方法搜索是没有匹配的结果的,但实际上这两个型号是一样的,这时你会认为库房买有,结果买回来后发现库房有相同的备件,造成浪费。(别说了,说多了都是泪,库房里还有好多型号不同但东西是一样的的备件)。
这个事情没人管吗???!!!
于是我就开发这个备件筛选工具,就是为了解决上面这个问题,该工具可以设置搜索的相似精度,备件型号里的特殊字符都会过滤掉,把可能相同的备件全部筛选出来,给设备工程师判断这些备件是否一样提供一个参考,避免备件的重复购买。
如有bug欢迎提出,谢谢。
软件界面如下所示:
如下图所示,设置搜索的相似精度为85%,软件完成搜索后会将搜索结果显示在窗体下方的DateGridView中,文件1中的哪一行,与文件2中的哪一行有相似的备件,设备工程师可以两个型号进行对比确认备件是否相同。
程序主要有以下功能:
1、字符串处理(过滤字符串中的特殊字符);
2、引用了两种字符串相似度的算法,并取两种算法算出的较大结果作为筛选的结果(可以避免漏选);
3、生成结果清单(使用NPOI创建Excel文件,并将DateGridView中的数据写入Excel文件);
4、生成备件清单(复制一份文件1,再使用NPOI将筛选出来的行删掉)
主要代码如下:
using System;
using System.Linq;
using System.Windows.Forms;
using F23.StringSimilarity;
using NP = NPOI.XSSF.UserModel;
using System.IO;
using System.Threading;
using NPOI.HSSF.UserModel;
using System.Drawing;
using Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System.Collections;namespace 备件筛选工具
{public partial class Form1 : Form{public Form1(){InitializeComponent();Control.CheckForIllegalCrossThreadCalls = false;//程序加载时取消跨线程操作的访问 X = this.Width;//获取窗体的宽度Y = this.Height;//获取窗体的高度setTag(this);//调用方法}NPOI.SS.UserModel.ISheet sht1;//声明一个sheet sht1NPOI.SS.UserModel.ISheet sht2;//声明一个sheet sht2string FilePath1 = "";//声明字符串变量 文件1路径string FilePath2 = "";//声明字符串变量 文件2路径string fileName1 = "";string fileName2 = "";ArrayList matchRow = new ArrayList();//选择文件1private void Btn_Select1_Click(object sender, EventArgs e){OpenFileDialog ofd1 = new OpenFileDialog();ofd1.InitialDirectory = @"C:\Users\28463\Desktop";//定义打开文件对话框的初始目录ofd1.Title = "请选择要筛选的文件";//定义打开文件对话框的名称ofd1.Filter = "所有文件|*.xls;*.xlsx";//过滤只显示Excel文件ofd1.ShowDialog(); //弹出打开文件对话框fileName1 = System.IO.Path.GetFileName(ofd1.FileName);//将文件1的名称赋值给文本框fileNametext_FilePath1.Text = fileName1;//将文件1的名称赋值给文本框text_FilePath1.TextFilePath1 = ofd1.FileName;//将文件1的路径赋值给FilePath1}//选择文件2private void Btn_Select2_Click(object sender, EventArgs e){OpenFileDialog ofd2 = new OpenFileDialog();ofd2.InitialDirectory = @"C:\Users\28463\Desktop";//定义打开文件对话框的初始目录ofd2.Title = "请选择要筛选的文件";//定义打开文件对话框的名称ofd2.Filter = "所有文件|*.xls;*.xlsx";//过滤只显示Excel文件ofd2.ShowDialog();//弹出打开文件对话框fileName2 = System.IO.Path.GetFileName(ofd2.FileName);//将文件2的名称赋值给文本框fileNametext_FilePath2.Text = fileName2;//将文件2的名称赋值给文本框text_FilePath2.Text FilePath2 = ofd2.FileName;//将文件2的路径赋值给FilePath1 }private void OpenFile1_Click(object sender, EventArgs e){try{System.Diagnostics.Process.Start(FilePath1);}catch (Exception ex){MessageBox.Show(ex.Message.ToString() + "\r\n" + "请检查是否选择文件!", "错误提示"); //抛出异常信息}}private void OpenFile2_Click(object sender, EventArgs e){try{System.Diagnostics.Process.Start(FilePath2);}catch (Exception ex){MessageBox.Show(ex.Message.ToString() + "\r\n" + "请检查是否选择文件!", "错误提示"); //抛出异常信息}}#region 过滤掉字符串中的特殊字符/// <summary>/// 过滤掉字符串中的特殊字符/// </summary>/// <param name="str">需要过滤字符串</param>/// <returns>过滤之后的字符串</returns>public static string ReplaceSymbol(string str){if (str == String.Empty)return String.Empty;//半角符号str = str.Replace("'", "");str = str.Replace("·", "");str = str.Replace(".", "");str = str.Replace(",", "");str = str.Replace(";", "");str = str.Replace(",", "");str = str.Replace("?", "");str = str.Replace("-", "");str = str.Replace("_", "");str = str.Replace("/", "");str = str.Replace("(", "(");str = str.Replace(")", ")");str = str.Replace("\\", "");//全角符号str = str.Replace(";", "");str = str.Replace(",", "");str = str.Replace("?", "");str = str.Replace("——", "");str = str.Replace("、", "");str = str.Replace("(", "");str = str.Replace(")", "");str = str.Replace("。", "");return str;}#endregion#region 利用Levenshtein方法计算两个字符串的相似率/// <summary>/// 利用Levenshtein方法计算两个字符串的相似率/// </summary>/// <param name="str1">字符串1</param>/// <param name="str2">字符串2</param>/// <returns>相似率</returns>private double Similarity1(string str1, string str2){str1 = ReplaceSymbol(str1).ToLower();//将字符串str1中的特殊符号去掉,并把字母变成小写str2 = ReplaceSymbol(str2).ToLower();//将字符串str2中的特殊符号去掉,并把字母变成小写double maxlen = str1.Length > str2.Length ? str1.Length : str2.Length;//取两个字符串长度中的较大的值,赋值给maxlenvar le = new Levenshtein();//实例化一个名称为le的Levenshtein对象,用于求从一个字符串变换到另一个字符串所需要的最短距离(步骤)double SimilarityRate = (1 - le.Distance(str1, str2) / maxlen);//计算相似率,其中le.Distance(str1,str2)为两个字符串转换的最短路径(步骤)return SimilarityRate;//返回相似率}#endregion#region 计算字符串相似度/// <summary>/// 获取两个字符串的相似度/// </summary>/// <param name=”str1”>第一个字符串</param>/// <param name=”str2”>第二个字符串</param>/// <returns></returns>private double Similarity2(string str1, string str2){str1 = ReplaceSymbol(str1).ToLower();str2 = ReplaceSymbol(str2).ToLower();double Kq = 2;double Kr = 1;double Ks = 1;char[] ss = str1.ToCharArray();char[] st = str2.ToCharArray();//获取交集数量int q = ss.Intersect(st).Count();int s = ss.Length - q;int r = st.Length - q;return Kq * q / (Kq * q + Kr * r + Ks * s);}#endregionprivate bool IsContain(string str1, string str2){str1 = ReplaceSymbol(str1).ToLower();str2 = ReplaceSymbol(str2).ToLower();return str2.Contains(str1);}private void Btn_SearchSimilarity_Click(object sender, EventArgs e){flag_SearchStop = false;btn_Stop.Focus();matchRow.Clear();//清空集合matchRow中的数据dataGridView1.Rows.Clear();//清除dataGridView1表格数据btn_SearchContain.Enabled = false;SearchSimilarity();//调用“搜索相似”方法btn_SearchContain.Enabled = true;}private void Btn_SearchContain_Click(object sender, EventArgs e){flag_SearchStop = false;btn_Stop.Focus();matchRow.Clear();//清空集合matchRow中的数据dataGridView1.Rows.Clear();//清除dataGridView1表格数据btn_SearchSimilarity.Enabled = false;SearchContain();//调用“搜索包含”方法btn_SearchSimilarity.Enabled = true;}/// <summary>/// 根据不同格式的Excel获取sheet(因为xlsx格式的Excel和xls格式的Excel获取sheet的方式不一样)/// </summary>/// <param name="FilePath">文件路径</param>/// <param name="fileName">文件名</param>/// <returns></returns>private NPOI.SS.UserModel.ISheet GetSheet(string FilePath, string fileName, int sheetIndex){FileStream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);//必须要选择flieShare方式为ReadWrite,这样就可以在文件被打开的时候读取文件信息。if ((fileName.Split('.')[fileName.Split('.').Length - 1]).ToLower() == "xlsx")//判断文件1的文件名最后一个.后的字符串是否为xlsx{NP.XSSFWorkbook wk = new NP.XSSFWorkbook(fs);//实例化一个.xlsx格式的工作簿NPOI.SS.UserModel.ISheet sht = wk.GetSheetAt(sheetIndex);//根据“选择sheet”下拉列表框,获取工作表return sht;}else //((fileName1.Split('.')[fileName1.Split('.').Length - 1]).ToLower() == "xls")//判断文件1的文件名最后一个.后的字符串是否为xls{HSSFWorkbook wk = new HSSFWorkbook(fs);//实例化一个.xls格式的工作簿NPOI.SS.UserModel.ISheet sht = wk.GetSheetAt(sheetIndex);//根据“选择sheet”下拉列表框,获取工作表return sht;}}bool flag_SearchStop = false;private void SearchSimilarity(){try{sht1 = GetSheet(FilePath1, fileName1, comboBox_sheet1.SelectedIndex);sht2 = GetSheet(FilePath2, fileName2, comboBox_sheet2.SelectedIndex);int rowsCount1 = sht1.LastRowNum;//获取工作表sht1的有效行数int rowsCount2 = sht2.LastRowNum;//获取工作表sht2的有效行数int listNumber = Convert.ToInt32(comboBox_list1.SelectedIndex);//根据“选择列:”下拉列表框的选择索引号,获取列 progressBar1.Visible = true;//显示进度条progressBar1.Maximum = rowsCount1;//设置进度条的最大值为sht1的行数+1lbl_ProgressbarValue.Visible = true;//显示进度条百分比for (int i = Convert.ToInt32(comboBox_Row1.Text) - 1; i <= rowsCount1; i++)//i为sht1的行数索引{progressBar1.Value = i;//定义进度条的值为ilbl_ProgressbarValue.Text = (i * 100 / progressBar1.Maximum).ToString() + "%";//将进度条百分比赋值给文本框Application.DoEvents();//重点,必须加上,否则窗体会假死if (progressBar1.Value == progressBar1.Maximum){MessageBox.Show("搜索完成,搜到" + (dataGridView1.Rows.Count - 1).ToString() + "个结果!", "搜索结果提示");progressBar1.Value = 0;//将进度条数据置零progressBar1.Visible = false;//隐藏进度条lbl_ProgressbarValue.Visible = false;//隐藏进度条百分比 btn_SaveSearchResult.Enabled = true;//搜索完成后使能“保存搜索结果”按钮btn_CreateResultExcel.Enabled = true;//搜索完成后使能“生成备件清单”按钮}if (!flag_SearchStop){if (sht1.GetRow(i).GetCell(listNumber) != null)//如果sht1第i行第listNumber列不为空{string str1 = GetCellValue(sht1, i, listNumber);if (str1 == ""){continue;//如果读取的sht1第i行,第listNumber列单元格的字符串的值为空,则跳出当前循环,进入下一循环}else //如果读取的sht1第i行,第listNumber列单元格的字符串的值不为空,则继续按下述循环判断sht2中的数据{for (int j = Convert.ToInt32(comboBox_Row2.Text) - 1; j <= rowsCount2; j++)//j为sht2的行数索引{if (sht2.GetRow(j) != null){if (comboBox_list2.Text == "搜索全部列"){for (int k = sht2.GetRow(j).FirstCellNum; k <= sht2.GetRow(j).LastCellNum; k++)//K为sht2的列数索引(或单元格索引){if (sht2.GetRow(j).GetCell(k) != null) //如果sht2的第j行,第k列的单元格数据不为空{string str2 = GetCellValue(sht2, j, k);if (str2 == ""){continue;//如果读取的sht2第j行,第k列单元格的字符串的值为空,则跳出当前循环,进入下一循环}else //如果读取的sht2第j行,第k列单元格的字符串的值不为空,执行如下比较字符串相似度的语句{double Simi = Similarity1(str1, str2) > Similarity2(str1, str2) ? Similarity1(str1, str2) : Similarity2(str1, str2);if (Simi >= Convert.ToDouble(comboBox_accuracy.Text) / 100){WriteToDateGridView(i, j, str1, str2); //调用 WriteToDateGridView函数,将搜索结果显示到dateGridView里 ListAdd(i);//将匹配的行数存入集合中}}}else{continue;//如果sht1第i行第listNumber列为空,则跳出当前循环,进入下一循环;}}}else //如果sheet2选择了列,则不搜索全部列,只搜索选择的列,可以大大减少搜索次数,提高搜索速度{if (sht2.GetRow(j).GetCell(comboBox_list2.SelectedIndex - 1) != null) //如果sht2的第j行,第k列的单元格数据不为空{string str2 = GetCellValue(sht2, j, comboBox_list2.SelectedIndex - 1);if (str2 == ""){continue;//如果读取的sht2第j行,第k列单元格的字符串的值为空,则跳出当前循环,进入下一循环}else //如果读取的sht2第j行,第k列单元格的字符串的值不为空,执行如下比较字符串相似度的语句{double Simi = Similarity1(str1, str2) > Similarity2(str1, str2) ? Similarity1(str1, str2) : Similarity2(str1, str2);if (Simi >= Convert.ToDouble(comboBox_accuracy.Text) / 100){WriteToDateGridView(i, j, str1, str2); //调用 WriteToDateGridView函数,将搜索结果显示到dateGridView里ListAdd(i);//将匹配的行数存入集合中}}}else{continue;//如果sht1第i行第listNumber列为空,则跳出当前循环,进入下一循环;}}}else{continue;}}}}else{continue;}}else{break;}}}catch (Exception ex){MessageBox.Show(ex.Message.ToString() + "\r\n" + "1.请检查是否选择文件!" + "\r\n" + "2.请检查文件的sheet和列是否选择正确!", "错误提示"); //抛出异常信息}}private void SearchContain(){try{sht1 = GetSheet(FilePath1, fileName1, comboBox_sheet1.SelectedIndex);sht2 = GetSheet(FilePath2, fileName2, comboBox_sheet2.SelectedIndex);int rowsCount1 = sht1.LastRowNum;//获取工作表sht1的有效行数int rowsCount2 = sht2.LastRowNum;//获取工作表sht2的有效行数int listNumber = Convert.ToInt32(comboBox_list1.SelectedIndex);//根据“选择列:”下拉列表框的选择索引号,获取列 progressBar1.Visible = true;//显示进度条progressBar1.Maximum = rowsCount1;//设置进度条的最大值为sht1的行数+1lbl_ProgressbarValue.Visible = true;//显示进度条百分比for (int i = Convert.ToInt32(comboBox_Row1.Text) - 1; i <= rowsCount1; i++)//i为sht1的行数索引{progressBar1.Value = i;//定义进度条的值为ilbl_ProgressbarValue.Text = (i * 100 / progressBar1.Maximum).ToString() + "%";//将进度条百分比赋值给文本框Application.DoEvents();//重点,必须加上,否则窗体会假死if (progressBar1.Value == progressBar1.Maximum){MessageBox.Show("搜索完成,搜到" + (dataGridView1.Rows.Count - 1).ToString() + "个结果!", "搜索结果提示");progressBar1.Value = 0;//将进度条数据置零progressBar1.Visible = false;//隐藏进度条lbl_ProgressbarValue.Visible = false;//隐藏进度条百分比 }if (!flag_SearchStop){if (sht1.GetRow(i).GetCell(listNumber) != null)//如果sht1第i行第listNumber列不为空{string str1 = GetCellValue(sht1, i, listNumber);if (str1 == ""){continue;//如果读取的sht1第i行,第listNumber列单元格的字符串的值为空,则跳出当前循环,进入下一循环}else //如果读取的sht1第i行,第listNumber列单元格的字符串的值不为空,则继续按下述循环判断sht2中的数据{for (int j = Convert.ToInt32(comboBox_Row2.Text) - 1; j <= rowsCount2; j++)//j为sht2的行数索引{if (sht2.GetRow(j) != null){if (comboBox_list2.Text == "搜索全部列"){for (int k = sht2.GetRow(j).FirstCellNum; k <= sht2.GetRow(j).LastCellNum; k++)//K为sht2的列数索引(或单元格索引){if (sht2.GetRow(j).GetCell(k) != null) //如果sht2的第j行,第k列的单元格数据不为空{string str2 = GetCellValue(sht2, j, k);if (str2 == ""){continue;//如果读取的sht2第j行,第k列单元格的字符串的值为空,则跳出当前循环,进入下一循环}else //如果读取的sht2第j行,第k列单元格的字符串的值不为空,执行如下比较字符串相似度的语句{if (IsContain(str1, str2)){WriteToDateGridView(i, j, str1, str2); //调用 WriteToDateGridView函数,将搜索结果显示到dateGridView里 ListAdd(i);//将匹配的行数存入集合中}}}else{continue;//如果sht1第i行第listNumber列为空,则跳出当前循环,进入下一循环;}}}else //如果sheet2选择了列,则不搜索全部列,只搜索选择的列,可以大大减少搜索次数,提高搜索速度{if (sht2.GetRow(j).GetCell(comboBox_list2.SelectedIndex - 1) != null) //如果sht2的第j行,第k列的单元格数据不为空{string str2 = GetCellValue(sht2, j, comboBox_list2.SelectedIndex - 1);if (str2 == ""){continue;//如果读取的sht2第j行,第k列单元格的字符串的值为空,则跳出当前循环,进入下一循环}else //如果读取的sht2第j行,第k列单元格的字符串的值不为空,执行如下比较字符串相似度的语句{if (IsContain(str1, str2)){WriteToDateGridView(i, j, str1, str2); //调用 WriteToDateGridView函数,将搜索结果显示到dateGridView里 ListAdd(i);//将匹配的行数存入集合中}}}else{continue;//如果sht1第i行第listNumber列为空,则跳出当前循环,进入下一循环;}}}else{continue;}}}}else{continue;}}else{break;}}}catch (Exception ex){MessageBox.Show(ex.Message.ToString() + "\r\n" + "1.请检查是否选择文件!" + "\r\n" + "2.请检查文件的sheet和列是否选择正确!", "错误提示"); //抛出异常信息}}private void Btn_Clear_Click(object sender, EventArgs e){dataGridView1.Rows.Clear();//清除dataGridView1表格数据matchRow.Clear();//清空集合matchRow中的数据progressBar1.Value = 0;//将进度条数据置零progressBar1.Visible = false;//隐藏进度条lbl_ProgressbarValue.Visible = false;//隐藏进度条百分比btn_SaveSearchResult.Enabled = false;//让“保存搜索结果”按钮无效btn_CreateResultExcel.Enabled = false;//让“生成备件清单”按钮无效//button1.Visible = true;}/// <summary>/// 将搜索结果显示到dateGridView里/// </summary>/// <param name="i">str1所在的行数</param>/// <param name="j">str1所在的行数</param>/// <param name="str1">sheet1中的字符串</param>/// <param name="str2">sheet2中的字符串</param>private void WriteToDateGridView(int i, int j, string str1, string str2){int index = this.dataGridView1.Rows.Add();this.dataGridView1.Rows[index].Cells[0].Value = (index + 1).ToString();this.dataGridView1.Rows[index].Cells[1].Value = "第" + (i + 1).ToString() + "行";this.dataGridView1.Rows[index].Cells[2].Value = str1;this.dataGridView1.Rows[index].Cells[3].Value = "第" + (j + 1).ToString() + "行";this.dataGridView1.Rows[index].Cells[4].Value = str2;}private string GetCellValue(NPOI.SS.UserModel.ISheet sht, int i, int j){string str = "";//声明字符串变量str2string cell_Type = sht.GetRow(i).GetCell(j).CellType.ToString();//获取sht2第j行,第k列单元格的数据格式,并赋值给字符串变量cell_Type2 switch (cell_Type) //根据单元格里的数据格式读取数据的值;{case "String":str = sht.GetRow(i).GetCell(j).StringCellValue;//按字符串格式读取单元格数据的值break;case "Numeric":str = sht.GetRow(i).GetCell(j).NumericCellValue.ToString();//按数值格式读取单元格数据的值break;}return str;}private void Btn_SaveSearchResult_Click(object sender, EventArgs e){SaveFileDialog saveFileDialog = new SaveFileDialog();saveFileDialog.Filter = "Excel files (*.xls)|*.xls";saveFileDialog.FilterIndex = 0;saveFileDialog.RestoreDirectory = true;saveFileDialog.CreatePrompt = true;saveFileDialog.Title = "导出Excel文件到";DateTime now = DateTime.Now;saveFileDialog.FileName = "搜索结果" + "-" + DateTime.Now.ToLongDateString().ToString() + "-" + now.Hour.ToString().PadLeft(2, '0') + "时" + now.Minute.ToString().PadLeft(2, '0') + "分" + now.Second.ToString().PadLeft(2, '0') + "秒";saveFileDialog.ShowDialog();this.dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;this.dataGridView1.MultiSelect = false;Stream myStream = saveFileDialog.OpenFile();StreamWriter sw = new StreamWriter(myStream, System.Text.Encoding.GetEncoding("gb2312"));string str = "";try{//写标题 for (int i = 0; i < this.dataGridView1.ColumnCount; i++){if (i > 0){str += "\t";}str += this.dataGridView1.Columns[i].HeaderText;}sw.WriteLine(str);//写内容 for (int j = 0; j < this.dataGridView1.Rows.Count; j++){string tempStr = "";for (int k = 0; k < this.dataGridView1.Columns.Count; k++){if (k > 0){tempStr += "\t";}if (this.dataGridView1.Rows[j].Cells[k].Value != null){tempStr += this.dataGridView1.Rows[j].Cells[k].Value.ToString();}else{continue;}}sw.WriteLine(tempStr);}sw.Close();myStream.Close();if (File.Exists("搜索结果" + "-" + DateTime.Now.ToLongDateString().ToString() + "-" + now.Hour.ToString().PadLeft(2, '0') + ":" + now.Minute.ToString().PadLeft(2, '0') + ":" + now.Second.ToString().PadLeft(2, '0'))){MessageBox.Show("搜索结果保存成功!保存路径与原文件路径相同!", "保存提示");}}catch (Exception ex){MessageBox.Show(ex.ToString());}finally{sw.Close();myStream.Close();}}/// <summary>/// “生产备件清单”按钮的的单击事件,根据匹配成功的行数,删除匹配成功的行数,生成备件清单(匹配成功的表示库房已经有这个备件,则该备件不需要采购,所以将其删除后,剩下的即为备件清单)/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Btn_CreateResultExcel_Click(object sender, EventArgs e){string ResultPath = System.IO.Path.GetDirectoryName(FilePath1) +"\\"+ "备件清单" + "-" + DateTime.Now.ToLongDateString().ToString()+".xlsx";//指定存储的路径 File.Copy(FilePath1, ResultPath, true);//三个参数分别是源文件路径,存储路径,若存储路径有相同文件是否替换int deleteTimes = 0;//记录删除行的次数,因为没删除一行,需要删除的行数索引就变了(减少了1)for (int i = 0; i <= matchRow.Count-1; i++){DeleteRows(ResultPath, (Int32)matchRow[i]+1-deleteTimes);deleteTimes++;}//生成成功提示。if (File.Exists(ResultPath)){MessageBox.Show("备件清单生成成功!保存路径与原文件路径相同!", "保存提示");}else{MessageBox.Show("备件清单生成失败!", "保存提示");}}/// <summary>/// 删除Excel文件中的特定行(上移并覆盖)/// </summary>/// <param name="FilePath">需要删除的Excel文件全路径</param>/// <param name="rowIndex">需要删除的行数索引</param>private void DeleteRows(string FilePath, int rowIndex)//(Excel.Worksheet sheet, int rowIndex){FileStream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);//必须要选择flieShare方式为ReadWrite,这样就可以在文件被打开的时候读取文件信息。NP.XSSFWorkbook wk = new NP.XSSFWorkbook(fs);//实例化一个.xlsx格式的工作簿NPOI.SS.UserModel.ISheet sht = wk.GetSheetAt(comboBox_sheet1.SelectedIndex);//根据“选择sheet”下拉列表框,获取工作表 sht.ShiftRows(rowIndex, sht.LastRowNum, -1);//将从第rowIndex行到最后一行的数据向上移动一行,即将rowIndex-1行删除了FileStream file = new FileStream(FilePath, FileMode.Create);//实例化一个FileStream文件wk.Write(file);//将file文件流写入wk工作簿file.Close();//关闭文件流}/// <summary>/// 判断matchRow里是否存在当前行索引号(因为文件1中的某一行可能搜索出多个相似结果,经过判断后可以避免重复存入相同的行数到matchRow中,导致生成备件清单时删除错误)/// </summary>/// <param name="i">当前行索引号</param>private void ListAdd(int i){if (!matchRow.Contains(i))//判断集合matchRow中是否包含i{matchRow.Add(i);//如果不包含,则将i添加到matchRow中}else{return;//如果包含,则返回}}private void Located()//(string filePath,){string excelName = FilePath1;//你的excel文件的位置string sheetName = "sheet1";//你的sheet的名字string strStart = "A100";//起始单元格string strEnd = "B200";//结束单元格object missing = Type.Missing;Excel.Application excel = new Excel.Application();Excel.Workbook book = excel.Workbooks.Open(excelName, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing);Excel.Worksheet sheet = (Excel.Worksheet)book.Worksheets[sheetName];excel.Application.Goto(sheet.Range[strStart, strEnd], true);excel.Visible = true;}private void Form1_Load(object sender, EventArgs e){this.Resize += new EventHandler(Form1_Resize);X = this.Width;Y = this.Height;setTag(this);Form1_Resize(new object(), new EventArgs());}//***控制控件大小及文字大小开始***//private float X;private float Y;private void setTag(Control cons){foreach (Control con in cons.Controls){con.Tag = con.Width + ":" + con.Height + ":" + con.Left + ":" + con.Top + ":" + con.Font.Size;if (con.Controls.Count > 0)setTag(con);}}private void setControls(float newx, float newy, Control cons){foreach (Control con in cons.Controls){string[] mytag = con.Tag.ToString().Split(new char[] { ':' });float a = Convert.ToSingle(mytag[0]) * newx;con.Width = (int)a;a = Convert.ToSingle(mytag[1]) * newy;con.Height = (int)(a);a = Convert.ToSingle(mytag[2]) * newx;con.Left = (int)(a);a = Convert.ToSingle(mytag[3]) * newy;con.Top = (int)(a);Single currentSize = Convert.ToSingle(mytag[4]) * Math.Min(newx, newy);con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit);if (con.Controls.Count > 0){setControls(newx, newy, con);}}}void Form1_Resize(object sender, EventArgs e){float newx = (this.Width) / X;float newy = this.Height / Y;setControls(newx, newy, this);//this.Text = "窗体尺寸:" + this.Width.ToString() + " " + this.Height.ToString();}//***控制控件大小及文字大小结束***//private void Button1_Click(object sender, EventArgs e){Located(); }private void DataGridView1_DoubleClick(object sender, EventArgs e){//Located();}private void Btn_Help_Click(object sender, EventArgs e){using (Form_Help dlg = new Form_Help()) //Form_Help是窗口类名,确保访问;后面的是构造函数{dlg.ShowDialog();}}private void Btn_Stop_Click(object sender, EventArgs e){flag_SearchStop = true;}}
}
这篇关于C#利用NPOI实现跨Excel数据查找(备件筛选工具)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!