备件筛选工具,软件试用链接: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 sht1
NPOI.SS.UserModel.ISheet sht2;//声明一个sheet sht2
string FilePath1 = "";//声明字符串变量 文件1路径
string FilePath2 = "";//声明字符串变量 文件2路径
string fileName1 = "";
string fileName2 = "";
ArrayList matchRow = new ArrayList();
//选择文件1
private 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的名称赋值给文本框fileName
text_FilePath1.Text = fileName1;//将文件1的名称赋值给文本框text_FilePath1.Text
FilePath1 = ofd1.FileName;//将文件1的路径赋值给FilePath1
}
//选择文件2
private 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的名称赋值给文本框fileName
text_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;//取两个字符串长度中的较大的值,赋值给maxlen
var 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);
}
#endregion
private 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的行数+1
lbl_ProgressbarValue.Visible = true;//显示进度条百分比
for (int i = Convert.ToInt32(comboBox_Row1.Text) - 1; i <= rowsCount1; i++)//i为sht1的行数索引
{
progressBar1.Value = i;//定义进度条的值为i
lbl_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的行数+1
lbl_ProgressbarValue.Visible = true;//显示进度条百分比
for (int i = Convert.ToInt32(comboBox_Row1.Text) - 1; i <= rowsCount1; i++)//i为sht1的行数索引
{
progressBar1.Value = i;//定义进度条的值为i
lbl_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 = "";//声明字符串变量str2
string 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;
}
}
}