none
Executar um DataReader para ler todos os valores na tabela e executar a soma RRS feed

  • Pergunta

  • Boa noite pessoal,

    Necessito da ajuda dos especialistas, estou fazendo um projeto onde Executo um Form com Relatório de um DRE (Demonstrativo de Resultado do Exercício) no período.

    Sendo assim, vou ter que fazer a "varredura" de vários  itens nas tabelas e gerar a soma no perído

    Exemplificando: Necessito fazer a leitura na tabela de "parcelas pagas" todos os alugueis pagos naquele período.

    Existe uma tabela com os códigos das despesas, neste exemplo usei o "9".

    Segue o meu código, que não está funcionando e está caindo na MessageBox com o " Error!"

    Anexo também o resultado da tabela e a execução da Query. Ajudem-me por favor.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Data.SqlClient;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace SGFRenaissance
    {
        public partial class Form_DRE_Exercicio : Form
        {
            SqlConnection conn = new SqlConnection("Data Source=DESKTOP-3O98051;Initial Catalog=SGFRenaissance;Integrated Security=True");
            SqlCommand cmd;
            SqlDataAdapter adapt;
            decimal totalrevenues = 0;
            decimal totalCMV = 0;
            decimal totalTaxes = 0;
            decimal comissions = 0;
            decimal RentTotal = 0;
            decimal RentTotalExpenses;
            DateTime dateinicial;
            DateTime datefinal;
    
            public Form_DRE_Exercicio()
            {
                InitializeComponent();
            }
    
            void SelectRentFromTable()
            {
                try
                {
    
                    String StrConn;
                    StrConn = @"Data Source=DESKTOP-3O98051;Initial Catalog=SGFRenaissance;Integrated Security=True";
                    SqlConnection sqlConnection = new SqlConnection(StrConn);
                    DateTime inicialdate; // para Conversão da data inicial
                    DateTime finaldate; // para conversão da data final
                    inicialdate = Convert.ToDateTime(mtbinicio.Text); //Caixa de texto Maskedtextbox - Data inicial
                    finaldate = Convert.ToDateTime(mtbfinal.Text); // Caixa de texto MaskedTextbox - Data final
                    sqlConnection.Open();
                    string sql = string.Format("select  Cod_Despesa, Valor_Pago from Base_Parcelas_Pagas where Cod_Despesa = 9 and Data_Pagamento Between ='inicialdate'and 'finaldate'"); // uso a variável ou não ?
                    SqlCommand sqlComm = new SqlCommand(sql, sqlConnection);
                    SqlDataReader reader = sqlComm.ExecuteReader();
                    while (reader.Read())
                    {
                        string dr = reader["Valor_Pago"].ToString();
                        Convert.ToDecimal(dr);
                        RentTotalExpenses = RentTotalExpenses + Convert.ToDecimal(dr);
                        RentTotal = RentTotalExpenses;
                    }
    
                    sqlConnection.Close();
    
                }
                catch  (Exception Ex)
                {
                    MessageBox.Show("Error!");
    
                }
    
            }
    
    
            private void btn_fechar_Click(object sender, EventArgs e)
            {
                this.Close();
                this.Dispose();
            }
    
            private void button_execute_Click(object sender, EventArgs e)
            {
                SelectRentFromTable();
                textBoxRent.Text = Convert.ToString(RentTotal);
            }
           
        }
    }
    

    AAgora segue os dados da Tabela e o resultado da Query

    Use SGFRenaissance
    Select Cod_Base_Titulos_Pagos, Cod_Despesa, Valor_Pago from Base_Parcelas_Pagas Where  Cod_Despesa = 9 and Data_Pagamento Between '2019-07-20'  and '2019-08-03' 
    
    Cod_Base_Titulos  Cod_Despesa  Valor_Pago
    
    35	            9	       300.00
    35	            9	       1000.00
    35	            9	       1000.00
    38	            9          3000.00
    45	            9	       90.25
    45	            9          4700.00
    78	            9          1515.95
    79	            9	       1515.95
    80	            9          1015.95
    
    

    Estou necessitando fazer a soma destes valores (que é o resultado do Select no período, digitado nos mtbinicio e mtbfinal.

    Agradeço desde já a ajuda de todos.

    Att.

    Flávio Rocha.

    quarta-feira, 20 de novembro de 2019 01:51

Respostas

  • Bom dia,

    O erro "Conversion failed When converting date...", é um erro do banco de dados. Você pode perceber isso, porque esse erro é lançado no "ExecuteScalar()", isso indica um erro na consulta. Assim, se os parâmetros que você está passando estão corretos (dateinicial e datefinal) os componentes que você usou no formulário não são o problema.

    Apenas altere sua query e remova os apóstrofos: 

    De : ... Between '@inicialdate'and '@finaldate'

    Para : ... Between @inicialdate and @finaldate
    • Marcado como Resposta F.oliveirarocha quinta-feira, 28 de novembro de 2019 02:48
    terça-feira, 26 de novembro de 2019 11:41

Todas as Respostas

  • Bom dia F.Oliveira, 
    Aparentemente, o problema é na parte: 

    "string sql = string.Format("select  Cod_Despesa, Valor_Pago from Base_Parcelas_Pagas where Cod_Despesa = 9 and Data_Pagamento Between ='inicialdate'and 'finaldate'");"

    Tem um sinal de igual que não deveria ter depois de between, e as variáveis de data não estão sendo passadas dessa forma. Tente fazer algumas alterações e passar as variáveis como parâmetros do objeto SqlCommand. Algo assim:

    string sql = string.Format("select  Cod_Despesa, Valor_Pago from Base_Parcelas_Pagas where Cod_Despesa = 9 and Data_Pagamento Between @inicialDate and @finalDate"); 
    SqlCommand sqlComm = new SqlCommand(sql, sqlConnection);
    sqlComm.Parameters.Add(new SqlParameter("inicialDate", inicialdate));
    sqlComm.Parameters.Add(new SqlParameter("finalDate", finaldate));

    Espero ter ajudado.

    • Sugerido como Resposta IgorFKModerator quarta-feira, 20 de novembro de 2019 12:14
    quarta-feira, 20 de novembro de 2019 12:05
  • Boa Noite João,

    Obrigado pela atenção, vamos aos problemas.

    Fiz as alterações sugeridas e estou postando abaixo, mas agora estou tendo um erro de referência "null reference exeption" na linha 46, quando entra a data final. 

    "Referencia de um objeto não definida para a instância de um objeto"

    Dizem que é um erro de instância, mas não percebi onde está faltando instanciar.

    1-Gostaria de saber se vc pode me ajudar neste código.

    2-Não tenho certeza de como fazer a verredura da tabela está correto o código das linhas seguintes dentro do While?

    3-Recebi um outro post, dizendo que era melhor já fazer a soma no Select  do valor pago. 

    Seria tipo ( "select  Cod_Despesa, SUM(Valor_Pago) from ...."); daria certo? já recebria o valor somado?

      void SelectRentFromTable()
            {
                try
                {
    
                    String StrConn;
                    StrConn = @"Data Source=DESKTOP-3O98051;Initial Catalog=SGFRenaissance;Integrated Security=True";
                    SqlConnection sqlConnection = new SqlConnection(StrConn);
                    sqlConnection.Open();
                    string sql = string.Format("select  Cod_Despesa, Valor_Pago from Base_Parcelas_Pagas where Cod_Despesa = 9 and Data_Pagamento Between ='@inicialdate'and '@finaldate'");
                    SqlCommand sqlComm = new SqlCommand(sql, sqlConnection);
                    DateTime dateinicial = Convert.ToDateTime(mtbinicio.Text);
                    cmd.Parameters.AddWithValue("@inicialdate", dateinicial);
                    DateTime datefinal = Convert.ToDateTime(mtbfinal.Text);
                    cmd.Parameters.AddWithValue("@finaldate", datefinal);
                    SqlDataReader reader = sqlComm.ExecuteReader();
                    while (reader.Read())
                    {
                        string dr = reader["Valor_Pago"].ToString();
                        Convert.ToDecimal(dr);
                        RentTotalExpenses = Convert.ToDecimal(dr);
                        RentTotal = RentTotalExpenses + RentTotalExpenses; 
                    }
    
                    sqlConnection.Close();
    
                }
                catch  (Exception Ex)
                {
                    MessageBox.Show("Error!" + Ex.Message);
    
                }
    
            }

    Fiz algumas alterações na ordem e na definição das datas, para receber o parâmetro exatamente antes de executar.

    Muito Obrigado pela sua atenção.

    sexta-feira, 22 de novembro de 2019 02:24
  • Bom dia, o problema do erro "Referencia de um objeto não definida para a instância de um objeto" é que você está usando um objeto chamado sqlComm, e atribuindo os valores no objeto cmd. Como esse cmd não foi instanciado, apresenta esse erro, só trocar para sqlComm que deve funcionar.

    Realmente trazer os valor somado do banco de dados, acho a melhor opção. Você pode fazer as alterações e usar a função ExecuteScalar para trazer um único valor de retorno.
    Mais ou menos assim:

    string sql = string.Format("select SUM(Valor_Pago) from Base_Parcelas_Pagas where Cod_Despesa = 9 and Data_Pagamento Between @inicialdate and @finaldate");
    SqlCommand sqlComm = new SqlCommand(sql, sqlConnection);
    
    DateTime dateinicial = Convert.ToDateTime(mtbinicio.Text);
    sqlComm.Parameters.AddWithValue("@inicialdate", dateinicial);
    DateTime datefinal = Convert.ToDateTime(mtbfinal.Text);
    sqlComm.Parameters.AddWithValue("@finaldate", datefinal);
    
    float valorPago = (float)sqlComm.ExecuteScalar();


    • Editado João Otávio A sexta-feira, 22 de novembro de 2019 12:17 alteração no código
    sexta-feira, 22 de novembro de 2019 12:15
  • João bom dia,

    Obrigado pela atenção.

    Estamos quase lá. Fiz as alterações mas temos que resolver o SQL:

    1 -Fiz a consulta no SQL para ver se funciona, então SÓ FUNCIONA ASSIM, COLOCANDO O "as":

    Use SGFRenaissance
    Select SUM(Valor_Pago) as TotalValorPago from Base_Parcelas_Pagas Where  Cod_Despesa = 9 and Data_Pagamento Between '2019-07-20'  and '2019-08-03'; 

    Executou beleza - retornou o valor de 14138.10

    2- depois das alterações (segue o código abaixo) estou recebendo uma mensagem de  erro, que deve ser no SQL do parênteses:

    Mensagem: "Error! Incorrect syntax near '=' .

    Na linha 49 que é na linha depois do '=' , ou seja quando faz o executescalar

    depois que executa dá o erro.

    3- Tentei colocar "as Total" e tbm o ExecuteNonQuery e o erro continua.

    A mensagem aparece o valor fica "0" mas o programa não aborta. Deve ser no SQL certo?

    A parte de cima continua igual.
    
     void SelectRentFromTable()
            {
                try
                {
    
                    String StrConn;
                    StrConn = @"Data Source=DESKTOP-3O98051;Initial Catalog=SGFRenaissance;Integrated Security=True";
                    SqlConnection sqlConnection = new SqlConnection(StrConn);
                    sqlConnection.Open();
                    string sql = string.Format("select SUM(Valor_Pago) from Base_Parcelas_Pagas where Cod_Despesa = 9 and Data_Pagamento Between ='@inicialdate'and '@finaldate'");
                    SqlCommand sqlComm = new SqlCommand(sql, sqlConnection);
                    DateTime dateinicial = Convert.ToDateTime(mtbinicio.Text);
                    sqlComm.Parameters.AddWithValue("@inicialdate", dateinicial);
                    DateTime datefinal = Convert.ToDateTime(mtbfinal.Text);
                    sqlComm.Parameters.AddWithValue("@finaldate", datefinal);
                    float TotalValorPago = (float)sqlComm.ExecuteScalar();
                    Decimal RentTotal = Convert.ToDecimal(TotalValorPago); // No debug o erro acontece aqui, depois do ExecuteScalar.
                    sqlConnection.Close();
    
                }
                catch  (Exception Ex)
                {
                    MessageBox.Show("Error!" + Ex.Message);
    
                }
    
            }
    
    
            private void btn_fechar_Click(object sender, EventArgs e)
            {
                this.Close();
                this.Dispose();
            }
    
            private void button_execute_Click(object sender, EventArgs e)
            {
                SelectRentFromTable();
                textBoxRent.Text = Convert.ToString(RentTotal);
            }
           
        }

    Agradeço sua atenção desde já.

    Obrigado.

    Flávio Rocha.


    Flavio Rocha.


    domingo, 24 de novembro de 2019 13:30
  • João,

    A execução no SQL Server também funciona com o seguinte select:

    Use SGFRenaissance
    Select SUM(Valor_Pago) as TotalValorPago from Base_Parcelas_Pagas Where  (Cod_Despesa = 9) and Data_Pagamento Between '2019-07-20'  and '2019-08-03'; 

    Retorna: 14138.10

    Abraços e obrigado.

    domingo, 24 de novembro de 2019 13:52
  • Bom dia, o erro "Incorrect syntax near '='." é que não é necessário colocar esse "=" depois de between:

    string sql = string.Format("select  Cod_Despesa, Valor_Pago from Base_Parcelas_Pagas where Cod_Despesa = 9 and Data_Pagamento Between = '@inicialdate' and '@finaldate'");

    O fato de só funcionar colocando o "AS", eu realmente não conheço, mas se você conseguiu executar no Management Studio e se obteve a resposta que precisa já é um avanço. Só precisa conseguir pegar esse valor na aplicação agora.

    Qualquer dúvida, estou à disposição.

    segunda-feira, 25 de novembro de 2019 11:38
  • João boa noite,

    Show, a mensagem de erro do "=" sumiu, porém agora estou tendo outra mensagem que é a de conversão da data, vc pode me ajudar nisso tbm?

    Error! Conversion failed When converting date and/or time from character string

    porém estou fazendo as devidas conversões, até mudei para o DateTimePicker mas não ajudou muito. Tirei o Masked Text Box. Alterei o código veja se consegue matar o problema. Conversão de data é uma guerra nesse visual Studio.

    Coloquei o custom Format na Propriedade =     (3 espaços em branco). Quero que o formulário comece com as datas em branco (vazias).

    O form está iniciando com as datas da Propriedade value = 01/01/2019. 

    Como faço para fazer as conversões sem erro ? Estou quase mudando para uma caixa de texto.

     void SelectRentFromTable()
            {
                try
                {
                   
                    String StrConn;
                    StrConn = @"Data Source=DESKTOP-3O98051;Initial Catalog=SGFRenaissance;Integrated Security=True";
                    SqlConnection sqlConnection = new SqlConnection(StrConn);
                    sqlConnection.Open();
                    string sql = string.Format("select SUM(Valor_Pago) from Base_Parcelas_Pagas where (Cod_Despesa = 9) and Data_Pagamento Between '@inicialdate'and '@finaldate'");
                    SqlCommand sqlComm = new SqlCommand(sql, sqlConnection);
    
                    DateTime dateinicial = Convert.ToDateTime(dtpInicio.Value.ToShortDateString());
                    sqlComm.Parameters.AddWithValue("@inicialdate", dateinicial);
    
                    DateTime datefinal = Convert.ToDateTime(dtpFinal.Value.ToShortDateString());
                    sqlComm.Parameters.AddWithValue("@finaldate", datefinal);
    
                    float TotalValorPago = (float)sqlComm.ExecuteScalar();
                    Decimal RentTotal = Convert.ToDecimal(TotalValorPago);
                    sqlConnection.Close();
    
                }
                catch  (Exception Ex)
                {
                    MessageBox.Show("Error!" + Ex.Message);
    
                }
    
            }
    
    
            private void btn_fechar_Click(object sender, EventArgs e)
            {
                this.Close();
                this.Dispose();
            }
    
            private void button_execute_Click(object sender, EventArgs e)
            {
                SelectRentFromTable();
                textBoxRent.Text = Convert.ToString(RentTotal);
            }
    
            private void dtpInicio_ValueChanged(object sender, EventArgs e)
            {
                dtpInicio.CustomFormat = "dd/MM/yyyy";
            }
    
            private void dtpFinal_ValueChanged(object sender, EventArgs e)
            {
                dtpFinal.CustomFormat = "dd/MM/yyyy";
            }
    
            private void Form_DRE_Exercicio_Load(object sender, EventArgs e)
            {
                dtpInicio.CustomFormat = "   ";
                dtpFinal.CustomFormat = "   ";
                dtpInicio.CustomFormat = null;
                dtpFinal.CustomFormat =null;
    
    
            }
        }

    Agradeço mais uma vez pela sua atenção. 

    Estou ansioso para ver o resultado final na caixa de texto.

    Muito obrigado.

    terça-feira, 26 de novembro de 2019 02:26
  • Bom dia,

    O erro "Conversion failed When converting date...", é um erro do banco de dados. Você pode perceber isso, porque esse erro é lançado no "ExecuteScalar()", isso indica um erro na consulta. Assim, se os parâmetros que você está passando estão corretos (dateinicial e datefinal) os componentes que você usou no formulário não são o problema.

    Apenas altere sua query e remova os apóstrofos: 

    De : ... Between '@inicialdate'and '@finaldate'

    Para : ... Between @inicialdate and @finaldate
    • Marcado como Resposta F.oliveirarocha quinta-feira, 28 de novembro de 2019 02:48
    terça-feira, 26 de novembro de 2019 11:41
  • João boa noite,

    Fiz a alteração, e agora aparece outra mensagem em português:

    "Error! Conversão especificada não é válida"

    O que fazer? É uma luta fazer conversão de DateTime 

    Será porque não estou usando o Globalization?

    Aguardo sua ajuda mais uma vez.

    Muito obrigado pela sua atenção.

    quarta-feira, 27 de novembro de 2019 01:41
  • Joaõ boa noite,

    Consegui resolver a mensagem de erro.

    Muito obrigado pela sua ajuda.

    Segue abaixo o codigo corrigido.

    Abraços e obrigado.

      void SelectRentFromTable()
            {
                try
                {
                   
                    String StrConn;
                    StrConn = @"Data Source=DESKTOP-3O98051;Initial Catalog=SGFRenaissance;Integrated Security=True";
                    SqlConnection sqlConnection = new SqlConnection(StrConn);
                    sqlConnection.Open();
                    string sql = string.Format("select SUM(Valor_Pago) from Base_Parcelas_Pagas where Cod_Despesa = 9 and Data_Pagamento Between @inicialdate and @finaldate");
                    SqlCommand sqlComm = new SqlCommand(sql, sqlConnection);
    
                    DateTime dateinicial = Convert.ToDateTime(dtpInicio.Value.ToShortDateString());
                    sqlComm.Parameters.Add("@inicialdate", dateinicial);
    
                    DateTime datefinal = Convert.ToDateTime(dtpFinal.Value.ToShortDateString());
                    sqlComm.Parameters.Add("@finaldate", datefinal);
    
                    //   float TotalValorPago = (float)sqlComm.ExecuteScalar();
                    var TotalValorPago = sqlComm.ExecuteScalar();
                    RentTotal = Convert.ToDecimal(TotalValorPago);
                    sqlConnection.Close();
    
                }
                catch  (Exception Ex)
                {
                    MessageBox.Show("Error!" + Ex.Message);
    
                }
    
            }
    

    quinta-feira, 28 de novembro de 2019 02:50