none
Como sumar y restar al darle click a una columna imagen en datagrid RRS feed

  • Pregunta

  • Buen dia Gente, 

    Estoy necesitando si me pueden orientar sobre como al apretar la celda con + , en la columna resultado sume de a 1 y cuando le de a la celda - reste tambien de a 1. Las columnas estan definidas de la siguiente manera 

            Dim colGenero As New DataGridViewImageColumn()
            colGenero.Name = "Suma"
            Me.DataGridView1.Columns.Add(colGenero)
            Dim colResta As New DataGridViewImageColumn()
            colResta.Name = "Resta"
            Me.DataGridView1.Columns.Add(colResta)
            Dim colResultado As New DataGridViewTextBoxColumn()
            colResultado.Name = "Resultado"
            Me.DataGridView1.Columns.Add(colResultado)

    Tambien necesitaria que la columna Resultado inicie en valor 0 y se vaya modificando a medida que se apretan esas celdas, por ahora no tengo que guardar la info en ninguna tabla y el resultado solo seria para seguir aprendiendo. Adjunto una imagen de como esta ahora el proyecto.

    Desde ya les agradezco mucho por su ayuda. 

    Saludos

    martes, 23 de junio de 2020 16:20

Respuestas

  • Hola:
    Copia y pega el siguiente codigo
    Option Explicit On
    Option Strict On
    Imports System.Data.SqlClient
    Public Class Form5
        Private Sub Form5_Load(sender As Object, e As EventArgs) Handles Me.Load
            DataGridView1.AllowUserToAddRows = False
            Dim msCadenaSQL As String = "Data Source=.\SQLEXPRESS;Initial Catalog=TU_BASE_DE_DATOS;Integrated Security=True"
            Dim mdtDataTable As New DataTable
            Try
                Dim lsQuery As String = "SELECT UN_CAMPO FROM TU_TABLA"
                Using loConexion As New SqlConnection(msCadenaSQL)
                    Using loDataAdapter As New SqlDataAdapter(lsQuery, loConexion)
                        loDataAdapter.Fill(mdtDataTable)
                    End Using
                End Using
            Catch ex As Exception
                MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End Try
            Dim colSuma As New DataGridViewImageColumn()
            colSuma.Name = "Suma"
            Me.DataGridView1.Columns.Add(colSuma)
            Dim colResta As New DataGridViewImageColumn()
            colResta.Name = "Resta"
            Me.DataGridView1.Columns.Add(colResta)
            Dim colResultado As New DataGridViewTextBoxColumn
            colResultado.Name = "Resultado"
            Me.DataGridView1.Columns.Add(colResultado)
            DataGridView1.DataSource = mdtDataTable
            For Each Fila As DataGridViewRow In DataGridView1.Rows
                Fila.Cells("Resultado").Value = 0
            Next
        End Sub
        Private Sub DataGridView1_CellFormatting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
            ' cuando se vaya a pintar la celda de la columna de imagen
            If Me.DataGridView1.Columns(e.ColumnIndex).Name = "Suma" Then
                ' establecer la altura de la fila para que se pueda visualizar correctamente
                Me.DataGridView1.Rows(e.RowIndex).Height = 40
                ' asignar la imagen adecuada
                e.Value = New Bitmap(Application.StartupPath & "\TU_IMAGEN_SUMA.jpg", False)
            End If
            If Me.DataGridView1.Columns(e.ColumnIndex).Name = "Resta" Then
                ' establecer la altura de la fila para que se pueda visualizar correctamente
                Me.DataGridView1.Rows(e.RowIndex).Height = 40
                ' asignar la imagen adecuada
                e.Value = New Bitmap(Application.StartupPath & "\TU_IMAGEN_RESTA.jpg", False)
            End If
        End Sub

        Private Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick
            If e.RowIndex = -1 Then
                Return
            End If
            Dim Columna As Integer = e.ColumnIndex
            Dim loFila As DataGridViewRow = DataGridView1.CurrentRow()
            DataGridView1.CurrentCell = loFila.Cells(2)
            If Columna = 0 Then
                DataGridView1.CurrentCell.Value = Convert.ToInt32(DataGridView1.CurrentCell.Value) + 1
            ElseIf Columna = 1 Then
                DataGridView1.CurrentCell.Value = Convert.ToInt32(DataGridView1.CurrentCell.Value) - 1
            End If
            DataGridView1.Refresh()
        End Sub
    End Class

    un saludo desde Bilbo
    Carlos
    • Marcado como respuesta Guille_87 sábado, 27 de junio de 2020 14:02
    miércoles, 24 de junio de 2020 18:49

Todas las respuestas

  • Hola:

    En un Form con 1 DataGridView, copia y pega el siguiente codigo

    Option Explicit On
    Option Strict On
    Public Class Form5
        Private mdtDataTable As New DataTable
        Private Sub Form5_Load(sender As Object, e As EventArgs) Handles Me.Load
            DataGridView1.AllowUserToAddRows = False
            'Añadimos las columnas.
            mdtDataTable.Columns.Add(New DataColumn("Resultado", Type.GetType("System.Int32")))
            'Añadimos datos
            For liCiclo As Integer = 1 To 10
                mdtDataTable.Rows.Add(0)
            Next
            Dim colSuma As New DataGridViewImageColumn()
            colSuma.Name = "Suma"
            Me.DataGridView1.Columns.Add(colSuma)
            Dim colResta As New DataGridViewImageColumn()
            colResta.Name = "Resta"
            Me.DataGridView1.Columns.Add(colResta)
            DataGridView1.DataSource = mdtDataTable
        End Sub
        Private Sub DataGridView1_CellFormatting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
            ' cuando se vaya a pintar la celda de la columna de imagen
            If Me.DataGridView1.Columns(e.ColumnIndex).Name = "Suma" Then
                ' establecer la altura de la fila para que se pueda visualizar correctamente
                Me.DataGridView1.Rows(e.RowIndex).Height = 40
                ' asignar la imagen adecuada
                e.Value = New Bitmap(Application.StartupPath & "\TU_FICHERO_IMAGEN.jpg", False)
            End If
            If Me.DataGridView1.Columns(e.ColumnIndex).Name = "Resta" Then
                ' establecer la altura de la fila para que se pueda visualizar correctamente
                Me.DataGridView1.Rows(e.RowIndex).Height = 40
                ' asignar la imagen adecuada
                e.Value = New Bitmap(Application.StartupPath & "\TU_FICHERO_IMAGEN.jpg", False)
            End If
        End Sub
        Private Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick
            If e.RowIndex = -1 Then
                Return
            End If
            Dim Columna As Integer = e.ColumnIndex
            Dim loFila As DataGridViewRow = DataGridView1.CurrentRow()
            DataGridView1.CurrentCell = loFila.Cells(2)  'Columna Resultado
            If Columna = 0 Then   'Columna Suma
                DataGridView1.CurrentCell.Value = Convert.ToInt32(DataGridView1.CurrentCell.Value) + 1
            ElseIf Columna = 1 Then    'Columna Resta
                DataGridView1.CurrentCell.Value = Convert.ToInt32(DataGridView1.CurrentCell.Value) - 1
            End If
            DataGridView1.Refresh()
        End Sub
    End Class

    Un saludo desde Bilbo
    Carlos
    miércoles, 24 de junio de 2020 7:32
  • Carlos, de nuevo muchas gracias, pero te consulto ya que estoy siguiendo con el codigo que me pasaste anteriormente, Este es el codigo completo con el que estoy actualmente, como tendria que hacer para agregar esa columna resultado sin crear otro datatable.

    Option Explicit On
    Option Strict On
    Imports System.Data.SqlClient
    
    Public Class Form1
       
        Private Sub frmFormatoIndirectoImagen_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Me.DataGridView1.DataSource = ConstruirDatos.pF_dtObtenerTabla()
            ' crear una nueva columna de tipo imagen para mostrar un icono indicativo del género del cliente y agregarla a la colección de columnas del control
            Dim colGenero As New DataGridViewImageColumn()
            colGenero.Name = "Suma"
            ' colGenero.DisplayIndex = 1
            Me.DataGridView1.Columns.Add(colGenero)
            Dim colResta As New DataGridViewImageColumn()
            colResta.Name = "Resta"
            ' colResta.DisplayIndex = 2
            Me.DataGridView1.Columns.Add(colResta)
            Dim colResultado As New DataGridViewTextBoxColumn()
            colResultado.Name = "Resultado"
            ' colResultado.DisplayIndex = 0
             Me.DataGridView1.Columns.Add(colResultado)
        End Sub
        Private Sub dataGridView1_CellFormatting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
            ' cuando se vaya a pintar la celda de la columna de imagen
            If Me.DataGridView1.Columns(e.ColumnIndex).Name = "Suma" Then
                ' establecer la altura de la fila para que se pueda visualizar correctamente
                'Me.DataGridView1.Rows(e.RowIndex).Height = 40
                ' asignar la imagen adecuada
                Select Case DirectCast(Me.DataGridView1.Rows(e.RowIndex).Cells("SEXO").Value, String)
                    Case "M"
                        'e.Value = New Bitmap(Me.[GetType](), "SimboloMasculino.jpg")
                        e.Value = New Bitmap(Application.StartupPath & "\image1.png", False)
                       
                        Exit Select
                    Case "F"
                        'e.Value = New Bitmap(Me.[GetType](), "SimboloFemenino.jpg")
                        e.Value = New Bitmap(Application.StartupPath & "\image1.png", True)
                   Exit Select
                End Select
            End If
            If Me.DataGridView1.Columns(e.ColumnIndex).Name = "Resta" Then
                e.Value = New Bitmap(Application.StartupPath & "\image2.png", True)
                ' establecer la altura de la fila para que se pueda visualizar correctamente
                'Me.DataGridView1.Rows(e.RowIndex).Height = 40
                ' asignar la imagen adecuada
            End If
    
        End Sub
        Private Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick
    End Class
    
    Public Class ConstruirDatos
            Public Shared Function pF_dtObtenerTabla() As DataTable
                Try
                ' crear la sentencia sql para obtener las filas
    
                Dim lsQuery As String = "Select ID_CLIENTE,DOC_NRO,APELLIDO,NOMBRE,SEXO From CLIENTES Where ID_CLIENTE='1088'"
                
                Using loConexion As New SqlConnection(lsCadConexion)
                        Dim daAdaptador As New SqlDataAdapter(lsQuery, loConexion)
                    Dim loDataTable As New DataTable()
                    daAdaptador.Fill(loDataTable)
                    Return loDataTable
                    End Using
                Catch ex As Exception
                MessageBox.Show(ex.Message, "pF_dtObtenerTabla", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Return Nothing
                End Try
            End Function
        End Class

    Asi es lo que tengo actualmente. Esto me trae datos de clientes y al final me agrega las columnas +,- y resultado.

    miércoles, 24 de junio de 2020 17:32
  • Hola:
    Copia y pega el siguiente codigo
    Option Explicit On
    Option Strict On
    Imports System.Data.SqlClient
    Public Class Form5
        Private Sub Form5_Load(sender As Object, e As EventArgs) Handles Me.Load
            DataGridView1.AllowUserToAddRows = False
            Dim msCadenaSQL As String = "Data Source=.\SQLEXPRESS;Initial Catalog=TU_BASE_DE_DATOS;Integrated Security=True"
            Dim mdtDataTable As New DataTable
            Try
                Dim lsQuery As String = "SELECT UN_CAMPO FROM TU_TABLA"
                Using loConexion As New SqlConnection(msCadenaSQL)
                    Using loDataAdapter As New SqlDataAdapter(lsQuery, loConexion)
                        loDataAdapter.Fill(mdtDataTable)
                    End Using
                End Using
            Catch ex As Exception
                MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End Try
            Dim colSuma As New DataGridViewImageColumn()
            colSuma.Name = "Suma"
            Me.DataGridView1.Columns.Add(colSuma)
            Dim colResta As New DataGridViewImageColumn()
            colResta.Name = "Resta"
            Me.DataGridView1.Columns.Add(colResta)
            Dim colResultado As New DataGridViewTextBoxColumn
            colResultado.Name = "Resultado"
            Me.DataGridView1.Columns.Add(colResultado)
            DataGridView1.DataSource = mdtDataTable
            For Each Fila As DataGridViewRow In DataGridView1.Rows
                Fila.Cells("Resultado").Value = 0
            Next
        End Sub
        Private Sub DataGridView1_CellFormatting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
            ' cuando se vaya a pintar la celda de la columna de imagen
            If Me.DataGridView1.Columns(e.ColumnIndex).Name = "Suma" Then
                ' establecer la altura de la fila para que se pueda visualizar correctamente
                Me.DataGridView1.Rows(e.RowIndex).Height = 40
                ' asignar la imagen adecuada
                e.Value = New Bitmap(Application.StartupPath & "\TU_IMAGEN_SUMA.jpg", False)
            End If
            If Me.DataGridView1.Columns(e.ColumnIndex).Name = "Resta" Then
                ' establecer la altura de la fila para que se pueda visualizar correctamente
                Me.DataGridView1.Rows(e.RowIndex).Height = 40
                ' asignar la imagen adecuada
                e.Value = New Bitmap(Application.StartupPath & "\TU_IMAGEN_RESTA.jpg", False)
            End If
        End Sub

        Private Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick
            If e.RowIndex = -1 Then
                Return
            End If
            Dim Columna As Integer = e.ColumnIndex
            Dim loFila As DataGridViewRow = DataGridView1.CurrentRow()
            DataGridView1.CurrentCell = loFila.Cells(2)
            If Columna = 0 Then
                DataGridView1.CurrentCell.Value = Convert.ToInt32(DataGridView1.CurrentCell.Value) + 1
            ElseIf Columna = 1 Then
                DataGridView1.CurrentCell.Value = Convert.ToInt32(DataGridView1.CurrentCell.Value) - 1
            End If
            DataGridView1.Refresh()
        End Sub
    End Class

    un saludo desde Bilbo
    Carlos
    • Marcado como respuesta Guille_87 sábado, 27 de junio de 2020 14:02
    miércoles, 24 de junio de 2020 18:49
  • Bien Carlos, ahi lo probe y le agregue la linea 
    ElseIf Columna = 1 And e.RowIndex >= 0 And Convert.ToInt32(DataGridView1.CurrentCell.Value) > 0 Then
                DataGridView1.CurrentCell.Value = Convert.ToInt32(DataGridView1.CurrentCell.Value) - 1
                End If
    para que el numero 0 sea el tope y no aparezcan numeros negativos, pero lo que me pasa es que al tocar la cabecera de la columna para ordenarlos de manera ascendente o descendente, a la columna resultado se le borran todos los resultados, probe comentando la linea esta DataGridView1.Refresh() y sigue pasando lo mismo, creo que tendria que hacer algo con esta linea 
    If e.RowIndex = -1 Then
                Return
            End If
    El tema que si la borro, al tocar los headers tira un error. 
    miércoles, 24 de junio de 2020 20:04
  • Hola:
    Para que puedas ordenar la columna resultado en vez de añadirla manualmente la tendras que añadir en la consulta que haces a la base de datos y que sea numerica
    Copia y pega el siguiente codigo

    Option Explicit On
    Option Strict On
    Imports System.Data.SqlClient

    Public Class Form5
        Private Sub Form5_Load(sender As Object, e As EventArgs) Handles Me.Load
            DataGridView1.AllowUserToAddRows = False
            Dim msCadenaSQL As String = "Data Source=.\SQLEXPRESS;Initial Catalog=TU_BASE_DE_DATOS;Integrated Security=True"
            Dim mdtDataTable As New DataTable
            Try
                Dim lsQuery As String = "SELECT 0 AS Resultado, id_usuario FROM usuario"
                Using loConexion As New SqlConnection(msCadenaSQL)
                    Using loDataAdapter As New SqlDataAdapter(lsQuery, loConexion)
                        loDataAdapter.Fill(mdtDataTable)
                    End Using
                End Using
            Catch ex As Exception
                MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End Try
            Dim colSuma As New DataGridViewImageColumn()
            colSuma.Name = "Suma"
            Me.DataGridView1.Columns.Add(colSuma)
            Dim colResta As New DataGridViewImageColumn()
            colResta.Name = "Resta"
            Me.DataGridView1.Columns.Add(colResta)
            DataGridView1.DataSource = mdtDataTable
        End Sub
        Private Sub DataGridView1_CellFormatting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
            ' cuando se vaya a pintar la celda de la columna de imagen
            If Me.DataGridView1.Columns(e.ColumnIndex).Name = "Suma" Then
                ' establecer la altura de la fila para que se pueda visualizar correctamente
                Me.DataGridView1.Rows(e.RowIndex).Height = 40
                ' asignar la imagen adecuada
                e.Value = New Bitmap(Application.StartupPath & "\TU_IMAGEN.jpg", False)
            End If
            If Me.DataGridView1.Columns(e.ColumnIndex).Name = "Resta" Then
                ' establecer la altura de la fila para que se pueda visualizar correctamente
                Me.DataGridView1.Rows(e.RowIndex).Height = 40
                ' asignar la imagen adecuada
                e.Value = New Bitmap(Application.StartupPath & "\TU_IMAGEN.jpg", False)
            End If
        End Sub

        Private Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick
            If e.RowIndex = -1 Then
                Return
            End If
            Dim Columna As Integer = e.ColumnIndex
            Dim loFila As DataGridViewRow = DataGridView1.CurrentRow()
            DataGridView1.CurrentCell = loFila.Cells(2)
            If Columna = 0 Then
                DataGridView1.CurrentCell.Value = Convert.ToInt32(DataGridView1.CurrentCell.Value) + 1
            ElseIf Columna = 1 Then
                DataGridView1.CurrentCell.Value = Convert.ToInt32(DataGridView1.CurrentCell.Value) - 1
            End If
            DataGridView1.Refresh()
        End Sub
    End Class

    Un saludo desde Bilbo
    Carlos
    miércoles, 24 de junio de 2020 20:25
  • ¿Alguna novedad sobre la consulta realizada? ¿Han sido útiles las respuestas proporcionadas?  

    jueves, 25 de junio de 2020 21:16
    Moderador
  • Barbaro Carlos, ahora he creado la columna resultado en la tabla sql, cuando la quiero actualizar dinamicamente con la siguiente query, tengo el problema que quedan todos los campos de la columna resultado con el mismo valor, como tendria que hacer para se actualicen los valores correctamente. La consulta que estoy usando es la siguiente

    Dim Columna As Integer = e.ColumnIndex
            Dim loFila As DataGridViewRow = DataGridView1.CurrentRow()
            DataGridView1.CurrentCell = loFila.Cells(2)
            If Columna = 0 Then
                DataGridView1.CurrentCell.Value = Convert.ToInt32(DataGridView1.CurrentCell.Value) + 1
                Dim actualizar As String = "Update cliente SET resultado=" + DataGridView1.CurrentCell.Value + ""
                Dim cmd = New SqlCommand(actualizar, lsCadConexion)
                cmd.ExecuteNonQuery()

    Desde ya muchas gracias.

    viernes, 26 de junio de 2020 15:23
  • Hola:
    Al principio la columna resultado era añadida manualmente al DGV y
    por ahora no tengo que guardar la info en ninguna tabla <
    Ahora la columna resultado es parte de la tabla y ademas quieres modificar su valor cada vez que se modifica su valor en el DGV
    ¿Cual sera la siguiente opcion?
    Lo que tienes que hacer es "aclararte la ideas", una vez lo tengas claro, expones lo que deseas porque sino NO vamos a finalizar el hilo.
    La sentencia UPDATE es algo como esto
    UPDATE tabla SET campo1=@campo1 WHERE id=@id
    En lo que tu estas haciendo te falta la clausula WHERE, por eso modifica a toda la tabla.

    ¿Porque estas modificando la tabla cada ves que haces un click?
    No sera mejor que modifiques la tabla 1 sola vez al finalizar la sesion de hacer clicks en la tabla

    Un saludo desde Bilbo
    Carlos
    viernes, 26 de junio de 2020 16:26
  • Gracias Carlos, estoy realizando pruebas constantemente para ir conociendo el funcionamiento de .Net, es por esto que primero hice algo sencillo, luego genere la columna en la base de datos y las ideas van surgiendo a medida que voy trabajando, ya que como en todo proyecto pueden presentarse cambios y hay que ir adaptándose. 

    No sera mejor que modifiques la tabla 1 sola vez al finalizar la sesion de hacer clicks en la tabla

    En realidad no, porque si el .exe se mantiene abierto todo el tiempo y no se cierra nunca, no veria los cambios en la tabla. Por eso la idea es que vaya haciendo el update a medida que cambia de valor la columna de resultado. 

    UPDATE tabla SET campo1=@campo1 WHERE id=@id

    Lo estoy probando de esta manera:

                Dim actualizar As String = "Update cliente Set resultado=" + DataGridView1.CurrentCell.Value + " where nombre_cliente=" + DataGridView1.CurrentRow.Cells("nombre_cliente").Value + ""
                Dim cmd = New SqlCommand(actualizar, lsCadConexion)
                    cmd.ExecuteNonQuery()
    

    Pero arroja, Información adicional: Invalid column name 'guille'.

    En vez de tomar el valor del campo, lo toma como una columna lo cual me parece raro ya que si pongo 

    where nombre_cliente="guille"

    con eso funciona a la perfeccion.


    • Editado Guille_87 viernes, 26 de junio de 2020 19:12 edicion para mejorar
    viernes, 26 de junio de 2020 18:47
  • Hola:
    El codigo seria:

            Try
                Dim lsQuery As String = "UPDATE cliente SET resultado=@resultado WHERE nombre_cliente=@nombrecliente"
                Using lConexion As New SqlConnection(TuCadenaDeConexion)
                    lConexion.Open()
                    Using lComando As New SqlCommand(lsQuery, lConexion)
                        lComando.Parameters.Add(New SqlParameter("@resultado", DataGridView1.CurrentRow.Cells("resultado").Value))
                        lComando.Parameters.Add(New SqlParameter("@nombrecliente", DataGridView1.CurrentRow.Cells("nombre_cliente").Value))
                        lComando.ExecuteNonQuery()
                    End Using
                End Using
            Catch ex As Exception
                MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Information)
            End Try

    Fijate en el uso de parametros, si lo haces concatenando strings, es muy facil que te de dolor de cabeza frecuentemente.
    Otro punto que me llama la atencion es que para la clausula WHERE uses el campo nombre_cliente y no uses un identificador UNICO de cliente.
    ¿Que pasa si el cliente se llama Jose y tienes 5 clientes con ese nombre?
    Pues que ya tienes "el lio armado"

    Un saludo desde Bilbo
    Carlos
    viernes, 26 de junio de 2020 19:58
  • Carlos, desde ya muchas gracias, cambie el where a id_cte por esto que me decias y funciono perfecto. Te agradezco mucho por ayudarme a lograr lo que estaba buscando del código. Doy por cerrado este hilo. Saludos desde Argentina.

    Guillermo

    sábado, 27 de junio de 2020 14:02