C#利用NPOI实现跨Excel数据查找(备件筛选工具)

2024-01-17 18:20

本文主要是介绍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数据查找(备件筛选工具)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/616844

相关文章

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx

使用Python创建一个能够筛选文件的PDF合并工具

《使用Python创建一个能够筛选文件的PDF合并工具》这篇文章主要为大家详细介绍了如何使用Python创建一个能够筛选文件的PDF合并工具,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录背景主要功能全部代码代码解析1. 初始化 wx.Frame 窗口2. 创建工具栏3. 创建布局和界面控件4

javaScript在表单提交时获取表单数据的示例代码

《javaScript在表单提交时获取表单数据的示例代码》本文介绍了五种在JavaScript中获取表单数据的方法:使用FormData对象、手动提取表单数据、使用querySelector获取单个字... 方法 1:使用 FormData 对象FormData 是一个方便的内置对象,用于获取表单中的键值

Vue ElementUI中Upload组件批量上传的实现代码

《VueElementUI中Upload组件批量上传的实现代码》ElementUI中Upload组件批量上传通过获取upload组件的DOM、文件、上传地址和数据,封装uploadFiles方法,使... ElementUI中Upload组件如何批量上传首先就是upload组件 <el-upl

Docker部署Jenkins持续集成(CI)工具的实现

《Docker部署Jenkins持续集成(CI)工具的实现》Jenkins是一个流行的开源自动化工具,广泛应用于持续集成(CI)和持续交付(CD)的环境中,本文介绍了使用Docker部署Jenkins... 目录前言一、准备工作二、设置变量和目录结构三、配置 docker 权限和网络四、启动 Jenkins

Java实战之利用POI生成Excel图表

《Java实战之利用POI生成Excel图表》ApachePOI是Java生态中处理Office文档的核心工具,这篇文章主要为大家详细介绍了如何在Excel中创建折线图,柱状图,饼图等常见图表,需要的... 目录一、环境配置与依赖管理二、数据源准备与工作表构建三、图表生成核心步骤1. 折线图(Line Ch

Python3脚本实现Excel与TXT的智能转换

《Python3脚本实现Excel与TXT的智能转换》在数据处理的日常工作中,我们经常需要将Excel中的结构化数据转换为其他格式,本文将使用Python3实现Excel与TXT的智能转换,需要的可以... 目录场景应用:为什么需要这种转换技术解析:代码实现详解核心代码展示改进点说明实战演练:从Excel到

如何使用CSS3实现波浪式图片墙

《如何使用CSS3实现波浪式图片墙》:本文主要介绍了如何使用CSS3的transform属性和动画技巧实现波浪式图片墙,通过设置图片的垂直偏移量,并使用动画使其周期性地改变位置,可以创建出动态且具有波浪效果的图片墙,同时,还强调了响应式设计的重要性,以确保图片墙在不同设备上都能良好显示,详细内容请阅读本文,希望能对你有所帮助...

C# string转unicode字符的实现

《C#string转unicode字符的实现》本文主要介绍了C#string转unicode字符的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录1. 获取字符串中每个字符的 Unicode 值示例代码:输出:2. 将 Unicode 值格式化

python安装whl包并解决依赖关系的实现

《python安装whl包并解决依赖关系的实现》本文主要介绍了python安装whl包并解决依赖关系的实现,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录一、什么是whl文件?二、我们为什么需要使用whl文件来安装python库?三、我们应该去哪儿下