none
Group By e SUM em DataTable RRS feed

  • Pergunta

  • Pessoal, como faço para agrupar linhas em um DataTable??

    tenho esse DataTable

     DataTable vinhosParaCotar = new DataTable();

                vinhosParaCotar.Columns.Add("VINHO",  Type.GetType("System.String"));
                vinhosParaCotar.Columns.Add("QTD", Type.GetType("System.Int32"));

    eu adiciono valores

                

    DataRow linha;

                linha = vinhosParaCotar.NewRow();
                linha["VINHO"] = vinho;
                linha["QTD"] = qtd;

          vinhosParaCotar.Rows.Add(linha);

    depois preciso agrupar por vinho e somar a quantidade para exibir num grid, só posso fazer isso pela aplicação devido a regra de negócio, se fosse pelo SQL era mais fácil.

    Como posso fazer isso??

    Valeu!!!

    Estou usando C# 4.0 com ASP.NET 



    sábado, 31 de agosto de 2013 06:13

Respostas

  • Olá Diego,

    Você pode converter seu DataTable em um IEnumerable<DataRow> usando do método AsEnumerable() e usar do método LINQ para agrupar e somar, veja:

    vinhosParaCotar.Columns.Add("VINHO", Type.GetType("System.String"));
    vinhosParaCotar.Columns.Add("QTD", Type.GetType("System.Int32"));
    
    vinhosParaCotar.Rows.Add("Vinho A", 1);
    vinhosParaCotar.Rows.Add("Vinho A", 2);
    vinhosParaCotar.Rows.Add("Vinho A", 3);
    vinhosParaCotar.Rows.Add("Vinho B", 4);
    vinhosParaCotar.Rows.Add("Vinho B", 5);
    vinhosParaCotar.Rows.Add("Vinho C", 1);
    
    var agrupado = vinhosParaCotar
        .AsEnumerable()
        .GroupBy(f => f.Field<string>("VINHO"))
        .Select(f => new 
        { 
            Vinho = f.Key, 
            Quantidade = f.Sum(s => s.Field<int>("QTD")) 
        });
    
    foreach (var item in agrupado)
    {
        Console.WriteLine("{0}{1}", "Vinho: " + item.Vinho.PadRight(30), "Quantidade: " + item.Quantidade);
    }
    
    Console.Read();


    Vitor Mendes | http://www.vitormendes.com.br/

    "Ajuda teu semelhante a levantar a sua carga, porém, não a carregá-la." (Pitágoras)

    sábado, 31 de agosto de 2013 16:12

Todas as Respostas

  • Diego, no caso essas variável "vinho" e "qtd" vem de onde?

    Já pensou em fazer um loop utilizando um list auxiliar para ir gravando as informações nele e depois jogar os dados já consolidados do list nas suas Rows do DataTable?


    "A vida é um paraíso, mas os homens não o sabem e não se preocupam em sabê-lo." Fiodor Dostoievski

    sábado, 31 de agosto de 2013 14:08
  • quando carrega a pagina pela primeira vez eu formo o DataTable, depois conforme ele escolhe o vinho (que vem do banco) em um DropDownList e coloca a quantidade em textbox eu chamo um método que adiciona no DataTable...depois que adiciono, vem a grande chave, que é agrupar por vinho e somar a quantidade, eu preciso fazer isso exibindo no grid como se fosse uma prévia para o usuário, quando ele confirmar, eu gravarei os dados no banco...como seria isso do List Kanaãm? estou aberto a ideias também....
    sábado, 31 de agosto de 2013 15:29
  • Então Diego, dá para fazer o seguinte, monta um List ou um array bidimensional que contenha na posição array[i][1] o código do produto e no campo array[i][2] a quantidade.

    Toda vez que o usuário escolher o vinho e selecionar a quantidade, você procura esse código no array, caso já exista, você apenas soma a quantidade, caso contrário, você adiciona o produto e a quantidade no array, depois disso, você atualiza o seu datatable com os dados do array.

    Você vai estar forçando uma sumarização dos dados antes de jogá-los no seu datatable de exibição do resumo.

    Acho que isso deve resolver seu problema.


    "A vida é um paraíso, mas os homens não o sabem e não se preocupam em sabê-lo." Fiodor Dostoievski

    sábado, 31 de agosto de 2013 15:39
  • Olá Diego,

    Você pode converter seu DataTable em um IEnumerable<DataRow> usando do método AsEnumerable() e usar do método LINQ para agrupar e somar, veja:

    vinhosParaCotar.Columns.Add("VINHO", Type.GetType("System.String"));
    vinhosParaCotar.Columns.Add("QTD", Type.GetType("System.Int32"));
    
    vinhosParaCotar.Rows.Add("Vinho A", 1);
    vinhosParaCotar.Rows.Add("Vinho A", 2);
    vinhosParaCotar.Rows.Add("Vinho A", 3);
    vinhosParaCotar.Rows.Add("Vinho B", 4);
    vinhosParaCotar.Rows.Add("Vinho B", 5);
    vinhosParaCotar.Rows.Add("Vinho C", 1);
    
    var agrupado = vinhosParaCotar
        .AsEnumerable()
        .GroupBy(f => f.Field<string>("VINHO"))
        .Select(f => new 
        { 
            Vinho = f.Key, 
            Quantidade = f.Sum(s => s.Field<int>("QTD")) 
        });
    
    foreach (var item in agrupado)
    {
        Console.WriteLine("{0}{1}", "Vinho: " + item.Vinho.PadRight(30), "Quantidade: " + item.Quantidade);
    }
    
    Console.Read();


    Vitor Mendes | http://www.vitormendes.com.br/

    "Ajuda teu semelhante a levantar a sua carga, porém, não a carregá-la." (Pitágoras)

    sábado, 31 de agosto de 2013 16:12
  • Vitor, muito obrigado, funcionou perfeitamente, depois usei uma função que utiliza reflection para transformar a variável agrupado em DataTable, vou compartilhar a  função, agradeço ao Kanaãm também pela sugestão, bom final de semana a vocês!!! Abraço!

      public DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
            {
                DataTable dtReturn = new DataTable();
    
                // column names 
                PropertyInfo[] oProps = null;
    
                if (varlist == null) return dtReturn;
    
                foreach (T rec in varlist)
                {
                    // Use reflection to get property names, to create table, Only first time, others will follow 
                    if (oProps == null)
                    {
                        oProps = ((Type)rec.GetType()).GetProperties();
                        foreach (PropertyInfo pi in oProps)
                        {
                            Type colType = pi.PropertyType;
    
                            if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition()
                            == typeof(Nullable<>)))
                            {
                                colType = colType.GetGenericArguments()[0];
                            }
    
                            dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
                        }
                    }
    
                    DataRow dr = dtReturn.NewRow();
    
                    foreach (PropertyInfo pi in oProps)
                    {
                        dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue
                        (rec, null);
                    }
    
                    dtReturn.Rows.Add(dr);
                }
                return dtReturn;
            }

    sábado, 31 de agosto de 2013 17:57