有个项目,客户要求表格要像Excel那样具有根据列的复杂筛选功能,而且最好不要改变太多原先的使用习惯。
上网搜了一下,大部分的都是把整列绑定到一个combobox上,覆盖到列标题上,从而达到简单的筛选功能。
仔细研究了下Excel的复杂筛选,仅靠DataGridView的右键功能不太好完全实现,于是就想到用一个panel来当筛选面板。
===================================================================
新建一个项目,form1中拖入一个datagridview,一个panel,一个statusStrip。
panel中如图所示放上2个label,7个button,3个combobox,1个listbox。
statusStrip中放入3个toolStripStatusLabel。
点击“升序”或者“降序”可以直接根据这一列来进行排序。
在筛选条件中,第一个combobox来选择“与”或者“或”,第二个combobox用来显示等于、大于、小于、包含等等,第三个combobox用来显示当前列所有非重复内容。
点击“添加条件”可以把上面的筛选条件添加到listbox中,选中listbox中的一个条件,点击“移除条件”可以移除该条件。
最后点击“确定”执行筛选,点击“取消”撤销本次所做的操作。
toolStripStatusLabel1用来显示按某一列升序或者降序排列。
toolStripStatusLabel2用来显示从N条数据中筛选到了M条数据。
toolStripStatusLabel3用来显示筛选的语句。
--------------------------------------------------
1、定义5个全局变量
DataTable dt; DataView dv; int row_total;//总行数 int row_select; //筛选后行数 string[] str_ltb;//存储筛选条件数组2、给datagridview填入数据并初始化一些数据
private void Form1_Load(object sender, EventArgs e) { dt = new DataTable(); dt.Columns.Add("ID", Type.GetType("System.Int32")); dt.Columns[0].AutoIncrement = true; //列值自动递增 dt.Columns[0].AutoIncrementSeed = 1; //起始值 dt.Columns[0].AutoIncrementStep = 1; //步长 dt.Columns.Add("Name", Type.GetType("System.String")); dt.Columns.Add("Birthday", Type.GetType("System.String")); dt.Columns.Add("Address", Type.GetType("System.String")); dt.Columns.Add("Salary", Type.GetType("System.Int32")); dt.Rows.Add(new object[] { null, "张一", "1980-01-01", "北京", 15000 }); dt.Rows.Add(new object[] { null, "张二", "1981-02-28", "上海", 20000 }); dt.Rows.Add(new object[] { null, "张三", "1982-03-18", "北京", 10000 }); dt.Rows.Add(new object[] { null, "张四", "1983-04-01", "河北", 5000 }); dt.Rows.Add(new object[] { null, "张五", "1984-05-14", "北京", 8000 }); dt.Rows.Add(new object[] { null, "李一", "1985-10-01", "广州", 11000 }); dt.Rows.Add(new object[] { null, "李二", "1986-09-07", "上海", 18000 }); dt.Rows.Add(new object[] { null, "李三", "1987-06-10", "北京", 20000 }); dt.Rows.Add(new object[] { null, "李四", "1988-04-01", "广州", 5000 }); dt.Rows.Add(new object[] { null, "李五", "1989-03-05", "北京", 7000 }); dt.Rows.Add(new object[] { null, "王一", "1983-01-09", "广州", 15000 }); dt.Rows.Add(new object[] { null, "王二", "1985-12-03", "上海", 30000 }); dt.Rows.Add(new object[] { null, "王三", "1987-08-22", "北京", 5000 }); dt.Rows.Add(new object[] { null, "王四", "1989-01-15", "河北", 3000 }); dt.Rows.Add(new object[] { null, "王五", "1989-05-20", "北京", 11000 }); //dgv.DataSource = dt; dgv.Dock = DockStyle.Fill; row_total = dt.Rows.Count; dv = dt.DefaultView; dgv.DataSource = dv; row_select = row_total; //禁止点击列标题自动排序 for (int i = 0; i < dgv.Columns.Count; i++) { dgv.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable; } pl_dgv_extend.Visible = false; toolStripStatusLabel1.Text = "按 ID 列升序排列"; toolStripStatusLabel2.Text = "在 " + row_total + " 条数据中找到 " + row_select + " 个"; toolStripStatusLabel3.Text = ""; }3、点击dgv列标题,panel显示,并根据列标题的不同位置,对应显示到相应的位置
private void dgv_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { int dLeft, dTop; //获取dgv列标题位置相对坐标 Rectangle range = dgv.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false); //计算pl_dgv_extend位置坐标 dLeft = range.Left + dgv.Left; dTop = range.Top + dgv.Top + range.Height; //设置pl_dgv_extend位置,超出框体宽度时,和dgv右边对齐 if (dLeft + pl_dgv_extend.Width > this.Width) { pl_dgv_extend.SetBounds(dgv.Width - pl_dgv_extend.Width, dTop, pl_dgv_extend.Width, pl_dgv_extend.Height); } else { pl_dgv_extend.SetBounds(dLeft, dTop, pl_dgv_extend.Width, pl_dgv_extend.Height); } //设置cb_condition下拉菜单内容 cb_condition.Items.Clear(); for (int i = 0; i < dgv.Rows.Count; i++) { bool isfind = false; for (int j = 0; j < cb_condition.Items.Count; j++) { if (cb_condition.Items[j].ToString() == dgv.Rows[i].Cells[e.ColumnIndex].Value.ToString()) { isfind = true; j = cb_condition.Items.Count;//break } } if (!isfind) { cb_condition.Items.Add(dgv.Rows[i].Cells[e.ColumnIndex].Value.ToString()); } } pl_dgv_extend.Visible = true; lb_columnname.Text = dgv.Columns[e.ColumnIndex].Name; //初始化选择项 cb_andor.SelectedIndex = 0; cb_operator.SelectedIndex = 0; cb_condition.Text = ""; //存储现有的筛选条件选项 if (ltb_condition.Items.Count == 0) { str_ltb = null; } else { str_ltb = new string[ltb_condition.Items.Count]; ltb_condition.Items.CopyTo(str_ltb, 0); } }4、升序降序代码
private void bt_asc_Click(object sender, EventArgs e) { dv.Sort = lb_columnname.Text + " asc"; toolStripStatusLabel1.Text = "按 " + lb_columnname.Text + " 列升序排列"; pl_dgv_extend.Visible = false; } private void bt_desc_Click(object sender, EventArgs e) { dv.Sort = lb_columnname.Text + " desc"; toolStripStatusLabel1.Text = "按 " + lb_columnname.Text + " 列降序排列"; pl_dgv_extend.Visible = false; }5、添加筛选条件
private void bt_add_Click(object sender, EventArgs e) { //空值判断 if (cb_operator.SelectedItem == null || cb_condition.Text.Trim() == "") { MessageBox.Show("请选择条件!"); return; } if (cb_andor.SelectedItem == null && ltb_condition.Items.Count > 0) { MessageBox.Show("请选择条件!"); return; } //文字转运算符 string str_andor = "", str_operator = ""; if (ltb_condition.Items.Count > 0) { if (cb_andor.SelectedItem == null) str_andor = ""; else if (cb_andor.SelectedItem.ToString() == "或") str_andor = "or "; else str_andor = "and "; } if (cb_operator.SelectedItem.ToString() == "等于") str_operator = "= "; else if (cb_operator.SelectedItem.ToString() == "大于") str_operator = "> "; else if (cb_operator.SelectedItem.ToString() == "大于等于") str_operator = ">= "; else if (cb_operator.SelectedItem.ToString() == "小于") str_operator = "< "; else if (cb_operator.SelectedItem.ToString() == "小于等于") str_operator = "<= "; else str_operator = "like "; //筛选条件添加到listbox if (cb_operator.SelectedItem.ToString() == "包含") { ltb_condition.Items.Add(str_andor + lb_columnname.Text + " " + str_operator + "'*" + cb_condition.Text.Trim() + "*'"); } else { ltb_condition.Items.Add(str_andor + lb_columnname.Text + " " + str_operator + "'" + cb_condition.Text.Trim() + "'"); } //初始化筛选条件 cb_andor.SelectedIndex = 0; cb_operator.SelectedIndex = 0; cb_condition.Text = ""; }6、移除筛选条件
private void bt_remove_Click(object sender, EventArgs e) { if (ltb_condition.SelectedItem == null) { MessageBox.Show("请选择需要移除的项!"); return; } int rownum = ltb_condition.SelectedIndex; ltb_condition.Items.RemoveAt(rownum); //如果移除了第一项并且移除后listbox项数目大于0 //把第一项开头的and或者or去掉 if (ltb_condition.Items.Count > 0 && rownum == 0) { string first = ltb_condition.Items[0].ToString(); string result; if (first.Substring(0, 2) == "or") { result = first.Substring(2, first.Length - 3); } else { result = first.Substring(3, first.Length - 4); } ltb_condition.Items.RemoveAt(0); ltb_condition.Items.Insert(0, result); } }7、清除所有筛选条件
private void bt_clear_Click(object sender, EventArgs e) { if (MessageBox.Show("是否要移除所有筛选条件?", "警告", MessageBoxButtons.YesNo) == DialogResult.Yes) { ltb_condition.Items.Clear(); } dv.RowFilter = ""; //清空筛选条件 pl_dgv_extend.Visible = false; row_select = row_total; toolStripStatusLabel2.Text = "在 " + row_total + " 条数据中找到 " + row_select + " 个"; toolStripStatusLabel3.Text = ""; }8、确认,执行筛选程序
private void bt_ok_Click(object sender, EventArgs e) { if (ltb_condition.Items.Count == 0) { dv.RowFilter = ""; toolStripStatusLabel3.Text = ""; } else { for (int i = 0; i < ltb_condition.Items.Count; i++) { if (i == 0) toolStripStatusLabel3.Text = ltb_condition.Items[0].ToString(); else toolStripStatusLabel3.Text += " " + ltb_condition.Items[i].ToString(); } dv.RowFilter = toolStripStatusLabel3.Text; } pl_dgv_extend.Visible = false; row_select = dv.Count; toolStripStatusLabel2.Text = "在 " + row_total + " 条数据中找到 " + row_select + " 个"; }9、取消,回滚操作
private void bt_cancle_Click(object sender, EventArgs e) {//回滚操作 ltb_condition.Items.Clear(); if (str_ltb != null) ltb_condition.Items.AddRange(str_ltb); pl_dgv_extend.Visible = false; }--------------------------------------------------
以上就是所有的代码了,新手,大家就将就着看吧。下面来看一下实际运行效果。
=========================================================
1、运行界面
2、点击列标题
3、点击边上的列标题,panel自动调整位置
4、按salary升序排列
5、填写筛选条件
6、填入两个条件
7、查询结果,在下方状态条显示筛选条目
8、多加一些条件
9、最终效果
注:由于toolStripStatusLabel的内容文字一旦超过最大宽度,该控件就会被隐藏,所以我把窗体拉长了点。至于怎么让它部分显示,没有查到。其实下面这个状态条完全可以用panel+label来实现,这样文字一旦超出label范围,就可以部分显示了。
/************************************************************* * * 来自于C#初学者——phoenix * 2015年5月22日 * http://blog.csdn.net/phoenix36999 * * **********************************************************/
用DataGridView实现Excel列的复杂筛选功能
时间: 2024-10-10 10:39:56
用DataGridView实现Excel列的复杂筛选功能的相关文章
DataGridView如何实现列标头带数据筛选功能,就象Excel高级筛选功能一样
'近日有本论坛网友问:DataGridView如何实现列标头带数据筛选功能,就象Excel高级筛选功能一样 '今晚正好闲着没事,加之以前也没用到过这个需求,所以就写了个模拟功能,供各位坛友酌情参考. 'VB.NET 2008 环境 '新建一个项目后,只需在Form1中拉一个DataGridView,一个ComboBox,然后将下面代码复制粘贴即可,其它什么也不用做 Public Class Form1 Dim SelectedCol As Integer = 0, IsFindit As Boo
NPOI DataGridView导出EXCEL
NPOI 官方网站 http://npoi.codeplex.com/ 加载NPOI.DLL ,引用这两个命名空间 using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; #region NPOI DataGridView 导出 EXCEL /// <summary> /// NPOI DataGridView 导出 EXCEL /// </summary> /// <param name="fileName"
Excel碰到空行无法筛选排序解决方法
Excel碰到空行无法筛选排序解决方法 有时候excel可真心考人智商,一列中有空行,那么你就只能筛选排序首个空行前的内容了,解决方法来了,做个小记录,以防今后忘了. 1.在首列插入一列: 2.全选该列输入1,使用快捷键"Ctrl+回车键"填充整列: 3.选择首行,点击"数据-->筛选-->自动筛选",现在可以全部筛选及排序了 Excel碰到空行无法筛选排序解决方法,布布扣,bubuko.com
Winform将DataGridView导出Excel,调用打印机打印DataGridView
DataGridView导出Excel (这个需要 Microsoft.Office.Interop.Excel.dll 在网上下载就可以) public static void ExportExcel(string fileName, DataGridView myDGV) { string saveFileName = ""; SaveFileDialog saveDialog = new SaveFileDialog(); saveDialog.DefaultExt = &qu
C# WinForm DataGridView 给标题列增加序号及格式化某个字段
DataGridView 给标题列增加序号 private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e) { DataGridViewTextBoxColumn dgv_Text = new DataGridViewTextBoxColumn(); for (int i = 0; i < dataGridView1.Rows.Count; i++) { i
pandas的筛选功能,跟excel的筛选功能类似,但是功能更强大。
Select rows from a DataFrame based on values in a column -pandas 筛选 https://stackoverflow.com/questions/17071871/select-rows-from-a-dataframe-based-on-values-in-a-column-in-pandas pandas的筛选功能,跟excel的筛选功能类似,但是功能更强大. 在SQL数据中, 我们可以用这样的语句: select * from
PHP:数字转Excel列头
转自我的个人博客:阔野飞花 http://www.rexcao.net/archives/169 前段时间升级一个项目的Excel导出功能,这次的列数大概有60多条,在处理过程中发现一个问题,原先做好的数字转Excel列头功能现在只到 AZ列就结束了,那显然是不够用啊,后来再仔细查看,发现,原来AZ列之后的内容显示到AAA列上面了,然后看了看原来的代码才发现,原来的逻辑错了! 我原来的错误逻辑是这样的:A-Z,Z下来是AA,AA-AZ,AZ下来是AAA,下来是AAAA依次类推...但是Excel
WinForm设置DataGridView某些行和列只读
WinForm设置DataGridView某些行和列的只读 列只读设置比较容易,行只读设置要求将SelectionMode设置为CellSelect,EditMode设置为EditOnEnter . '--DataGridView1控件的初始化设置(在数据绑定前设置,load事件中) Private Sub InitDataGrid1() Me.GridView1.ReadOnly = False '设置非只读 Me.GridView1.SelectionMode = DataGridViewS
根据Excel列类型获取列的值
using System.Data; using System.IO; using System.Text; using System.Web; using NPOI.SS.UserModel; using NPOI.HSSF.UserModel; namespace AIMSCommon { public class ExcelRender { /// <summary> /// 根据Excel列类型获取列的值 /// </summary> /// <param name=