none
!!! C# Расчет, отображение суммы в DataGridView, запись в таблицу Access RRS feed

  • Вопрос

  • Приветствую!

    Необходима помощь в реализации поставленной задачи озвученной в заголовке темы.

    Есть готовая БД Access с таблицей, которая имеет колонки: цена, количество, сумма. Таблица Access уже имеет данные в перечисленных колонках. Необходимо реализовать расчет в C# (например) по нажатию кнопки.

    Код ниже обновляет старые расчеты например, известна цена и количество, (сумму специально стер), код ниже сумму пересчитает, но по нажатию на кнопку сохранить, не запишет в таблицу Access. А если ввести новые данные то выскочит ошибка (InvalidOperationException : Сбой сопоставления столбцов из SourceColumn "Сумма" из-за того, что DataColumn "Сумма" является вычисляемым столбцом.) Помогите с кодом!

    DataTable dtTabl = appData.Tables["GoodsDelivery"];
                DataColumn Column4 = dtTabl.Columns["Цена"];
                DataColumn Column5 =   dtTabl.Columns["Количество"];
                DataColumn Column6 = dtTabl.Columns["Сумма"];
                Column6.Expression = "Цена*Количество";
                dataGridView.Refresh();


    • Изменено Al.Guru 28 января 2017 г. 14:57
    28 января 2017 г. 14:55

Ответы

  • Так вы определитесь, хотите поле вычисляемое или нет. Если да, сделайте его *в базе* вычисляемым. Если нет, просто посчитайте запросом

    public void CalculateSum()
    {
    	string queryString = "UPDATE myTable SET Summa = Cena * Kolichestvo";
    
    	using (OleDbConnection connection = new OleDbConnection(myConnectionString))
           {
            OleDbCommand command = new OleDbCommand(queryString, connection);
            connection.Open();
            command.ExecuteNonQuery();
    	}	
    	
    }




    • Изменено VadimTagil 28 января 2017 г. 15:19
    • Предложено в качестве ответа AlexFV 28 января 2017 г. 19:10
    • Помечено в качестве ответа Al.Guru 28 января 2017 г. 19:46
    • Снята пометка об ответе Al.Guru 28 января 2017 г. 21:13
    • Помечено в качестве ответа Al.Guru 28 января 2017 г. 21:13
    • Снята пометка об ответе Al.Guru 28 января 2017 г. 21:13
    • Помечено в качестве ответа Al.Guru 28 января 2017 г. 21:13
    • Снята пометка об ответе Al.Guru 28 января 2017 г. 21:13
    • Помечено в качестве ответа Al.Guru 28 января 2017 г. 21:13
    28 января 2017 г. 15:12
  • "Если я Вас правильно понял, то необходимо в ту же кнопку добавить строку для заполнения"

    +

    "Обновление DGV происходит только после повторного нажатия кнопки"

    странно... возможно не срабатывает из-за какого-то кэширования в OleDb

    попробуйте после ExecuteNonQuery вставить connection.Close();

    • Помечено в качестве ответа Al.Guru 28 января 2017 г. 19:46
    28 января 2017 г. 18:16
  • "обновляется сумма на старых данных,  на новых нет."

    Так может надо просто вызвать dataGridView.EndEdit(); перед обновлением

    Если dataGridView привязана к BindingSource, также вызвать bindingSource.EndEdit();

    • Помечено в качестве ответа Al.Guru 29 января 2017 г. 13:10
    29 января 2017 г. 7:21

Все ответы

  • Так вы определитесь, хотите поле вычисляемое или нет. Если да, сделайте его *в базе* вычисляемым. Если нет, просто посчитайте запросом

    public void CalculateSum()
    {
    	string queryString = "UPDATE myTable SET Summa = Cena * Kolichestvo";
    
    	using (OleDbConnection connection = new OleDbConnection(myConnectionString))
           {
            OleDbCommand command = new OleDbCommand(queryString, connection);
            connection.Open();
            command.ExecuteNonQuery();
    	}	
    	
    }




    • Изменено VadimTagil 28 января 2017 г. 15:19
    • Предложено в качестве ответа AlexFV 28 января 2017 г. 19:10
    • Помечено в качестве ответа Al.Guru 28 января 2017 г. 19:46
    • Снята пометка об ответе Al.Guru 28 января 2017 г. 21:13
    • Помечено в качестве ответа Al.Guru 28 января 2017 г. 21:13
    • Снята пометка об ответе Al.Guru 28 января 2017 г. 21:13
    • Помечено в качестве ответа Al.Guru 28 января 2017 г. 21:13
    • Снята пометка об ответе Al.Guru 28 января 2017 г. 21:13
    • Помечено в качестве ответа Al.Guru 28 января 2017 г. 21:13
    28 января 2017 г. 15:12
  • VadimTagil

    Расчет должен произойти на форме в C#, в datagridview по нажатию кнопки [обновить сумму], с дальнейшей записью этого расчета в БД Access в те же колонки ...цена, количество, сумма. 

    В вашем коде выше: myConnectionString = строке подключения?

    Типо: @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + @"name.accdb"



    • Изменено Al.Guru 28 января 2017 г. 15:44
    28 января 2017 г. 15:36
  • В вашем коде выше: myConnectionString = строке подключения?

    Типо: @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + @"name.accdb"



    Да (можно использовать OleDbConnectionStringBuilder)
    28 января 2017 г. 16:00
  • По нажатию на кнопку, вообще ничего не происходит. Что я делаю не так?

    private void btnUpdateSum_Click(object sender, EventArgs e)
            {
                string queryString = "UPDATE GoodsDelivery SET Сумма = Цена * Количество";
                using (OleDbConnection connection = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + @"name.accdb"))
                {
                    OleDbCommand command = new OleDbCommand(queryString, connection);
                    connection.Open();
                    command.ExecuteNonQuery();
                }	
            }

    з.ы.

    Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\\name.accdb - не измененный



    • Изменено Al.Guru 28 января 2017 г. 16:16
    28 января 2017 г. 16:12
  • Вру...

    Запись происходит в таблицу Access по старым значениям. То есть там где я убрал ручками сумму, происходит расчет в тихую и данные пишутся в таблицу Access. На форме C# в datagridview ничего не происходит. Новые данные вносятся в Access только после сохранения данных без отображения расчета в datagridview, и нажатия обновить сумму. 

    ***

    Осталось связать datagridview с обновлением сумм в реальном времени, datagridview.refresh(); и ...update();  ...не срабатывают.



    • Изменено Al.Guru 28 января 2017 г. 17:04
    28 января 2017 г. 16:43
  • Естественно, после расчета данные нужно снова загрузить в программу. У меня же нет телепатии понять как вы данные загружаете. Если через TableAdapter, надо вызвать метод Fill. 
    28 января 2017 г. 17:13
  • Я извиняюсь за ограниченую информацию, вы скажите что необходимо предоставить, мигом организую. Подключения происходят через TableAdapter. Если я Вас правильно понял, то необходимо в ту же кнопку добавить строку для заполнения. Обновление DGV происходит только после повторного нажатия кнопки. Вот обновленный код кнопки:

    private void btnUpdateSum_Click(object sender, EventArgs e)
            {
                string queryString = "UPDATE GoodsDelivery SET Сумма = Цена * Количество";
                using (OleDbConnection connection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=name.accdb"))
                {
                    OleDbCommand command = new OleDbCommand(queryString, connection);
                    connection.Open();
                    command.ExecuteNonQuery();
                    this.goodsDeliveryTableAdapter.Fill(this.appData.GoodsDelivery);
                    dataGridView.Refresh();
                }	
            } 


    • Изменено Al.Guru 28 января 2017 г. 17:59
    28 января 2017 г. 17:56
  • "Если я Вас правильно понял, то необходимо в ту же кнопку добавить строку для заполнения"

    +

    "Обновление DGV происходит только после повторного нажатия кнопки"

    странно... возможно не срабатывает из-за какого-то кэширования в OleDb

    попробуйте после ExecuteNonQuery вставить connection.Close();

    • Помечено в качестве ответа Al.Guru 28 января 2017 г. 19:46
    28 января 2017 г. 18:16
  • Да все работает, спасибо! Теперь данные обновляет после первого нажатия.

    Маленький незначительный нюансик...

    Что бы обновить данные необходимо сохраниться иначе при нажатии на кнопку [обновить] таблица убегает на первую запись и введенные новые данные слетают. Может ли это происходить в другой последовательности? С начало обновить сумму, а потом сохранить данные.

    28 января 2017 г. 18:23
  • Если просчитывать без сохранения в базу, тогда надо по другому делать:

    DataTable dt=this.appData.GoodsDelivery;
    object val;
    decimal cena,kolichestvo;
    
    foreach(DataRow row in dt){
    
    	val=row["Цена"];	
    	if(val==DBNull.Value)continue;
    	else cena=(decimal)val;
    	
    	val=row["Количество"];	
    	if(val==DBNull.Value)continue;
    	else kolichestvo=(decimal)val;
    	
    	row["Сумма"]=cena*kolichestvo;
    }
    
    dataGridView.Refresh();

    28 января 2017 г. 18:46
  • Хотел попробовать метод №2 но пишет что оператор foreach не работает с переменными типа  "System.Data.Data.Table" поскольку "System.Data.Data.Table" не содержит открытого определения для "GetEnumerator".

    28 января 2017 г. 19:11
  • foreach(DataRow row in dt.Rows)
    28 января 2017 г. 19:47
  • foreach(DataRow row in dt.Rows)
    InvalidCastException не обработано ругается на эту строку:  else cena = (decimal)val;
    28 января 2017 г. 19:55
  • тогда измените decimal на тип который используется в базе, или пропишите cena = Convert.ToDecimal(val);

    28 января 2017 г. 20:03
  • Угу именно там ошибка и была... в БД использую double, пока крутил чего да как скудные познания позволили сообразить что дело в этом, изменил, начало ругаться на: ReadOnlyException Столбец "Сумма" доступен только для чтения. Нашел колонку в схеме данных изменил с true на false заработало. Но все равно немножечко не то. 

    Хотелось, что бы работало так.

    В DGV ввожу цену и количество, нажимаю [обновить] происходит подсчет и показывает сумму, потом жму сохранить. А на деле работает так. Ввожу новые данные, жму кнопку [обновить], обновляется сумма на старых данных, на новых нет. Жму сохранить новые значения(цена/количество), их сохраняет без расчета в колонке Сумма. Потом снова жму [обновить], в этот момент, обновляется Сумма прежде введенных (новых) данных в DGV, ну и что бы сохранить полученную сумму, снова необходимо нажать сохранить.






    • Изменено Al.Guru 28 января 2017 г. 21:24
    28 января 2017 г. 20:48
  • "обновляется сумма на старых данных,  на новых нет."

    Так может надо просто вызвать dataGridView.EndEdit(); перед обновлением

    Если dataGridView привязана к BindingSource, также вызвать bindingSource.EndEdit();

    • Помечено в качестве ответа Al.Guru 29 января 2017 г. 13:10
    29 января 2017 г. 7:21
  • "обновляется сумма на старых данных,  на новых нет."

    Так может надо просто вызвать dataGridView.EndEdit(); перед обновлением

    Если dataGridView привязана к BindingSource, также вызвать bindingSource.EndEdit();

    Вот теперь работает именно так, как необходимо было. Спасибо за знания и ваше терпение.
    • Изменено Al.Guru 29 января 2017 г. 13:10
    29 января 2017 г. 13:07