none
Métodos de DataGridView para validar el ingreso de datos contra una base de datos y enfocar en una celda determinada RRS feed

  • Pregunta

  • Hola.

    Tengo un formulario con un dataGridView donde tengo que ingresar cuentas contables en las celdas de la primera columna, necesito que cuando el usuario ingrese al cuenta contable y de enter o pulse tab este ejecuta una función donde se busque, si no se encuentra coincidencia este no abandone la celda, si lo encuentra el método buscar devuelve la descripción de la cuenta, quiero ponerla esta en la celda siguiente y que la tercera celda obtenga el encoque.

    Estaba intentando con el evento CellValidating, pero tengo problemas hay momentos en que se manda a la funcion buscar el valor antes digitado y no el valor actual de la celda.

    Que métodos y eventos debo tener en cuenta para conseguir lo mencionado.

    Saludos.

    Mauricio
    lunes, 14 de agosto de 2017 3:46

Respuestas

  • No es una tarea complicada, sólo considerar el orden de los eventos. Te dejo un ejemplo simple, revisalo y efectúa los cambios que consideres oportunos (entiendo que la forma como se consulta y recupera los datos no es asunto del hilo que expones).

    Private IsValidating As Boolean = False
    
    Private Sub DataGridView1_CellValidating(sender As Object, e As ...
    
    	Dim dgv = TryCast(sender, DataGridView)
    
    	'Actuar para la columna 'ColCuentaCorriente' cuando se haya ingresado un valor
    	If dgv.Columns(e.ColumnIndex).Name = "ColCuentaContable" AndAlso
    			e.FormattedValue.ToString <> String.Empty Then
    		'Llamar a la función 'GetCuentaContable' con el valor escrito en la celda
    		Dim Datos = GetCuentaContable(e.FormattedValue.ToString())
    		'¿Qué retorna la función 'GetCuentaContable'?
    		If Datos IsNot Nothing Then
    			e.Cancel = False
    
    			'Asignar valor a la siguiente columna
    			dgv("Column2", e.RowIndex).Value = Datos
                            'Salimos del controlador del evento CellValidating
    			Return
    		End If
    
    		'Si la función 'GetCuentaContable' retorna Nothing la cuenta contable no existe
    		dgv.Rows(e.RowIndex).ErrorText = "Cuenta contable no existe"
    		e.Cancel = True
    	End If
    
    End Sub
    
    Private Sub DataGridView1_CellValidated(sender As Object, e As ...
    
    	TryCast(sender, DataGridView).Rows(e.RowIndex).ErrorText = String.Empty
    
    	IsValidating = False
    
    End Sub
    
    Private Sub DataGridView1_CellEndEdit(sender As Object, e As ...
    
    	Dim dgv = TryCast(sender, DataGridView)
    
    	'Actuar para la columna 'ColCuentaCorriente' siempre y cuando exista un valor
    	If dgv.Columns(e.ColumnIndex).Name = "ColCuentaContable" AndAlso
    		Convert.ToString(dgv(e.ColumnIndex, e.RowIndex).Value) <> String.Empty Then
    		'Otorgar foco a la subsiguiente columna
    		dgv.CurrentCell = CType(sender, DataGridView)("Column3", e.RowIndex)
    		dgv.BeginEdit(True)
    
    		IsValidating = True
    	End If
    
    End Sub
    
    Private Sub DataGridView1_RowValidating(sender As Object, e As ...
    
    	e.Cancel = IsValidating
    
    End Sub

    - Resultado


    Nuestra profesión exige tener pasión por resolver problemas de una manera óptima y eficiente.
    • Marcado como respuesta mpulla jueves, 17 de agosto de 2017 23:38
    martes, 15 de agosto de 2017 18:35

Todas las respuestas

  • No me queda claro donde da el enter en un Textbox?  y si el DataGridView ya tiene datos o los tienes almacenados en un DataTabel a la espera de la busqueda. Si puedes amplia más el requerimiento

    Slaudos

    lunes, 14 de agosto de 2017 4:01
  • Hola Marcelo.

    El DataGridView, no tiene datos los va ingresando el usuario, en la celda de la primera columna el usuario ingresa el código contable, cuando termina da enter o tab ese momento necesito validar que contra la db, si existe datos el metodo de busqueda los devuelve para llenar la siguiente celda y enfocar en la tercera celda, caso contrario muestra el mensaje que no existe y permanece en la misma celda.

    Necesito controlar esto, tengo problemas con el evento CellValidating donde tengo el código.

    Que metodos y eventos necesito controlar, puedes ayudarme con algún ejemplo.

    Saludos.

    Mauricio

    lunes, 14 de agosto de 2017 5:56
  • No me olvide de ti he, el tema se complica si se efectua la busqueda desde el mismo datagridview. Pregunta y si utilizas la busqueda en un textbox y de allí efecuta la carga? algo similar a esto

    https://social.msdn.microsoft.com/Forums/es-ES/707220ca-8376-4968-9dd9-ec97b96f2f98/buscador-en-un-datagridview?forum=vbes

    Pero en tu caso efecuaría la busqueda contra  DataTable o directamente contra la bd, que supongo ya lo debes tener

    Saludos sigo viendo


    • Editado Marcelo PF lunes, 14 de agosto de 2017 22:07
    lunes, 14 de agosto de 2017 22:04
  • Hola Marcelo.

    Ya reviso el link.

    La busqueda la hago contra la db y es postgres, me conecto via odbc.

    Saludos.

    Mauricio

    lunes, 14 de agosto de 2017 22:58
  • Te digo mi idea, supongo que si te conectas con odbc no tendras problemas en generar un adaptador y una DataTable, de allí parto yo, en el load del formulario cargo la Tabla

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load '...Aquí deberías tener la conexión y los datos en el Adapter ........>> Tabla = New DataTable DatAdapter.Fill(Tabla) If Tabla.Rows.Count > 0 Then no = True End If TextBox5.Text = TextBox5.Tag 'El Tag = "Ingrese el número del registro

    Dgv.EditMode = DataGridViewEditMode.EditOnEnter End Sub

    A nivel formulario declaro

      Public no As Boolean = False
        Public borrar As Boolean = False
        Public r As Integer = 0
        Public c As Integer = 0

    un button buscar

     Private Sub Button10_Click(sender As Object, e As EventArgs) Handles Button10.Click
            borrar = False
            If no = False Then
                MsgBox("La tabla no tienen valores")
                Exit Sub
            End If
            Dim a As String = TextBox5.Text
                For i As Integer = 0 To Tabla.Rows.Count - 1
    
    
                    If Convert.ToString(Tabla.Rows(i).Item(0)) = a Then
                        Dgv.Rows.Add()
                        Dgv.Rows(c).Cells(0).Value = Tabla.Rows(i).Item(0)
                        Dgv.Rows(c).Cells(0 + 1).Value = Tabla.Rows(i).Item(1)
                        Dgv.ClearSelection()
                        Dgv.Focus()
                        Dgv.Rows(c).Cells(0 + 2).Selected = True
                        c = c + 1
                        TextBox5.Text = TextBox5.Tag
                        Exit For
                    Else
                        TextBox5.Text = "Registro no encontrado"
                    End If
                Next
        End Sub

    Un textbox, en el evento KeyPress

      Private Sub TextBox5_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TextBox5.KeyPress
            If Asc(e.KeyChar) = 13 Then
                borrar = False
                If no = False Then
                    MsgBox("La tabla no tienen valores")
                    Exit Sub
                End If
                Dim a As String = TextBox5.Text
                For i As Integer = 0 To Tabla.Rows.Count - 1
    
    
                    If Convert.ToString(Tabla.Rows(i).Item(0)) = a Then
                        Dgv.Rows.Add()
                        Dgv.Rows(c).Cells(0).Value = Tabla.Rows(i).Item(0)
                        Dgv.Rows(c).Cells(0 + 1).Value = Tabla.Rows(i).Item(1)
                        Dgv.ClearSelection()
                        Dgv.Focus()
                        Dgv.Rows(c).Cells(0 + 2).Selected = True
                        c = c + 1
                        TextBox5.Text = TextBox5.Tag
                        Exit For
                    Else
                        TextBox5.Text = "Registro no encontrado"
                    End If
                Next
    
            Else
                If borrar = False Then
                    TextBox5.Text = ""
                    borrar = True
                Else
                    borrar = True
                End If
    
            End If
        End Sub

    Aclarando, en la propiedad Tag del textbox colocamos la leyenda que saldra una vez realizada la busqueda

    si no encunetra mensje "de no encontrado" en el propio text, al dar clic al text borra lo que tenga, se puede ejecutar tanto del button como dando enter en el text box este con la propiedad Multiline en false

    Si encuentra el código que se supone está en la primer columna de Tabla coloca: en el DGV el número de registro encontrado en la primer celda en la segunda la segunda celda de Tabal y foco en la tercer celda de el DGV

    Ve si te sirve, aún hay cosas que arreglar

    Saludos



    • Editado Marcelo PF martes, 15 de agosto de 2017 21:50
    martes, 15 de agosto de 2017 12:03
  • No es una tarea complicada, sólo considerar el orden de los eventos. Te dejo un ejemplo simple, revisalo y efectúa los cambios que consideres oportunos (entiendo que la forma como se consulta y recupera los datos no es asunto del hilo que expones).

    Private IsValidating As Boolean = False
    
    Private Sub DataGridView1_CellValidating(sender As Object, e As ...
    
    	Dim dgv = TryCast(sender, DataGridView)
    
    	'Actuar para la columna 'ColCuentaCorriente' cuando se haya ingresado un valor
    	If dgv.Columns(e.ColumnIndex).Name = "ColCuentaContable" AndAlso
    			e.FormattedValue.ToString <> String.Empty Then
    		'Llamar a la función 'GetCuentaContable' con el valor escrito en la celda
    		Dim Datos = GetCuentaContable(e.FormattedValue.ToString())
    		'¿Qué retorna la función 'GetCuentaContable'?
    		If Datos IsNot Nothing Then
    			e.Cancel = False
    
    			'Asignar valor a la siguiente columna
    			dgv("Column2", e.RowIndex).Value = Datos
                            'Salimos del controlador del evento CellValidating
    			Return
    		End If
    
    		'Si la función 'GetCuentaContable' retorna Nothing la cuenta contable no existe
    		dgv.Rows(e.RowIndex).ErrorText = "Cuenta contable no existe"
    		e.Cancel = True
    	End If
    
    End Sub
    
    Private Sub DataGridView1_CellValidated(sender As Object, e As ...
    
    	TryCast(sender, DataGridView).Rows(e.RowIndex).ErrorText = String.Empty
    
    	IsValidating = False
    
    End Sub
    
    Private Sub DataGridView1_CellEndEdit(sender As Object, e As ...
    
    	Dim dgv = TryCast(sender, DataGridView)
    
    	'Actuar para la columna 'ColCuentaCorriente' siempre y cuando exista un valor
    	If dgv.Columns(e.ColumnIndex).Name = "ColCuentaContable" AndAlso
    		Convert.ToString(dgv(e.ColumnIndex, e.RowIndex).Value) <> String.Empty Then
    		'Otorgar foco a la subsiguiente columna
    		dgv.CurrentCell = CType(sender, DataGridView)("Column3", e.RowIndex)
    		dgv.BeginEdit(True)
    
    		IsValidating = True
    	End If
    
    End Sub
    
    Private Sub DataGridView1_RowValidating(sender As Object, e As ...
    
    	e.Cancel = IsValidating
    
    End Sub

    - Resultado


    Nuestra profesión exige tener pasión por resolver problemas de una manera óptima y eficiente.
    • Marcado como respuesta mpulla jueves, 17 de agosto de 2017 23:38
    martes, 15 de agosto de 2017 18:35
  • Hola Marcelo.

    Gracias por tu tiempo y código, lo voy a revisar.

    Saludos.

    Mauricio

    miércoles, 16 de agosto de 2017 0:13
  • Hola Willams.

    Conosco poco de vb.net, me parece que es lo que necesito, voy a probarlo.

    Por favor puedes decirme cual es el orden de eventos?

    Saludos

    Mauricio

    miércoles, 16 de agosto de 2017 0:16
  • Es el mismo orden que muestro en el código adjunto: CellValidating -> CellValidated -> CellEndEdit, no digo que sean los únicos eventos que se producen pero son los que necesito para ocupar la solución del caso que propones. El evento RowValidating lo utilizo para mantener el "foco en la fila".


    Nuestra profesión exige tener pasión por resolver problemas de una manera óptima y eficiente.
    miércoles, 16 de agosto de 2017 0:51
  • Hola Willams.

    Gracias es lo que necesito.

    En realidad la DataGridView tiene 5 columnas

    Cuenta    Descripción   Debe   Haber    Comentario


    Tengo, un pequeño problema, la cuenta valida bien pero solo cuando doy enter, el enfoque va a celda correcta Debe, si doy tab el enfoque lo recibe la celda de descripción, como corregir esto?

    Por favor puedes ayudarme con algo más.

    Tengo que hacer que si la celda Debe tiene valor mayor a cero, encere la celda Haber o si la celda Haber es mayor a cero encere la celda Debe.

    Así mismo si doy enter o tab, ademas de validar, el enfoque vaya hacia la celda de derecha, la exepción es la columna descripción que debe ser saltada.

    Cuando tenga un registro completo es decir una cuenta correcta, debe o haber tenga un valor mayor a cero, poder crear un nuevo registro.

    Para validar la celda debe y haber, agrege algo de código al que me proporcionaste, pero no responde como espero.

    En CellValidating la columna no a perdido el enfoque, por lo que e.ColumnIndex corresponde a la celda actual o me equivoco?


        Private Sub GrdDetalle_CellValidating(sender As Object, e As DataGridViewCellValidatingEventArgs) Handles GrdDetalle.CellValidating
    
            Dim dgv = TryCast(sender, DataGridView)
    
            If dgv.Columns(e.ColumnIndex).Name = "ColCuenta" AndAlso e.FormattedValue.ToString <> String.Empty Then
                Dim oCuenta As New Cuenta
                oContabilidadDB.Cuenta_Buscar(oCuenta, SistemaVariables.codigo_empresa, 2017, e.FormattedValue.ToString)
    
                If oCuenta.codigo_cuenta <> 0 Then
                    e.Cancel = False
                    dgv("ColNombre", e.RowIndex).Value = oCuenta.descripcion
                    Return
    
                End If
    
                dgv.Rows(e.RowIndex).ErrorText = "Cuenta contable no existe"
                e.Cancel = True
    
            End If
    
            If InStr("ColDebe ColHaber", dgv.Columns(e.ColumnIndex).Name) > 0 Then
    
                Dim Valor As Decimal = Decimal.TryParse(dgv(dgv.Columns(e.ColumnIndex).Name, e.RowIndex).Value, 0)
    
                If Valor > 0 Then
                    If dgv.Columns(e.ColumnIndex).Name = "ColDebe" Then
                        dgv("ColHaber", e.RowIndex).Value = "0.00"
                    Else
                        dgv("ColDebe", e.RowIndex).Value = "0.00"
                    End If
                End If
    
                Me.GrdSuma()
            End If
    
        End Sub

    Para realizar el enfoque correspondiente agregue este código pero hay momentos en que hay un error.

    Cual es el error?

        Private Sub GrdDetalle_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles GrdDetalle.CellEndEdit
    
            Dim dgv = TryCast(sender, DataGridView)
    
            If dgv.Columns(e.ColumnIndex).Name = "ColCuenta" AndAlso Convert.ToString(dgv(e.ColumnIndex, e.RowIndex).Value) <> String.Empty Then
                dgv.CurrentCell = CType(sender, DataGridView)("ColDebe", e.RowIndex)
                dgv.BeginEdit(True)
    
                IsValidating = True
            End If
    
            If dgv.Columns(e.ColumnIndex).Name = "ColDebe" Then
                dgv.CurrentCell = CType(sender, DataGridView)("ColHaber", e.RowIndex)
                dgv.BeginEdit(True)
    
                IsValidating = True
            End If
    
            If dgv.Columns(e.ColumnIndex).Name = "ColHaber" Then
                dgv.CurrentCell = CType(sender, DataGridView)("ColConcepto", e.RowIndex)
                dgv.BeginEdit(True)
    
                IsValidating = True
            End If
    
        End Sub

    Saludos

    Mauricio

    jueves, 17 de agosto de 2017 4:32