• 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

  • 相关阅读:
    bk.
    仅仅为了记录
    一个简单的Lua解释器
    Lua与C++相互调用
    Struts标签、Ognl表达式、el表达式、jstl标签库这四者之间的关系和各自作用
    OGNL表达式struts2标签“%,#,$”
    Java异常报错机制
    到底EJB是什么?
    Spring总结
    JSON(JavaScript Object Notation)
  • 原文地址:https://www.cnblogs.com/SunSpring/p/15040513.html
Copyright © 2020-2023  润新知