none
Buscar en datagridview por clave primaria

    Question

  • Hola!

    ¿como puedo buscar un registro dentro de un datagridview por la clave primaria, siendo ésta de más de un campo?

    es que todos los ejemplos que he encontrado son para buscar por un campo (ejemplo, http://www.recursosvisualbasic.com.ar/htm/vb-net/52-buscar-fila-en-datagridview.htm) pero a mi no me vale porque tengo que buscar por 3 valores de la fila.

    También he visto la opción "select" del dataset que es justo lo que necesito, ya que ahí puedo construir la cadena de filtro que quiera. El problema en este caso es que yo necesito el indice de la fila del grid en la que está ese registro, y si he cambiado la ordenacion del grid (pulsando en el heather de una columna, por ejemplo) el indice del grid no va a coincidir con el indice del dataset.

    Lo ideal sería la propiedad "select" en el objeto grid. ¿existe eso? ¿alguna otra manera?

    Saludos y gracias de antemano
    Tuesday, November 03, 2009 10:38 AM

Answers

  • "JavierRomero" escribió:

    > Pues entendiste mal, jeje. Es exactamente lo que quiero

    ¡Pues sí! Seguramente no lo entendí bien, aunque a decir verdad, ya no sé lo que realmente deseas buscar, encontrar o hacer, porque si inicialmente preguntabas

    > ¿como puedo buscar un registro dentro de un datagridview por la
    > clave primaria, siendo ésta de más de un campo?

    Y después pasastes a decir:

    > no quiero filtrar los datos, simplemente quiero saber la fila
    > en la que está el elemento que busco.
    >
    > Por ejemplo, si yo tengo los artículos ordenados por codigo,
    > el dataset.rows(0). item("Codigo"). corresponderá al artículo 1.
    > Pero si me voy al datagrid y ordeno descendente, el
    > datagridview.rows(0).item("Codigo") me devolverá 999 y no el 1.

    Y ahora deseas:

    > Lo que quiero es situarme en la fila en la que está el elemento que busco:
    >
    > DataGrid.CurrentCell = DataGrid.Rows(X).Cells(0)
    >
    > siendo X la fila en la que se encuentra mi elemento.

    Pues ya no sabe uno a lo que atenerse. :-(

    Si es esto último lo que deseas hacer, tienes que recorrer todas las filas existentes en el control DataGridView para encontrar la fila que cumple con los valores que deseas buscar, tal y como muestra el siguiente ejemplo:

    Dim rowIndex As Int32 = 0
    
    For Each row As DataGridViewRow In DataGridView1.Rows
    
      ' Si el valor del campo es igual al valor del control TextBox, 
      ' abandonamos el bucle. 
      ' 
      If CInt(row.Cells("IdCliente").Value) = 4301034 Then Exit For
    
      rowIndex += 1
    
    Next
    
    ' Asignamos la propiedad CurrentCell 
    ' 
    DataGridView1.CurrentCell = DataGridView1.Item(0, rowIndex)
    
    ' Asignamos la propiedad FirstDisplayedCell 
    ' 
    DataGridView1.FirstDisplayedCell = DataGridView1.CurrentCell
    ¿Que deseas utilizar una consulta LINQ, como te comentó Leandro?

    Dim query As IEnumerable(Of DataGridViewRow) = _
    From item In DataGridView1.Rows.Cast(Of DataGridViewRow)() _
    Where CInt(item.Cells("IdCliente").Value) = 4301034 _
    Select item
    
    Dim row As DataGridViewRow = query.FirstOrDefault()
    
    If Not row Is Nothing Then
      ' Asignamos la propiedad CurrentCell 
      ' 
      DataGridView1.CurrentCell = DataGridView1.Item(0, row.Index)
    
      ' Asignamos la propiedad FirstDisplayedCell 
      ' 
      DataGridView1.FirstDisplayedCell = DataGridView1.CurrentCell
    
    End If


    ¡En fin! ¡Esperemos que sea ésto lo que deseas hacer! :-)




    Enrique Martínez [MS MVP - VB]
    Wednesday, November 04, 2009 3:08 PM
    Moderator

All replies

  • hola

    Para realizar la consulta a la db que tecnica estas utilizando?
    Me imagino por los ejemplos que proporcionas utilizas dataset tipados, o BindingSource.


    No has proebado realziar directamente el query usando los objetos de ado.net ?

    me refiero a crear tu propiea consulta sql del tipo

    SELECT * FROM <tabla> WHERE campo1 = @campo1 AND campo2=@campo2 AND campo3 = @campo3

    como veras los @ son parametros de tu consulta


    seria algo como esto

        Using cnn As New SqlConnection("<connection string>")

            Try

                Dim sql As String = "SELECT * FROM <table> WHERE campo1 = @campo1 AND campo2 = @campo2"


                Dim cmd As New SqlCommand(sql, cnn)


                cmd.Parameters.AddWithValue("@campo1", txtCampo1.Text)
                cmd.Parameters.AddWithValue("@campo2", txtCampo2.Text)

                cnn.Open()

                Dim reader As SqlDataReader = cmd.ExecuteReader

                If(reader.Read)
              
                    TextBox1.Text = Convert.ToString(reader("<campo>"))
                    TextBox2.Text = Convert.ToString(reader("<campo>"))
                    TextBox3.Text = Convert.ToString(reader("<campo>"))
              
                End If

            Catch ex As Exception
              
                MessageBox.Show(ex.Message)

            End Try

        End Using


    como veras por ahi es algo mas trabajoso, pero tienes control absoluto sobre la db, y como trabajarla

    ADO.NET  

    Recuperaci ó n y modificaci ó n de datos en ADO.NET



    te dejo algunos link qeue splcian como suar ado.net

    el tema aqui es que no estas realizando una consulta a tu grilla, sino que lo haces directo a tu db

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Tuesday, November 03, 2009 1:21 PM
  • Hola, Javier:

    ¿Qué es lo que te impide ejecutar el método Select del objeto DataTable asociado al control DataGridView?

    Imagina que deseas recuperar un cliente especificando su identificador de cliente:

            ' Referenciamos el objeto DataTable asociado
            ' al control DataGridView.
            '
            Dim dt As DataTable = DirectCast(DataGridView1.DataSource, DataTable)
    
            ' Recuperamos el registro cuyo identificador de
            ' cliente sea igual a 4300020
            '
            Dim rows() As DataRow = dt.Select("IdCliente = 4300020")
    
            ' Si hay alguna fila, referenciamos el primer objeto DataRow
            '
            If rows.Length > 0 Then
                Dim dr As DataRow = rows(0)
    
                ' Comprobamos el valor del campo IdCliente
                '
                MessageBox.Show(CStr(dr.Item("IdCliente")))
    
    
            End If
    
    


    Si el campo por donde deseas efectuar la búsqueda es alfanumérico, en el método Select tienes que encerrar su valor entre comillas simples.

    Se comprende que tienes el control DataGridView asociado a un objeto DataTable.

    Un saludo


    Enrique Martínez [MS MVP - VB]
    Tuesday, November 03, 2009 2:27 PM
    Moderator
  • hola

    Enrique lo que lo limita es que necesita aplicar un filtro por ms de un campo.

    en el ejemplo estas usando

    dt.Select("IdCliente = 4300020")

    pero me imagino que lo que busca es algo como ser

    dt.Select("IdCliente = 4300020 AND IdArticulo=150")

    la verdad nunca lo he probado pero por ahi con el AND funcione


    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Tuesday, November 03, 2009 2:34 PM
  • "Leandro Tuttini" escribió:

    > Enrique lo que lo limita es que necesita aplicar un filtro por ms de un campo.

    ¿Y dónde está el problema? Puede añadir varias condiciones al criterio de selección:

           Dim rows() As DataRow = _
                dt.Select("IdCliente = 4300020 AND " & _
                          "NombreCliente='PEPE GOTERA Y OTILIO, CHAPUZAS A DOMICILIO'")
    


    Pero me hubiese gustado más que, en lugar de decírselo claro, hubiera sido Javier el que se diese cuenta de ello. ;-)

    Enrique Martínez [MS MVP - VB]
    Tuesday, November 03, 2009 2:42 PM
    Moderator
  • hola

    ahh excelente si la verdad no estaba seguro si se podia armar expresiones compuesta en el metodo Select(), la verdad lo he usado muy poco, por eso no queria meter la pata recomendandolo.

    Pero veo que confirmas que se puede, por lo tanto creo que tendria la respuesta.

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Tuesday, November 03, 2009 3:09 PM
  • Hola de nuevo a los dos!

    por partes:

    -el datagridview lo lleno con un dataset, como bien indicais.

    -no quiero filtrar los datos, simplemente quiero saber la fila en la que está el elemento que busco. Por tanto, lo que dice Leandro de hacer el query filtrado no me sirve. Yo tengo un grid con 1000 elementos (por ejemplo) y quiero saber la posicion de uno, pero sin filtrar nada.

    -en cuanto a lo del "select" del objeto dataset, os confirmo que si se puede construir el where que se quiera, sea de un campo o de diez (lo he usado en ocasiones y funciona perferctamente). ¿por que no puedo usarlo? porque no me devuelve la fila en la que está posicionado el registro dentro del grid. Incluso aunque devolviera el indice dentro del dataset, no tiene porque coincidir con el datagrid. Por ejemplo, si yo tengo los artículos ordenados por codigo, el dataset.rows(0). item("Codigo"). corresponderá al artículo 1. Pero si me voy al datagrid y ordeno descendente, el datagridview.rows(0).item("Codigo") me devolverá 999 y no el 1. El indice del dataset y del datagridview no tienen porque ir parejos, y yo necesito el registro del grid poque quiero poner como fila seleccionada esa.

    Saludos y espero haberme explicado bien ahora!
    Tuesday, November 03, 2009 3:40 PM
  • > -en cuanto a lo del "select" del objeto dataset,

    Te refererías al "select" del objeto DATATABLE. Los objetos DataSet no tienen filas ni columnas. :-)

    > quiero saber la fila en la que está el elemento que busco.

    Si te dedicas a ordenar los registros del control DataGridView por una determinada columna y después por otra, los índices de las filas se renumeran, por lo que una fila tendrá un índice y después tendrá otro, como bien dices.

    ¿Como puedes obtener el ÍNDICE ORIGINAL que la fila tiene el objeto DataTable? Pues en estos momento ignoro cómo lo puedes obtener.

    En lugar del índice de la fila, ¿no te sirve el objeto DataRow, tal y como te he comentado en el ejemplo?

    ¿Para qué deseas obtener el índice de la fila?





    Enrique Martínez [MS MVP - VB]
    Tuesday, November 03, 2009 4:01 PM
    Moderator
  • hola

    si lo que necesitas es buscar un registro en la grilla directamente creo que en ese caso la forma simple seria usando un simple For Each por cada Row


    ahora bien tambien podrias utilziar linq

    algo como esto

            Dim query = From item In dataGridView1.Rows.Cast(Of DataGridViewRow)() _
                        Where item.Cells("Id").Value = txtFiltroNombreId.Text _
                            And item.Cells("Nombre").Value = txtFiltroNombre.Text _
                        Select item



            For Each item In query

                Console.WriteLine(item.Index)

            Next


    como veras Id y Nombre son dos columnas de la datagridview
    y luego en el for each puede consultar los indices de los registros devueltos

    o sino usar

    Dim row As DataGridViewRow = query.FirstOrDefault()

    para recuperar simpre uno solo y de este row entonces si el indice


    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Tuesday, November 03, 2009 5:34 PM
  • "Leandro Tuttini" escribió:

    > en el for each puede consultar los indices de los registros devueltos
    > o sino usar
    > Dim row As DataGridViewRow = query.FirstOrDefault()

    Ambas ejecuciones devolverán el índice de la fila del objeto DataGridView, que unas veces puede ser el índice 1 y otras el índice 256 ó 999, dependiendo de la columna por la que se encuentre ordenado el control DataGridView, y eso es precisamente lo que quiere evitar Javier, si he entendio bien su último mensaje, claro está. :-)



    Enrique Martínez [MS MVP - VB]
    Tuesday, November 03, 2009 5:51 PM
    Moderator
  • hola

    si mas que anda apuntaba a que puediera ahcer algo como esto}


    Dim query = From item In dataGridView1.Rows.Cast(Of DataGridViewRow)() _
                        Where item.Cells("Id").Value = txtFiltroNombreId.Text _
                            And item.Cells("Nombre").Value = txtFiltroNombre.Text _
                        Select item


    Dim row As DataGridViewRow  = query.FirstOrDefault()

    If Not row Is Nothing Then

       ' aqui puede recuperar el indice
        Dim indice As integer = row.Index

    End If


    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Tuesday, November 03, 2009 6:04 PM
  • "Leandro Tuttini" escribió:

    >    ' aqui puede recuperar el indice
    >    Dim indice As integer = row.Index

    Pero ese índice será el que tenga el objeto DataGridViewRow devuelto por la consulta LINQ, que repito, puede ser el 1, 256 ó 999. Es un índice variable dependiendo de la ordenación que tenga el control DataGridView.

    Salvo que yo esté equivocado o confundido, lo que yo me imagino que desea Javier es recuperar el índice que la fila tiene en el objeto DataTable al cual se encuentra enlazado el control DataGridView. Es decir, si un registro concreto tiene el índice 348 en el objeto DataTable, recuperar la fila del objeto DataGridView que tiene ese índice, el 348.

    Como la propiedad Index del objeto DataGridViewRow es variable, ¿cómo obtienes el índice 348 que tiene el cliente 4300020, si unas veces el control DataGridView está ordenado por la columna IdCliente y otras veces por la columna Domicilio?

    Yo, desde luego no sé para qué desea obtener el índice de la fila, cuando lo interesante sería referenciar el propio objeto DataRow que pertenece a un cliente X o Y. Teniendo el objeto DataRow, podemos acceder a los valores de los campos del objeto DataTable.

     


    Enrique Martínez [MS MVP - VB]
    Tuesday, November 03, 2009 6:17 PM
    Moderator


  • Ambas ejecuciones devolverán el índice de la fila del objeto DataGridView , que unas veces puede ser el índice 1 y otras el índice 256 ó 999 , dependiendo de la columna por la que se encuentre ordenado el control DataGridView, y eso es precisamente lo que quiere evitar Javier, si he entendio bien su último mensaje, claro está. :-)



    Enrique Martínez [MS MVP - VB]
    Pues entendiste mal, jeje. Es exactamente lo que quiero

    A ver si ahora me explico. Lo que quiero es situarme en la fila en la que está el elemento que busco:

    DataGrid.CurrentCell = DataGrid.Rows(X).Cells(0)

    siendo X la fila en la que se encuentra mi elemento. Por tanto, esté ordenado como esté, necesito el índice que tiene en ese momento. Por tanto, quizás me valga el código que pone Leandro. Lo pruebo y os digo algo.

    Gracias de nuevo!!

    Wednesday, November 04, 2009 8:13 AM
  • "JavierRomero" escribió:

    > Pues entendiste mal, jeje. Es exactamente lo que quiero

    ¡Pues sí! Seguramente no lo entendí bien, aunque a decir verdad, ya no sé lo que realmente deseas buscar, encontrar o hacer, porque si inicialmente preguntabas

    > ¿como puedo buscar un registro dentro de un datagridview por la
    > clave primaria, siendo ésta de más de un campo?

    Y después pasastes a decir:

    > no quiero filtrar los datos, simplemente quiero saber la fila
    > en la que está el elemento que busco.
    >
    > Por ejemplo, si yo tengo los artículos ordenados por codigo,
    > el dataset.rows(0). item("Codigo"). corresponderá al artículo 1.
    > Pero si me voy al datagrid y ordeno descendente, el
    > datagridview.rows(0).item("Codigo") me devolverá 999 y no el 1.

    Y ahora deseas:

    > Lo que quiero es situarme en la fila en la que está el elemento que busco:
    >
    > DataGrid.CurrentCell = DataGrid.Rows(X).Cells(0)
    >
    > siendo X la fila en la que se encuentra mi elemento.

    Pues ya no sabe uno a lo que atenerse. :-(

    Si es esto último lo que deseas hacer, tienes que recorrer todas las filas existentes en el control DataGridView para encontrar la fila que cumple con los valores que deseas buscar, tal y como muestra el siguiente ejemplo:

    Dim rowIndex As Int32 = 0
    
    For Each row As DataGridViewRow In DataGridView1.Rows
    
      ' Si el valor del campo es igual al valor del control TextBox, 
      ' abandonamos el bucle. 
      ' 
      If CInt(row.Cells("IdCliente").Value) = 4301034 Then Exit For
    
      rowIndex += 1
    
    Next
    
    ' Asignamos la propiedad CurrentCell 
    ' 
    DataGridView1.CurrentCell = DataGridView1.Item(0, rowIndex)
    
    ' Asignamos la propiedad FirstDisplayedCell 
    ' 
    DataGridView1.FirstDisplayedCell = DataGridView1.CurrentCell
    ¿Que deseas utilizar una consulta LINQ, como te comentó Leandro?

    Dim query As IEnumerable(Of DataGridViewRow) = _
    From item In DataGridView1.Rows.Cast(Of DataGridViewRow)() _
    Where CInt(item.Cells("IdCliente").Value) = 4301034 _
    Select item
    
    Dim row As DataGridViewRow = query.FirstOrDefault()
    
    If Not row Is Nothing Then
      ' Asignamos la propiedad CurrentCell 
      ' 
      DataGridView1.CurrentCell = DataGridView1.Item(0, row.Index)
    
      ' Asignamos la propiedad FirstDisplayedCell 
      ' 
      DataGridView1.FirstDisplayedCell = DataGridView1.CurrentCell
    
    End If


    ¡En fin! ¡Esperemos que sea ésto lo que deseas hacer! :-)




    Enrique Martínez [MS MVP - VB]
    Wednesday, November 04, 2009 3:08 PM
    Moderator
  • quizá no me expliqué bien, jeje

    aunque releyendo, lo que intentaba decir en todas era localizar una fila del grid

    >¿como puedo buscar un registro dentro de un datagridview por la clave primaria?


    >¿por que no puedo usarlo? porque no me devuelve la fila en la que está posicionado el registro dentro del grid . Incluso aunque devolviera el indice dentro del dataset, no tiene porque coincidir con el datagrid. Por ejemplo, si yo tengo los artículos ordenados por codigo, el dataset.rows(0).item("Codigo"). corresponderá al artículo 1. Pero si me voy al datagrid y ordeno descendente, el datagridview.rows(0).item("Codigo") me devolverá 999 y no el 1. El indice del dataset y del datagridview no tienen porque ir parejos, y yo necesito el registro del grid poque quiero poner como fila seleccionada esa.

    >A ver si ahora me explico. Lo que quiero es situarme en la fila en la que está el elemento que busco


    En fin, que parece que esta solucion si que me sirve, porque localizo la fila que quiero y con el current cell me pongo en ella. Lo pruebo y os digo si me funcionó...

    Gracias nuevamente por el interés!!

    Wednesday, November 04, 2009 3:38 PM
  • Repasa mi última respuesta porque acabo de añadir un ejemplo por si deseas ejecutar una consulta LINQ, tal y como te comentó Leandro Tuttini.

    No te olvides de marcar como satisfactorias aquellas respuestas que te hayan sido útiles. ¿OK?




    Enrique Martínez [MS MVP - VB]
    Wednesday, November 04, 2009 3:45 PM
    Moderator