lunes, 22 de marzo de 2010

Filtrar un control DatagridView

Código de ejemplo realizado en vb.net 2005 para filtrar un control BindingSource y luego enlazarlo a un DatagridView

En el ejemplo primero se conecta a un base de datos x de sql server para obtener todos los registros de una tabla en un objeto DataTable.
Luego se enlaza ese objeto DataTable que tiene los datos de la tabla a un componente BindingSource.
Por último , se utiliza la propiedad Filter del BindingSource para filtrar los datos por un determinado campo, y una ves filtrado se enlaza al DatagridView para visualizar los registros

Controles para el ejemplo

  • Añadir un control DataGridView : DataGridView1
  • Un control TextBox para escribir el valor
  • Un Combo para la opción del filtro
  • Indicar la cadena de conexión
  • ( Espacio de nombres usado : System.Data.SqlClient para acceder al cliente de sql )

Nota: establecer en el primer parámetro de la subRutina Filtrar_DatagridView, el nombre del campo por el cual filtrar ( debe ser un campo de tipo texto )
Código fuente

Option Explicit On
Option Strict On

' espacio de nombres para poder acceder al cliente sql
Imports System.Data
Imports System.Data.SqlClient

Public Class Form1

' enumeración para las opciones que se usarán
' para filtrar con el operador Like
Enum e_FILTER_OPTION
SIN_FILTRO = 0
CADENA_QUE_COMIENCE_CON = 1
CADENA_QUE_NO_COMIENCE_CON = 2
CADENA_QUE_CONTENGA = 3
CADENA_QUE_NO_CONTENGA = 4
CADENA_IGUAL = 5
End Enum

' cadena de conexión para SQL EXPRESS en modo local
Private Const cs As String = "Data Source=(local)\SQLEXPRESS;" & _
"Integrated Security=True;" &"Initial Catalog=la_base_de_datos"

'Instanciar el componente BindingSource
Private BindingSource1 As Windows.Forms.BindingSource = New BindingSource

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load


Try
' Inicializar la conexión y abrir
Using cn As SqlConnection = New SqlConnection(cs)
cn.Open()

' Inicializar DataAdapter indicando el sql para recuperar
'los registros de la tabla
Dim da As New SqlDataAdapter("SELECT * FROM la_tabla", cn)
Dim dt As New DataTable ' crear un DataTable

' llenarlo
da.Fill(dt)

' enlazar el DataTable al BindingSource
BindingSource1.DataSource = dt

' agregar las opciones al combobox
With (ComboBox1)

'cargar los items de opciones para filtrar
.Items.Add("No filtrar")
.Items.Add("Que comience con")
.Items.Add("Que No comience con")
.Items.Add("Que contenga")
.Items.Add("Que No contenga")
.Items.Add("Que sea igual")

.DropDownStyle = ComboBoxStyle.DropDownList
.SelectedIndex = 1
End With
End Using
' errores
Catch ex As Exception
MsgBox(ex.Message.ToString)
End Try
End Sub


Private Sub Aplicar_Filtro()

' filtrar por el campo Producto
''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim ret As Integer = Filtrar_DataGridView( _
"Producto",TextBox1.Text.Trim, _
BindingSource1,DataGridView1, _
CType(ComboBox1.SelectedIndex, e_FILTER_OPTION))

If ret = 0 Then
' si no hay registros cambiar el color del txtbox
TextBox1.BackColor = Color.Red
Else
TextBox1.BackColor = Color.White
End If
' visualizar la cantidad de registros
Me.Text = ret & " Registros encontrados"

End Sub

Function Filtrar_DataGridView( _
ByVal Columna As String,ByVal texto As String, _
ByVal BindingSource As BindingSource, _
ByVal DataGridView As DataGridView, _
Optional ByVal Opcion_Filtro As e_FILTER_OPTION = Nothing) As Integer

' verificar que el DataSource no esté vacio
If BindingSource1.DataSource Is Nothing Then
Return 0
End If

Try

Dim filtro As String = String.Empty

' Seleccionar la opción
Select Case Opcion_Filtro
Case e_FILTER_OPTION.CADENA_QUE_COMIENCE_CON
filtro = "like '" & texto.Trim & "%'"
Case e_FILTER_OPTION.CADENA_QUE_NO_COMIENCE_CON
filtro = "Not like '" & texto.Trim & "%'"
Case e_FILTER_OPTION.CADENA_QUE_NO_CONTENGA
filtro = "Not like '%" & texto.Trim & "%'"
Case e_FILTER_OPTION.CADENA_QUE_CONTENGA
filtro = "like '%" & texto.Trim & "%'"
Case e_FILTER_OPTION.CADENA_IGUAL
filtro = "='" & texto.Trim & "'"
End Select
' Opción para no filtrar
If Opcion_Filtro = e_FILTER_OPTION.SIN_FILTRO Then
filtro = String.Empty
End If

' armar el sql
If filtro <> String.Empty Then
filtro = "[" & Columna & "]" & filtro
End If

' asigar el criterio a la propiedad Filter del BindingSource
BindingSource.Filter = filtro
' enlzar el datagridview al BindingSource
DataGridView.DataSource = BindingSource.DataSource

' retornar la cantidad de registros encontrados
Return BindingSource.Count

' errores
Catch ex As Exception
MsgBox(ex.Message.ToString, MsgBoxStyle.Critical)
End Try

Return 0

End Function

Private Sub txt_Filtro_TextChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles textbox1.TextChanged

Aplicar_Filtro()

End Sub
End Class

El mismo ejemplo pero para filtrar un campo de tipo numérico
Código fuente con los mismos controles
( Nota : Indicar el nombre del campo )
Option Explicit On
Option Strict On

Imports System.Data
Imports System.Data.SqlClient

Public Class Form1
Enum e_FILTER_OPTION
SIN_FILTRO = 0
NUMERICO_MENOR = 1
NUMERICO_MAYOR = 2
NUMERICO_MENOR_IGUAL = 3
NUMERICO_MAYOR_IGUAL = 4
NUMERICO_IGUAL = 5
NUMERICO_DISTINTO = 6
End Enum

Private Const cs As String = "Data Source=(local)\SQLEXPRESS;" & _
"Integrated Security=True;" &"Initial Catalog=la_base_de_datos"

'Instanciar el componente BindingSource
Private BindingSource1 As Windows.Forms.BindingSource = New BindingSource

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load


Try

Using cn As SqlConnection = New SqlConnection(cs)
cn.Open()

Dim da As New SqlDataAdapter("SELECT * FROM la_tabla", cn)
Dim dt As New DataTable

da.Fill(dt)


BindingSource1.DataSource = dt
With (ComboBox1)
.Items.Add("No filtrar")
.Items.Add("Menor")
.Items.Add("Mayor")
.Items.Add("Menor o igual")
.Items.Add("Mayor o igual")
.Items.Add("Igual")
.Items.Add("Distinto")

.DropDownStyle = ComboBoxStyle.DropDownList
.SelectedIndex = 1
End With
End Using
Catch ex As Exception
MsgBox(ex.Message.ToString)
End Try
End Sub


Private Sub filtrar()

' filtrar por el campo Id de tipo numérico
''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim ret As Integer = Filtrar_DataGridView( _
"Id",TextBox1.Text.Trim,BindingSource1, _
DataGridView1,CType(ComboBox1.SelectedIndex, e_FILTER_OPTION))

If ret = 0 Then
TextBox1.BackColor = Color.Red
Else
TextBox1.BackColor = Color.White
End If
Me.Text = ret & " Registros encontrados"

End Sub

Function Filtrar_DataGridView( _
ByVal Columna As String,ByVal dato As String, _
ByVal BindingSource As BindingSource,ByVal DataGridView As DataGridView, _
Optional ByVal Opcion_Filtro As e_FILTER_OPTION = Nothing) As Integer
If BindingSource1.DataSource Is Nothing Then
Return 0
End If

Try

Dim filtro As String = String.Empty

' Seleccionar la opción
Select Case Opcion_Filtro
Case e_FILTER_OPTION.NUMERICO_MENOR
filtro = "< " & dato.Trim & ""
Case e_FILTER_OPTION.NUMERICO_MAYOR
filtro = "> " & dato.Trim & ""
Case e_FILTER_OPTION.NUMERICO_MENOR_IGUAL
filtro = "<= " & dato.Trim & ""
Case e_FILTER_OPTION.NUMERICO_MAYOR_IGUAL
filtro = ">= " & dato.Trim & ""
Case e_FILTER_OPTION.NUMERICO_IGUAL
filtro = "= " & dato.Trim & ""
Case e_FILTER_OPTION.NUMERICO_DISTINTO
filtro = "<> " & dato.Trim & ""
End Select

' Sin filtro
If Opcion_Filtro = e_FILTER_OPTION.SIN_FILTRO Or Not IsNumeric(dato.Trim) Then
filtro = String.Empty
End If

If filtro <> String.Empty Then
filtro = "[" & Columna & "]" & filtro
End If

BindingSource.Filter = filtro

DataGridView.DataSource = BindingSource.DataSource
Return BindingSource.Count

Catch ex As Exception
MsgBox(ex.Message.ToString, MsgBoxStyle.Critical)
End Try

Return 0

End Function

Private Sub txt_Filtro_TextChanged( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles TextBox1.TextChanged

filtrar()

End Sub

Private Sub Combo1_SelectedIndexChanged( _
ByVal sender As System.Object,ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
filtrar()
End Sub
End Class


Nota: si se quiere filtrar por varios campos, se debe indicar al filter la condición por ejemplo de la siguiente manera.
BindingSource .Filter = "[nombre Producto] = 'Nombre' And [Precio] <= 500"

Donde los campos de tipo texto deben ir encerrados entre comillas simples.

No hay comentarios:

Publicar un comentario