Usuário com melhor resposta
Group By e SUM em DataTable

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
- Editado Diego de Oliveira Neves sábado, 31 de agosto de 2013 06:15 s
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)
- Marcado como Resposta Diego de Oliveira Neves sábado, 31 de agosto de 2013 17:53
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
-
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....
-
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
-
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)
- Marcado como Resposta Diego de Oliveira Neves sábado, 31 de agosto de 2013 17:53
-
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; }