none
¿Como realizar una búsqueda de datos desde una celda de un DataGridView y que me traiga los datos seleccionados en el mismo Grid? RRS feed

  • Pregunta

  • Buenos días a todos.

    Soy nuevo desarrollando en VB.NET y tengo el siguiente inconveniente.

    En un formulario tengo un DataGridView que no esta enlazado a ningún objeto de mi base de datos en SQL server.  La función de este control es enviar datos ingresados por el usuario a una tabla de la BD llamada "Detalle_Entrada_Insumos" mediante un botón "Crear".

    el control tiene las siguientes columnas: Referencia, Descripción, Cantidad, Unidad de Medida, Precio Unitario, Precio Total.

    En mi BD tengo una tabla principal llamada "Insumos" y contiene las referencias creadas previamente.

    lo que deseo hacer es, que al momento de que el usuario comience a digitar en las celdas Referencia o Descripción del DatagridView, me despliegue una lista con las referencias que coincidan y que estén creadas en la tabla "Insumos", al dar clic en la referencia que el usuario desee, me cargue automáticamente la información en las celdas "Referencia, Descripción, Unidad de Medida" de mi tabla "Insumos". Esto con el fin de que el usuario este seguro de que la referencia esta creada en la BD antes de realizar la entrada de la compra.

    Agradezco de antemano a todas las personas que deseen ayudarme en este inconveniente.

    jueves, 14 de abril de 2016 16:54

Respuestas

  • Hola,

    [-].... lo que deseo hacer es, que al momento de que el usuario comience a digitar en las celdas Referencia o Descripción del DatagridView, me despliegue una lista con las referencias que coincidan y que estén creadas en la tabla "Insumos"

    Puedes usar el evento EditingControlShowing del DataGridView para castear la celda a TextBox y crear una colecición para hacer el autocomplete mediante el AutoCompleteStringCollection.

    Algo así :

    Private Sub DataGridView1_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
    
            'Obtenemos el índice de la columna
            Dim columna As Integer = DataGridView1.CurrentCell.ColumnIndex
    
            'Convertimos la celda en un TextBox
            Dim txt As TextBox = DirectCast(e.Control, TextBox)
    
            'Agregamos los datos de la consulta
            txt.AutoCompleteCustomSource = autocompletar()
            txt.AutoCompleteSource = AutoCompleteSource.CustomSource
    
            'Validamos
            'Si es la primera columa (posición 0) mostramos los datos
            If columna = 0 Then
                txt.AutoCompleteMode = AutoCompleteMode.Suggest
            Else
                'Si es otra columna no autocompletamos
                txt.AutoCompleteMode = AutoCompleteMode.None
            End If
    
        End Sub

    En ese caso solo quiero autocompletar la primera columna, y desactivo el autocomplete de las otras columnas, o también puedes hacerlas de solo lecturas si no las vas a editar.

    El método :

     Public Function autocompletar() As AutoCompleteStringCollection
            Dim comando As SqlDataAdapter
            Dim dt As DataTable
            Dim misDatos As AutoCompleteStringCollection
    
            Using con As New SqlConnection("miCadenaDeConexión")
                comando = New SqlDataAdapter("SELECT DISTINCT NOMBRE FROM INSUMOS", con)
    
                dt = New DataTable()
    
                Try
                    comando.Fill(dt)
                    misDatos = New AutoCompleteStringCollection()
    
                    If dt.Rows.Count > 0 Then
                        For Each fila As DataRow In dt.Rows
                            misDatos.Add(Convert.ToString(fila("NOMBRE")))
                        Next
                    End If
    
                Catch ex As Exception
                    MessageBox.Show("Se produjo un error : " + ex.Message)
                    misDatos = Nothing
                End Try
    
                Return misDatos
    
            End Using
    
        End Function

    [-] Al dar clic en la referencia que el usuario desee, me cargue automáticamente la información en las celdas "Referencia, Descripción, Unidad de Medida" de mi tabla "Insumos". Esto con el fin de que el usuario este seguro de que la referencia esta creada en la BD antes de realizar la entrada de la compra.

    Eso puedes hacerlo mediante el evento CellEndEdit del DataGridView, obtienes el datos y haces una consulta a la base de datos, obteniendo los datos en un DataTable y asignándole los valores a las demás celdas.

    Aquí mostré un ejemplo como se hace esa consulta.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta Wilson Ardila viernes, 15 de abril de 2016 21:25
    jueves, 14 de abril de 2016 17:52
  • Hola,

    [-] Me gustaría que al mostrar la lista desplegable de las referencias, me mostrara también la descripción en la misma lista. ¿Tienes idea de como hacerlo?

    Puedes concatenar el valor en la consulta, para que te muestren registros compuesto, recuerda que el autocomplete comenzará a buscar las coincidencias desde el inicio.

         Using con As New SqlConnection("miCadenaDeConexión")
                comando = New SqlDataAdapter("SELECT CONCAT(MICAMPO1,' - ',MICAMPO2) AS RESULTADO FROM INSUMOS", con)
    
                dt = New DataTable()
    
                Try
                    comando.Fill(dt)
                    misDatos = New AutoCompleteStringCollection()
    
                    If dt.Rows.Count > 0 Then
                        For Each fila As DataRow In dt.Rows
                            misDatos.Add(Convert.ToString(fila("RESULTADO")))
                        Next
                    End If

    Donde al autocompletar te mostrará algo así :

    Con lo referente a la segunda pregunta.

    Qué error te muestra?, a simple vista veo que te equivocaste en esta parte.

    Dim tabla As DataTable = ds.Tables(1)

    Debes tomar la tabla 0 del DataSet (ds.Tables(0)), ya que los indices siempre comienzan de cero.

    Por otro lado,

     comando = New SqlDataAdapter("select * from Insu.....

    Recomendación : Si solo tomas dos valores, deberías especificarlas en tu consulta, para que cuando asignes los valores no lo hagas salteando columnas, como lo haces en este código, así evitas traer columnas que no usarás.

                    DataGridView1.Rows(indiceFila).Cells(2).Value = Convert.ToString(tabla(0)(2))
                    DataGridView1.Rows(indiceFila).Cells(4).Value = Convert.ToString(tabla(0)(4))

    Estoy pendiente a cualquier duda.

    Saludos.




    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta Wilson Ardila viernes, 15 de abril de 2016 21:25
    viernes, 15 de abril de 2016 4:04
  • Hola,

    Como ahora tienes un resultado compuesta en tu AutoComplete, tienes que extraer el primer valor, el cual será el mismo que se enviará a la función para obtener los resultados.

    Private Sub DataGridView1_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
    
            'Indice de la columna 
            If e.ColumnIndex = 0 Then
    
                Dim valorCelda As String = Convert.ToString(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value)
    
                'Obtengo un array de String, según el separador
                'En este caso lo divide en dos partes
                Dim resultado As String() = valorCelda.Split("-")
    
    
                'Asigno el nuevo valor a la celda (para que no me muestre todo)
                DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = resultado(0)
    
                'Le pongo el Trim para que me borre los espacios en blanco
                rellenarFila(resultado(0).Trim, e.RowIndex)
    
            End If
    
        End Sub

    Resultado :

    [-] ¿No hay posibilidad que la lista desplegable se auto ajuste al ancho de la cadena de caracteres mas larga?

    Me parece que no.

    La lista tomará el tamaño de la celda, puedes establecerla la columna con un tamaño por defecto.

    En sí no he encontrado la manera de que se adapte al tamaño máximo.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta Wilson Ardila viernes, 15 de abril de 2016 21:25
    viernes, 15 de abril de 2016 19:41

Todas las respuestas

  • Hola,

    [-].... lo que deseo hacer es, que al momento de que el usuario comience a digitar en las celdas Referencia o Descripción del DatagridView, me despliegue una lista con las referencias que coincidan y que estén creadas en la tabla "Insumos"

    Puedes usar el evento EditingControlShowing del DataGridView para castear la celda a TextBox y crear una colecición para hacer el autocomplete mediante el AutoCompleteStringCollection.

    Algo así :

    Private Sub DataGridView1_EditingControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
    
            'Obtenemos el índice de la columna
            Dim columna As Integer = DataGridView1.CurrentCell.ColumnIndex
    
            'Convertimos la celda en un TextBox
            Dim txt As TextBox = DirectCast(e.Control, TextBox)
    
            'Agregamos los datos de la consulta
            txt.AutoCompleteCustomSource = autocompletar()
            txt.AutoCompleteSource = AutoCompleteSource.CustomSource
    
            'Validamos
            'Si es la primera columa (posición 0) mostramos los datos
            If columna = 0 Then
                txt.AutoCompleteMode = AutoCompleteMode.Suggest
            Else
                'Si es otra columna no autocompletamos
                txt.AutoCompleteMode = AutoCompleteMode.None
            End If
    
        End Sub

    En ese caso solo quiero autocompletar la primera columna, y desactivo el autocomplete de las otras columnas, o también puedes hacerlas de solo lecturas si no las vas a editar.

    El método :

     Public Function autocompletar() As AutoCompleteStringCollection
            Dim comando As SqlDataAdapter
            Dim dt As DataTable
            Dim misDatos As AutoCompleteStringCollection
    
            Using con As New SqlConnection("miCadenaDeConexión")
                comando = New SqlDataAdapter("SELECT DISTINCT NOMBRE FROM INSUMOS", con)
    
                dt = New DataTable()
    
                Try
                    comando.Fill(dt)
                    misDatos = New AutoCompleteStringCollection()
    
                    If dt.Rows.Count > 0 Then
                        For Each fila As DataRow In dt.Rows
                            misDatos.Add(Convert.ToString(fila("NOMBRE")))
                        Next
                    End If
    
                Catch ex As Exception
                    MessageBox.Show("Se produjo un error : " + ex.Message)
                    misDatos = Nothing
                End Try
    
                Return misDatos
    
            End Using
    
        End Function

    [-] Al dar clic en la referencia que el usuario desee, me cargue automáticamente la información en las celdas "Referencia, Descripción, Unidad de Medida" de mi tabla "Insumos". Esto con el fin de que el usuario este seguro de que la referencia esta creada en la BD antes de realizar la entrada de la compra.

    Eso puedes hacerlo mediante el evento CellEndEdit del DataGridView, obtienes el datos y haces una consulta a la base de datos, obteniendo los datos en un DataTable y asignándole los valores a las demás celdas.

    Aquí mostré un ejemplo como se hace esa consulta.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta Wilson Ardila viernes, 15 de abril de 2016 21:25
    jueves, 14 de abril de 2016 17:52
  • Hola JC NaupaCrispín.

    Muchas gracias por la pronta ayuda

    Incorpore la primera parte del código que dejaste y me funciono perfecto, me muestra la lista desplegable con las referencias creadas de la tabla "Insumos".

    Me gustaría que al mostrar la lista desplegable de las referencias, me mostrara también la descripción en la misma lista. ¿Tienes idea de como hacerlo?

    Por otro lado, fui al link que dejaste para la segunda parte y adapte el código para mi proyecto, pero al ejecutarlo me muestra un error, el cual no he podido solucionar y sigo sin que me cargue la información que necesito en las celdas "Descripción" y "Unidad de Medida"

    Aquí dejo los dos bloques de código para que me hagas el grande favor y me expliques donde estoy fallando. 

    Código del evento CellEndEdit del DGV

    Private Sub DataGridView1_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
    
            'Indice de la columna 
            If e.ColumnIndex = 1 Then
    
                Dim valor As String = Convert.ToString(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value)
    
                'Mandamos el valor y el índice de la fila
                rellenarFila(valor, e.RowIndex)
    
            End If
          
    
        End Sub

    Código del método

    Public Sub rellenarFila(ByVal valor As String, ByVal indiceFila As Integer)
    
            Dim comando As SqlDataAdapter
            Dim ds As DataSet
            Dim consulta As String = String.Empty
    
            cn = New SqlConnection(My.Settings.Conexion)
            comando = New SqlDataAdapter("select * from Insumos WHERE IN_idinsumo = ''" + valor + "", cn)
    
            ds = New DataSet()
    
            Try
                'Llenado del Dataset
                comando.Fill(ds)
    
                Dim tabla As DataTable = ds.Tables(1)
    
                'Si solo devuelve una fila
                'Tomamos sus valores
    
                If tabla.Rows.Count = 1 Then
    
                    'Agregamos los datos a la misma fila
                   
                    DataGridView1.Rows(indiceFila).Cells(2).Value = Convert.ToString(tabla(0)(2))
                    DataGridView1.Rows(indiceFila).Cells(4).Value = Convert.ToString(tabla(0)(4))
    
    
                    'tabla(0)(1) -> tabla(fila)(columna)
                End If
    
            Catch ex As Exception
                MessageBox.Show("Se produjo un error : " & ex.Message)
            End Try
    
        End Sub
    Nuevamente gracias por su valiosa colaboración y el valioso tiempo que me puedas dedicar.

    viernes, 15 de abril de 2016 0:55
  • Hola,

    [-] Me gustaría que al mostrar la lista desplegable de las referencias, me mostrara también la descripción en la misma lista. ¿Tienes idea de como hacerlo?

    Puedes concatenar el valor en la consulta, para que te muestren registros compuesto, recuerda que el autocomplete comenzará a buscar las coincidencias desde el inicio.

         Using con As New SqlConnection("miCadenaDeConexión")
                comando = New SqlDataAdapter("SELECT CONCAT(MICAMPO1,' - ',MICAMPO2) AS RESULTADO FROM INSUMOS", con)
    
                dt = New DataTable()
    
                Try
                    comando.Fill(dt)
                    misDatos = New AutoCompleteStringCollection()
    
                    If dt.Rows.Count > 0 Then
                        For Each fila As DataRow In dt.Rows
                            misDatos.Add(Convert.ToString(fila("RESULTADO")))
                        Next
                    End If

    Donde al autocompletar te mostrará algo así :

    Con lo referente a la segunda pregunta.

    Qué error te muestra?, a simple vista veo que te equivocaste en esta parte.

    Dim tabla As DataTable = ds.Tables(1)

    Debes tomar la tabla 0 del DataSet (ds.Tables(0)), ya que los indices siempre comienzan de cero.

    Por otro lado,

     comando = New SqlDataAdapter("select * from Insu.....

    Recomendación : Si solo tomas dos valores, deberías especificarlas en tu consulta, para que cuando asignes los valores no lo hagas salteando columnas, como lo haces en este código, así evitas traer columnas que no usarás.

                    DataGridView1.Rows(indiceFila).Cells(2).Value = Convert.ToString(tabla(0)(2))
                    DataGridView1.Rows(indiceFila).Cells(4).Value = Convert.ToString(tabla(0)(4))

    Estoy pendiente a cualquier duda.

    Saludos.




    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta Wilson Ardila viernes, 15 de abril de 2016 21:25
    viernes, 15 de abril de 2016 4:04
  • Hola JC NaupaCrispín.

    ¡Perfecto!, me funciona bien. el error lo tenia efectivamente en esto:

    Dim tabla As DataTable = ds.Tables(1)

    Era el indice 0, también tenia error en la consulta a la base de datos. ya quedó solucionado y me está cargando la información en las celdas que necesito. 

    Pero ahora tengo un pequeño inconveniente en la lista despegable, efectivamente aparece el formato "P0001 - Producto 1". Pero al hacer clic con el mouse en la referencia que voy a tomar, me carga en la celda toda la información: (P0001 - Producto 1) y por supuesto te imaginaras que no me carga los datos en las siguientes dos columnas porque no lo encuentra en la base de datos así.

    Teniendo en cuenta lo anterior, si necesito que me muestre la lista desplegable de esa manera pero que al hacer clic con el mouse me cargue únicamente la referencia.

    También que cuando salga la lista desplegable se alcance a leer toda la cadena, porque solo se ve la referencia, la descripción queda oculta hasta que el usuario la arrastra con el mouse. ¿No hay posibilidad que la lista desplegable se auto ajuste al ancho de la cadena de caracteres mas larga?

    si me pudieras ayudar con esto quedaría eternamente agradecido y te prometo que sería lo último.

    muchas gracias..

    viernes, 15 de abril de 2016 17:57
  • Hola,

    Como ahora tienes un resultado compuesta en tu AutoComplete, tienes que extraer el primer valor, el cual será el mismo que se enviará a la función para obtener los resultados.

    Private Sub DataGridView1_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
    
            'Indice de la columna 
            If e.ColumnIndex = 0 Then
    
                Dim valorCelda As String = Convert.ToString(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value)
    
                'Obtengo un array de String, según el separador
                'En este caso lo divide en dos partes
                Dim resultado As String() = valorCelda.Split("-")
    
    
                'Asigno el nuevo valor a la celda (para que no me muestre todo)
                DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value = resultado(0)
    
                'Le pongo el Trim para que me borre los espacios en blanco
                rellenarFila(resultado(0).Trim, e.RowIndex)
    
            End If
    
        End Sub

    Resultado :

    [-] ¿No hay posibilidad que la lista desplegable se auto ajuste al ancho de la cadena de caracteres mas larga?

    Me parece que no.

    La lista tomará el tamaño de la celda, puedes establecerla la columna con un tamaño por defecto.

    En sí no he encontrado la manera de que se adapte al tamaño máximo.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta Wilson Ardila viernes, 15 de abril de 2016 21:25
    viernes, 15 de abril de 2016 19:41
  • Hola JC NaupaCrispín.

    Funciona excelente gracias a tu ayuda. Ya llevaba casi una semana intentando de una u otra forma y nada, hasta que decidí inscribirme en este foro pensando en que tal vez nadie me podría ayudar.

    De corazón agradezco el tiempo dedicado a mi asunto y pues bueno, si durante el desarrollo del proyecto que estoy realizando encuentro otro inconveniente, no dudaré en escribir nuevamente. Claro está, si no es mucha molestia.

    Nuevamente gracias y te deseo mucho éxito en tu vida personal y profesional.

    Saludos,

    viernes, 15 de abril de 2016 21:24
  • HOLA PERO SI QUIERO AGREGAR DATOS A OTRAS DIOS COLUMNAS COMO SE TENDRÍAN QUE DEFINIR
    domingo, 23 de junio de 2019 0:07