WinForm使用DataGridView实现类似Excel表格的查找替换

在桌面程序开发过程中我们常常使用DataGridView作为数据展示的表格,在表格中我们可能要对数据进行查找或者替换。
其实要实现这个查找替换的功能并不难,记录下实现过程,不一定是最好的方式,但它有用!
先看demo下效果

技术图片

1、数据展示

  • 建一个WinForm窗体 GridDataWindow ,放上菜单和DataGridView控件,添加4列用来显示信息。

技术图片

  • 创建一个Person类用于显示数据
 public class Person { public int ID { get; set; } public string Name { get; set; } public string Sex { get; set; } public int Age { get; set; } }
  • 在窗体Load事件里面初始化显示数据

技术图片

2、查找替换窗体

  • 建一个WinForm窗体 DataToolsWindow

技术图片

这个窗体主要是用来控制查找和替换的文本,选择范围是当前列还是整个数据表格。
窗体中主要是查找替换文本的值,选中的查找范围和是否能设置查找范围变量;还包括4个事件,4个事件在GridDataWindow 中添加用于响应操作。

  • LookUpHandler:点击查找,根据选择的范围和值依次查找表格单元格。
  • ReplaceHandler:替换文本,根据选择的范围和值依次查找表格单元格,如果查找到则替换。
  • ReplaceAllHandler:全部替换,根据选择的范围和值依次查找所有表格单元格,查找到并全部替换。
  • WindownClosedHandler:窗体关闭,当查找窗体关闭后主窗体得到通知并做些需要的逻辑。
public event EventHandler LookUpHandler;public event EventHandler ReplaceHandler;public event EventHandler ReplaceAllHandler;public event EventHandler WindownClosedHandler;public bool AllLookup{ get { if (cbRange.SelectedIndex == 1) return true; else return false; } set { if (value) { cbRange.SelectedIndex = 1; } else { cbRange.SelectedIndex = 0; } }}public bool CanSetRang{ set { btnLookup.Enabled = false; btnReplace.Enabled = false; btnAllReplace.Enabled = false; }}public string LookupContent{ get { return txtLookup.Text; } set { txtLookup.Text = value; }}public string ReplaceContent{ get { return txtReplace.Text; }}

3、如何查找替换

技术图片

实例化一个DataToolsWindow后对事件进行注册。重点是如何查找,因为替换和查找一样,只要查找到了替换就行了。

  • 查找下一个

大概的思路就是按照【选定】的当前单元格为标记,首先以当前单元格为分界线向下查找,在查找的过程中判断用户选择的是当前列还是整个数据表,如果是当前列只需要按行查找当前列就行了。
如果是整个数据表查找则需要整行的每列都查找,如果查找到选中行查找的列就是找当前列前面的列(后面的列会在向下查找中遍历到),如果不是选中行则整行从第一列开始全部列查找。
同理,向下查找的思路也就出来了。

private void ToolsWindow_LookUpHandler(object sender, EventArgs e){ int currentRowIndex = dgvPeople.CurrentCell.RowIndex; int currentColumnIndex = dgvPeople.CurrentCell.ColumnIndex; foreach (DataGridViewRow row in dgvPeople.Rows) { //向下查找 if (row.Index >= currentRowIndex) { if (toolsWindow.AllLookup) { //如果是当前选中行 则查找后面的列 if (currentRowIndex == row.Index) { foreach (DataGridViewCell cell in row.Cells) { if (cell.ColumnIndex > currentColumnIndex) { if (cell.Value != null && cell.Value.ToString().Contains(toolsWindow.LookupContent)) { cell.Selected = true; dgvPeople.CurrentCell = cell; return; } } } } else { //否则从第一列开始查找 foreach (DataGridViewCell cell in row.Cells) { if (cell.Value != null && cell.Value.ToString().Contains(toolsWindow.LookupContent)) { cell.Selected = true; dgvPeople.CurrentCell = cell; return; } } } } else { //字段查找不查找当前 因为是查找下一个 if (row.Index == currentRowIndex) continue; if (row.Cells[currentColumnIndex].Value != null && row.Cells[currentColumnIndex].Value.ToString().Contains(toolsWindow.LookupContent)) { row.Cells[currentColumnIndex].Selected = true; dgvPeople.CurrentCell = row.Cells[currentColumnIndex]; return; } } } } foreach (DataGridViewRow row in dgvPeople.Rows) { //向上查找 if (row.Index <= currentRowIndex) { if (toolsWindow.AllLookup) { //如果是当前选中行 只查找前面的列 if (currentRowIndex == row.Index) { foreach (DataGridViewCell cell in row.Cells) { if (cell.ColumnIndex < currentColumnIndex) { if (cell.Value != null && cell.Value.ToString().Contains(toolsWindow.LookupContent)) { cell.Selected = true; dgvPeople.CurrentCell = cell; return; } } } } else { //否则从第一列开始查找 foreach (DataGridViewCell cell in row.Cells) { if (cell.Value != null && cell.Value.ToString().Contains(toolsWindow.LookupContent)) { cell.Selected = true; dgvPeople.CurrentCell = cell; return; } } } } else { //字段查找不查找当前 因为是查找下一个 if (row.Index == currentRowIndex) continue; if (row.Cells[currentColumnIndex].Value != null && row.Cells[currentColumnIndex].Value.ToString().Contains(toolsWindow.LookupContent)) { row.Cells[currentColumnIndex].Selected = true; dgvPeople.CurrentCell = row.Cells[currentColumnIndex]; return; } } } } MessageBox.Show("未找到匹配项!");}
  • 替换下一个

替换就比较简单了,首先如果选中列就是查找的值则直接替换,然后再替换则按照查找的思路查找到下一个后替换就行了,代码基本一样就没必要放垃圾代码了。

  • 全部替换

全部替换就不用查找下一个要显示查找过程那么麻烦了,直接遍历所有单元格进行替换并选中供用户查看就行了。

private void ToolsWindow_ReplaceAllHandler(object sender, EventArgs e){ bool IsReplace = false; int currentColumnIndex = dgvPeople.CurrentCell.ColumnIndex; foreach (DataGridViewRow row in dgvPeople.Rows) { if (toolsWindow.AllLookup) { foreach (DataGridViewCell cell in row.Cells) { if (cell.ColumnIndex != 0 && cell.Value != null && cell.Value.ToString().Contains(toolsWindow.LookupContent)) { cell.Selected = true; cell.Value = cell.Value.ToString().Replace(toolsWindow.LookupContent, toolsWindow.ReplaceContent); IsReplace = true; } } } else { if (row.Cells[currentColumnIndex].Value != null && row.Cells[currentColumnIndex].Value.ToString().Contains(toolsWindow.LookupContent)) { row.Cells[currentColumnIndex].Selected = true; row.Cells[currentColumnIndex].Value = row.Cells[currentColumnIndex].Value.ToString().Replace(toolsWindow.LookupContent, toolsWindow.ReplaceContent); IsReplace = true; } } } if (!IsReplace) MessageBox.Show("未找到匹配项!");}

4、源文件

打包了这个两个窗体代码:DataGridViewExcel.zip

相关文章