none
Como sumar columna Datagridview filtrada por dato de celda RRS feed

  • Pregunta

  • Buenas amigos, 

    Tengo un formulario en el cual hay un datagridview donde voy añadiendo articulos con datos como codigo, descripcion, descuentos, precios e importe. Muestro más abajo imagen para que podais verlo. Las columnas de Imp.Dto , Imp.Iva, Importe, T.re, impre son columnas que se calculan en funcion a los datos introducidos en la otras columnas. Mi consulta es la siguiente, segun pueden ver en la imagen mas abajo, necesito sumar los valores que es encuentran en la columna "impre" , y asignar el valor a un label en funcion al valor que tiene la celda t.re. Ejemplo. En la primera y segunda fila vemos que el valor de las celdas en la columna "t.re" es de 5,20 , pues necesito añadir al label que esta más abajo la suma de las dos celdas situadas en las filas donde el valor es 5,2 de la columna impre.

    Los valores tanto de las celdas como de los labels inferiores son calculadas en el evento CellValueChange . He tratado de filtrar dichos valores con el Foreach pero no me realiza los calculos ni en el momento ni la forma adecuada. Alguna idea???. Dejo parte donde se realizan los calculos y se asigna el valor en la celda correspondiente del Datagridview.

     

    domingo, 28 de diciembre de 2014 11:49

Respuestas

  • if (dgvarticulos.Columns[e.ColumnIndex].Name == "precio")
              {
                  try
                  {
                      dgvarticulos.CurrentRow.Cells[11].Value = variablere.ToString("N2");
    
                      double varcantidad;
                      if (dgvarticulos.CurrentRow.Cells[1].Value == null)
                      {
                          varcantidad = 1;
                          dgvarticulos.CurrentRow.Cells[1].Value = varcantidad.ToString("N2");
                      }
                      else
                      {
                          varcantidad = Convert.ToDouble(dgvarticulos.CurrentRow.Cells[1].Value);
                      }
                      double vardto = Math.Round( Convert.ToDouble(dgvarticulos.CurrentRow.Cells[5].Value), 2);//COLUMNA TIPO DTO.
                      double variva = Math.Round( Convert.ToDouble(dgvarticulos.CurrentRow.Cells[7].Value), 2);//COLUMNA TIPO IVA.
                      double varpvp1 = Math.Round( Convert.ToDouble(dgvarticulos.CurrentRow.Cells[9].Value), 2);//COLUMNA PRECIO UDAD.
                      double varimpdto = Math.Round(varpvp1 * vardto / 100, 2);
                      double importe = Math.Round(varcantidad * (varpvp1 - varimpdto), 2);
                      varimpdto = varimpdto * varcantidad;
                      double varimpiva = Math.Round(importe * variva / 100, 2);
                      double varimpre = Math.Round(importe * variablere / 100, 2);
                      
    
    
                      dgvarticulos.CurrentRow.Cells[6].Value = varimpdto.ToString("N2");
                      dgvarticulos.CurrentRow.Cells[8].Value = varimpiva.ToString("N2");
                      dgvarticulos.CurrentRow.Cells[10].Value = importe.ToString("N2");
                      dgvarticulos.CurrentRow.Cells[12].Value = varimpre.ToString("N2");
                      
                      
                  }
                  catch
                  {
                     
                  }
             }


    • Marcado como respuesta Gori0056 domingo, 28 de diciembre de 2014 23:21
    domingo, 28 de diciembre de 2014 11:55
  • En primer lugar agradeceros a todos tan rapida respuesta. 

    Decir que finalmente la forma en que lo he solucionado es una mezcla de ideas aportadas por Efrain, Williams y Jose, Muchas gracias a los tres. 

    El resultado es el siguiente, como podreis comprobar abajo realiza la suma diferenciada segun tipo y de forma correcta:


    Para realizar esto lo primero que he de indicar que tanto los datos de los articulos como los tipo de indices de iva y recargo provienen de tablas sql. 

    Lo que he hecho ha sido lo siguiente, con el siguiente codigo cargaba el articulo en el DGV, y creando un evento en el cual almacenara en una variable el tipo de recargo para posteiormente utilizarlo para los calculos que necesito, una vez asignado los valores a las variables utilizo el siguiente codigo para extraer segun el tipo la suma de la columna.

    private void Sumarrecargo()
            {
                double impre1 = 0;
                double impre2 = 0;
                double impre3 = 0;
                double impre4 = 0;
                
                foreach (DataGridViewRow row in dgvarticulos.Rows)
                {
                    if (chrecargo.Checked == true)
                    {
                        if (Convert.ToDouble(row.Cells["tre"].Value) == varre1)
                        {
                            impre1 += Convert.ToDouble(row.Cells["impre"].Value);
                            
                        }
                        if (Convert.ToDouble(row.Cells["tre"].Value) == varre2)
                        {
                            impre2 += Convert.ToDouble(row.Cells["impre"].Value);
                            
                        }
                        if (Convert.ToDouble(row.Cells["tre"].Value) == varre3)
                        {
                            impre3 += Convert.ToDouble(row.Cells["impre"].Value);
                            
                        }
                        if (Convert.ToDouble(row.Cells["tre"].Value) == varre4)
                        {
                            impre4 += Convert.ToDouble(row.Cells["impre"].Value);
                            
                        }
                    }
                }
                lblimpre1.Text = Math.Round(impre1, 2).ToString();
                lblimpre2.Text = Math.Round(impre2, 2).ToString();
                lblimpre3.Text = Math.Round(impre3, 2).ToString();
                lblimpre4.Text = Math.Round(impre4, 2).ToString();
            }
    Las variables varre1, varre2, varre3, varre4 son las que anteriormente he asignado con los valores 5,2 , 1,4 , 0,5 y 0 que son los tipos de % actuales de impuestos que se cobran en mi pais segun el tipo de articulo. A lo que comentaba Williams sobre que ocurriria si hubiesen mas de 4 valores distintos en la columna, indicar que es poco probable que dicho caso ocurra, a no ser que estatalmente se amplien la cantidad de tipos distintos de impuestos, cosa que en los ultimos 10 años no ha ocurrido, pero en el caso posible, el 4 valor que estamos indicando actualmente no se utiliza o esta marcado como el 0%. Con esto decir, que si seria un problema para otros tipos de casos utilizar este ejemplo, ya que en mi caso esta restringido para solo 4 valores distintos.


    • Marcado como respuesta Gori0056 domingo, 28 de diciembre de 2014 23:21
    domingo, 28 de diciembre de 2014 23:21

Todas las respuestas

  • if (dgvarticulos.Columns[e.ColumnIndex].Name == "precio")
              {
                  try
                  {
                      dgvarticulos.CurrentRow.Cells[11].Value = variablere.ToString("N2");
    
                      double varcantidad;
                      if (dgvarticulos.CurrentRow.Cells[1].Value == null)
                      {
                          varcantidad = 1;
                          dgvarticulos.CurrentRow.Cells[1].Value = varcantidad.ToString("N2");
                      }
                      else
                      {
                          varcantidad = Convert.ToDouble(dgvarticulos.CurrentRow.Cells[1].Value);
                      }
                      double vardto = Math.Round( Convert.ToDouble(dgvarticulos.CurrentRow.Cells[5].Value), 2);//COLUMNA TIPO DTO.
                      double variva = Math.Round( Convert.ToDouble(dgvarticulos.CurrentRow.Cells[7].Value), 2);//COLUMNA TIPO IVA.
                      double varpvp1 = Math.Round( Convert.ToDouble(dgvarticulos.CurrentRow.Cells[9].Value), 2);//COLUMNA PRECIO UDAD.
                      double varimpdto = Math.Round(varpvp1 * vardto / 100, 2);
                      double importe = Math.Round(varcantidad * (varpvp1 - varimpdto), 2);
                      varimpdto = varimpdto * varcantidad;
                      double varimpiva = Math.Round(importe * variva / 100, 2);
                      double varimpre = Math.Round(importe * variablere / 100, 2);
                      
    
    
                      dgvarticulos.CurrentRow.Cells[6].Value = varimpdto.ToString("N2");
                      dgvarticulos.CurrentRow.Cells[8].Value = varimpiva.ToString("N2");
                      dgvarticulos.CurrentRow.Cells[10].Value = importe.ToString("N2");
                      dgvarticulos.CurrentRow.Cells[12].Value = varimpre.ToString("N2");
                      
                      
                  }
                  catch
                  {
                     
                  }
             }


    • Marcado como respuesta Gori0056 domingo, 28 de diciembre de 2014 23:21
    domingo, 28 de diciembre de 2014 11:55
  •    VB.NET

    Public Sub SumarColumna()
            Dim SumaColumna52 As Decimal = 0
            Dim SumaColumna14 As Decimal = 0
            For Each row As DataGridViewRow In DataGridView1.Rows
                If Not IsDBNull(row.Cells("T.RE").Value) AndAlso Not String.IsNullOrEmpty(row.Cells("T.RE").Value) And Not IsDBNull(row.Cells("IMPRE").Value) AndAlso Not String.IsNullOrEmpty(row.Cells("IMPRE").Value) Then
    
                    If CDec(row.Cells("t.re").Value) = 5.2 Then
                        SumaColumna52 = SumaColumna52 + CDec(row.Cells("IMPRE").Value)
                    ElseIf CDec(row.Cells("t.re").Value) = 1.4 Then
                        SumaColumna14 = SumaColumna14 + CDec(row.Cells("IMPRE").Value)
                    End If
    
                End If
            Next
    
            Label1.Text = SumaColumna52.ToString("n2")
            Label2.Text = SumaColumna14.ToString("n2")
        End Sub

    C#

    public void SumarColumna() {
            decimal SumaColumna52 = 0;
            decimal SumaColumna14 = 0;
            foreach(DataGridViewRow row in DataGridView1.Rows){
                if( ! IsDBNull(row.Cells("T.RE").Value) && ! String.IsNullOrEmpty(row.Cells("T.RE").Value) & ! IsDBNull(row.Cells("IMPRE").Value) && ! String.IsNullOrEmpty(row.Cells("IMPRE").Value) ){
     
                    if( Convert.ToDecimal(row.Cells("t.re").Value) == 5.2 ){
                        SumaColumna52 = SumaColumna52 + Convert.ToDecimal(row.Cells("IMPRE").Value);
                    }else if( Convert.ToDecimal(row.Cells("t.re").Value) == 1.4 ){
                        SumaColumna14 = SumaColumna14 + Convert.ToDecimal(row.Cells("IMPRE").Value);
                    }
     
                }
            }
     
            Label1.Text = SumaColumna52.ToString("n2");
            Label2.Text = SumaColumna14.ToString("n2");
        }


    EFRAIN MEJIAS C VALENCIA - VENEZUELA

    domingo, 28 de diciembre de 2014 15:15
  • Hola,

    Veo con mal ojo lo que intentas hacer. ¿Qué pasa si tienes mas de 4 valores distintos en la columna T.re? En la parte de Recargo Equivalencia sólo tienes disponible para 4 posiciones. Quizá debas de "migrar" esa información a otro contenedor de datos - algo ligero - como un ListView. En fin, en líneas simples lo que deberías hacer es hacer un "distinct" a la columna T.re para traer los valores distintos y luego preguntar esos valores distintos por cada fila y acumularlos en cada etiqueta que yo lo he llamado (Label1, Label2, Label3, Label4)

    List<decimal> tre = new List<decimal>();
    
                foreach (DataGridViewRow row in dataGridView1.Rows)
                {
                    if (tre.Any(a => !a.Equals(row.Cells["tre"].Value)))
                    {
                        tre.Add(Convert.ToDecimal(row.Cells["tre"].Value));
                    }
                }
                foreach (DataGridViewRow row in dataGridView1.Rows)
                {
                    if (tre[0].Equals(row.Cells["tre"].Value))
                    {
                        label1.Text = Convert.ToString(Convert.ToDecimal(label1.Text) + Convert.ToDecimal(row.Cells["impre"].Value));                    
                    }
                    if (tre[1].Equals(row.Cells["tre"].Value))
                    {
                        label2.Text = Convert.ToString(Convert.ToDecimal(label2.Text) + Convert.ToDecimal(row.Cells["impre"].Value));
                    }
                    if (tre[2].Equals(row.Cells["tre"].Value))
                    {
                        label3.Text = Convert.ToString(Convert.ToDecimal(label3.Text) + Convert.ToDecimal(row.Cells["impre"].Value));
                    }
                    if (tre[3].Equals(row.Cells["tre"].Value))
                    {
                        label4.Text = Convert.ToString(Convert.ToDecimal(label4.Text) + Convert.ToDecimal(row.Cells["impre"].Value));
                    }
                }

    -----------------------------------------------------------------------------------------------------
    Espero haberte ayudado con mi sugerencia, si resolvió tu problema no olvides marcarla como respuesta.

    Willams Morales P.
    Arequipa - Perú
    domingo, 28 de diciembre de 2014 17:28
  • Todo esto es relativamente sencillo con data binding.  Nada más necesitamos una clase que represente las líneas en el DGV que implemente INotifyPropertyChanged, luego un objeto con el patrón Observer, que ya está hecho y es el BindingList y.... ¡ya!  Me parece que es todo.  Siempre me piden un proyecto de ejemplo así que le hago uno 30 minutos.

    EDICIÓN:

    Listo.  Aquí le dejo un enlace al ZIP.

    La mecánica es bien sencilla:  La primera regla a respetar aquí es:  Siempre tomamos los datos que necesitamos de la colección original.  No debe leerse el valor de las celdas del DGV si se tiene la fuente de datos original.  Los controles como el DGV no están diseñados para almacenar datos; están diseñados para mostrar datos.

    En segundo lugar, aprovechamos Data Binding y creamos una clase SaleItem que representa una línea del DGV.  Por facilidad en el ejemplo yo usé AutoGenerateColumns, pero lo mejor es que las defina manualmente para que ajuste los detallitos.  La clase SaleItem hereda de Entity para heredar las capacidades de INotifyPropertyChanged.

    Finalmente el formulario en el Form_Load se suscribe al evento ListChanged de la lista de items para así recalcular el total cada vez que la lista cambia.  Veo que usted tiene algún requerimiento especial para calcular el total.  Simplemente asegúrese de programar eso en el cálculo de la suma.  El ejemplo que yo hice es un cálculo simple del gran total únicamente.


    Jose R. MCP
    Code Samples


    domingo, 28 de diciembre de 2014 17:56
    Moderador
  • En primer lugar agradeceros a todos tan rapida respuesta. 

    Decir que finalmente la forma en que lo he solucionado es una mezcla de ideas aportadas por Efrain, Williams y Jose, Muchas gracias a los tres. 

    El resultado es el siguiente, como podreis comprobar abajo realiza la suma diferenciada segun tipo y de forma correcta:


    Para realizar esto lo primero que he de indicar que tanto los datos de los articulos como los tipo de indices de iva y recargo provienen de tablas sql. 

    Lo que he hecho ha sido lo siguiente, con el siguiente codigo cargaba el articulo en el DGV, y creando un evento en el cual almacenara en una variable el tipo de recargo para posteiormente utilizarlo para los calculos que necesito, una vez asignado los valores a las variables utilizo el siguiente codigo para extraer segun el tipo la suma de la columna.

    private void Sumarrecargo()
            {
                double impre1 = 0;
                double impre2 = 0;
                double impre3 = 0;
                double impre4 = 0;
                
                foreach (DataGridViewRow row in dgvarticulos.Rows)
                {
                    if (chrecargo.Checked == true)
                    {
                        if (Convert.ToDouble(row.Cells["tre"].Value) == varre1)
                        {
                            impre1 += Convert.ToDouble(row.Cells["impre"].Value);
                            
                        }
                        if (Convert.ToDouble(row.Cells["tre"].Value) == varre2)
                        {
                            impre2 += Convert.ToDouble(row.Cells["impre"].Value);
                            
                        }
                        if (Convert.ToDouble(row.Cells["tre"].Value) == varre3)
                        {
                            impre3 += Convert.ToDouble(row.Cells["impre"].Value);
                            
                        }
                        if (Convert.ToDouble(row.Cells["tre"].Value) == varre4)
                        {
                            impre4 += Convert.ToDouble(row.Cells["impre"].Value);
                            
                        }
                    }
                }
                lblimpre1.Text = Math.Round(impre1, 2).ToString();
                lblimpre2.Text = Math.Round(impre2, 2).ToString();
                lblimpre3.Text = Math.Round(impre3, 2).ToString();
                lblimpre4.Text = Math.Round(impre4, 2).ToString();
            }
    Las variables varre1, varre2, varre3, varre4 son las que anteriormente he asignado con los valores 5,2 , 1,4 , 0,5 y 0 que son los tipos de % actuales de impuestos que se cobran en mi pais segun el tipo de articulo. A lo que comentaba Williams sobre que ocurriria si hubiesen mas de 4 valores distintos en la columna, indicar que es poco probable que dicho caso ocurra, a no ser que estatalmente se amplien la cantidad de tipos distintos de impuestos, cosa que en los ultimos 10 años no ha ocurrido, pero en el caso posible, el 4 valor que estamos indicando actualmente no se utiliza o esta marcado como el 0%. Con esto decir, que si seria un problema para otros tipos de casos utilizar este ejemplo, ya que en mi caso esta restringido para solo 4 valores distintos.


    • Marcado como respuesta Gori0056 domingo, 28 de diciembre de 2014 23:21
    domingo, 28 de diciembre de 2014 23:21
  • Todo esto es relativamente sencillo con data binding.  Nada más necesitamos una clase que represente las líneas en el DGV que implemente INotifyPropertyChanged, luego un objeto con el patrón Observer, que ya está hecho y es el BindingList y.... ¡ya!  Me parece que es todo.  Siempre me piden un proyecto de ejemplo así que le hago uno 30 minutos.

    EDICIÓN:

    Listo.  Aquí le dejo un enlace al ZIP.

    La mecánica es bien sencilla:  La primera regla a respetar aquí es:  Siempre tomamos los datos que necesitamos de la colección original.  No debe leerse el valor de las celdas del DGV si se tiene la fuente de datos original.  Los controles como el DGV no están diseñados para almacenar datos; están diseñados para mostrar datos.

    En segundo lugar, aprovechamos Data Binding y creamos una clase SaleItem que representa una línea del DGV.  Por facilidad en el ejemplo yo usé AutoGenerateColumns, pero lo mejor es que las defina manualmente para que ajuste los detallitos.  La clase SaleItem hereda de Entity para heredar las capacidades de INotifyPropertyChanged.

    Finalmente el formulario en el Form_Load se suscribe al evento ListChanged de la lista de items para así recalcular el total cada vez que la lista cambia.  Veo que usted tiene algún requerimiento especial para calcular el total.  Simplemente asegúrese de programar eso en el cálculo de la suma.  El ejemplo que yo hice es un cálculo simple del gran total únicamente.


    Jose R. MCP
    Code Samples


    Muchisimas gracias por tu ayuda.
    domingo, 28 de diciembre de 2014 23:22
  • Muchisimas gracias por tu ayuda

    domingo, 28 de diciembre de 2014 23:23
  • Muchisimas gracias por tu ayuda.
    domingo, 28 de diciembre de 2014 23:23