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

posted @ 2021-07-22 08:58  XSpringSun  阅读(1247)  评论(2编辑  收藏  举报