I want to show sum of total Price of items. I am facing 2 issues:
It's showing me wrong total of items price
I want to add .00 to the total price
You can check issue in the image for a clear explanation.
Here is my code:
tDisplay.Text = "Return/" + "Receipt No:" + Return_Form.setalueforText011;
label1.Text = Return_Form.setalueforText011;
OleDbConnection VCON = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\Restaurant.accdb");
DataSet dsa = new DataSet();
DataTable dt = new DataTable();
dsa.Tables.Add(dt);
OleDbDataAdapter da = new OleDbDataAdapter();
da = new OleDbDataAdapter("SELECT [Column1],[Column2],[Column3] from [Total] Where [Receipt No] = " + label1.Text + "", VCON);
da.Fill(dt);
//dataGridView1.DataSource = dt;
for (int i = 0; i < dt.Rows.Count; i++)
{
products.Add(new tblProduct() { productName = dt.Rows[i]["Column2"].ToString(),productPrice = Convert.ToDecimal(Math.Round(Convert.ToDecimal(dt.Rows[i]["Column1"].ToString())))});
label3.Text = dt.Rows[i]["Column3"].ToString();
textBox59.Text = "Rs: "+String.Format("{0:}", Total);
tblProduct selected = (tblProduct)(listBox60.SelectedItem);
Total += (decimal)selected.productPrice;
}
VCON.Close();
In your loop you add to the total always the SelectedItem row. This is always the first item so you end up doubling the value of the first item.
for (int i = 0; i < dt.Rows.Count; i++)
{
// Create and initialize a new tblProduct from the datatable row
tblProduct current = new tblProduct();
current.ProductName = dt.Rows[i]["Column2"].ToString();
current.productPrice = Convert.ToDecimal(Math.Round(Convert.ToDecimal(dt.Rows[i]["Column1"].ToString())));
// Add to your list of products
products.Add(current);
// This line is wrong because you overwrite the value at each loop
label3.Text = dt.Rows[i]["Column3"].ToString();
// Sum the price of the current tblProduct
Total += (decimal)current.productPrice;
}
// Outside the loop update your total label
textBox59.Text = "Rs: "+String.Format("{0:0.00}", Total);
If you allow me to give an advice. Do not name your controls that way. They are unreadable and not easily recognizable. Looking at this code some day from now you will have a lot of problems to remember which control is textBox59 or listBox60.
Sum
Instead of using for loop, You can simply use Compute method of data table and pass an expression to compute. For example:
var total = yourDataTable.Compute("SUM(Column1)", "");
Format
Also to format total to show 2 digits after decimal place, you can use either of these options:
The "0" Custom Numeric Format String : string.Format("{0:0.00}", total))
The Fixed-Point "F" format Specifier: string.Format("{0:F2}", total))
Update Sum on changes of data
Also to be able to show the sum automatically in a TextBox event when new items added or some items removed or some values changed, handle ListChanged event of DataTable.DefaultView and set the result as Text of the text box.
Example
// Define data table
var dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Price", typeof(int));
// Fill data
dt.Rows.Add("Product 1", 100);
dt.Rows.Add("Product 2", 200);
// Set data source of data grid view
this.dataGridView1.DataSource = dt;
// Automatically update text box, by SUM of price
textBox1.Text = $"{dt.Compute("SUM(Price)", ""):F2}";
dt.DefaultView.ListChanged += (obj, args) =>
textBox1.Text = $"{dt.Compute("SUM(Price)", ""):F2}";
Related
I have Datagridview and all these data is from my Database(SQL). I have a column "Quantity" and I create a combo box in my datagrid which also "Quantity". On run time Combo box is already there, but i can't get the values of "Quantity" (textbox) to my "Quantity" (Combo box). Here's my code
private DataTable _products()
{
using (var con = SQLConnection.GetConnection())
{
var ds = new DataSet();
var select = new SqlCommand("Select * from employee_product", con);
var sda = new SqlDataAdapter();
sda.SelectCommand = select;
sda.Fill(ds);
dt = ds.Tables[0];
return dt;
}
}
private void fillcombo()
{
var combo = new DataGridViewComboBoxColumn();
ListProduct.Columns.Add(combo);
combo.HeaderText = "Quantity";
combo.Name = "combo";
ArrayList row = new ArrayList();
foreach (DataRow dr in dt.Rows)
{
row.Add(dr["Quantity"].ToString());
}
combo.Items.AddRange(row.ToArray());
}
Below is a small example of what my comment describes.
Some pointers as what to expect when using a DataGridViewComboBoxColumn… First I recommend you wire up the grids DataError. If a value is in the grid that is NOT in the combo box, then the grid will throw a DataError exception. In addition, in most cases when this happen it will make your program non-functional as the grid will continue to throw this error whenever it gains focus or more data is added. This is why you want to wire up the grids DataError… I can almost guarantee you will get this error if you are not careful making sure the combo box has ALL the values that are in the original data.
It is convenient and fortunate that the posted code is filling the combo boxes will “only” the data that is actually in the DataTable. This makes sure that the combo boxes will be good when the data is loaded into the grid. Unfortunately, in the case of the “quantity” values as the code shows… ONLY the values in the DataTable will be in the combo box. This may not always be the case or what you want…
From my small example below with only five (5) different “quantity” values in the data, when the code is run, each combo box only contains five (5) different values. This may be a problem if the user wanted to change the value to “7.5.” That value is not in the original data and it won’t be in the combo box for the user to select; therefore, this approach will possibly miss some needed values.
Using “quantity” as an example I would guess that you may want “quantity” to be values from 1 to 10 in .5 increments. This would be values 1, 1.5, 2, 2.5, 3, 3.5… etc. The limit of 10 is used as an example to demonstrate that often times the combo will contain values that “may” not be in the original data. Setting the combo box data table to these (default) values will display the values described above. However, looking at the original data in my example below, this will crash when it loads the data because there are values in the original data that are NOT in the combo box data table, namely 12.5, 33.5 and 22.5 since these values are greater than 10.
This is an “important” point. When ever you are using a data source on the grid and it has a combo box that is pre-filled with the data… you better make sure that the original data does NOT have a value that is NOT in the combo box. Without this check the DataError will most likely pop up somewhere down the line. So, it is something you would want to ALWAYS address/check for.
Fortunately, the posted code is already doing this, In the GetComboColumn method below, the commented-out line GetFullComboDT will get ALL the values we want in the combo box. Now we have to make sure that the original data doesn’t have any values that are NOT in the combo box. In my example below there are three (3) values that are NOT in the full combo box… 12.5, 33.5 and 22.5. The loop will go ahead and “add” these values to the combo box. This will almost guarantee that you will avoid getting the dreaded DataError.
I hope this makes sense and helps.
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
DataTable gridDT = GetGridTable();
FillGridTable(gridDT);
DataGridViewComboBoxColumn combocol = GetComboColumn(gridDT);
dataGridView1.Columns.Add(combocol);
dataGridView1.DataSource = gridDT;
}
private DataTable GetGridTable() {
DataTable dt = new DataTable();
dt.Columns.Add("Col1", typeof(string));
dt.Columns.Add("Col2", typeof(string));
dt.Columns.Add("Quantity", typeof(decimal));
return dt;
}
private DataTable GetComboTable() {
DataTable dt = new DataTable();
dt.Columns.Add("index", typeof(int));
dt.Columns.Add("Quantity", typeof(decimal));
return dt;
}
private void FillGridTable(DataTable dt) {
dt.Rows.Add("C0R0", "C1R0", 12.5);
dt.Rows.Add("C0R1", "C1R1", 2);
dt.Rows.Add("C0R2", "C1R2", 33.5);
dt.Rows.Add("C0R3", "C1R3", 1);
dt.Rows.Add("C0R4", "C1R4", 22.5);
dt.Rows.Add("C0R5", "C1R5", 1);
dt.Rows.Add("C0R6", "C1R6", 12.5);
}
private DataGridViewComboBoxColumn GetComboColumn(DataTable dt) {
DataGridViewComboBoxColumn combo = new DataGridViewComboBoxColumn();
combo.HeaderText = "Quantity";
combo.Name = "combo";
combo.DataPropertyName = "Quantity";
combo.DisplayMember = "Quantity";
DataTable comboDT = GetComboTable();
//DataTable comboDT = GetFullcomboDT();
int index = 0;
foreach (DataRow dr in dt.Rows) {
if (NewValue((decimal)dr["Quantity"], comboDT)) {
comboDT.Rows.Add(index, dr["Quantity"]);
}
}
combo.DataSource = comboDT;
return combo;
}
private bool NewValue(decimal value, DataTable dt) {
foreach (DataRow row in dt.Rows) {
if (((decimal)row["Quantity"]) == value) {
return false;
}
}
return true;
}
private DataTable GetFullcomboDT() {
DataTable dt = new DataTable();
dt.Columns.Add("index", typeof(int));
dt.Columns.Add("Quantity", typeof(decimal));
decimal currentValue = 1.0m;
int index = 0;
for (int i = 0; i < 20; i++) {
dt.Rows.Add(index, currentValue);
currentValue += 0.5m;
index++;
}
return dt;
}
You have to manually add the values to the comboboxes and declare the type of them first.
Something like that should do it:
DataGridViewComboBoxCell dgvcell;
for (int x = 0; (x <= (DataGridView1.Rows.Count - 1)); x++)
{
SQL_cmd.CommandText = "select something from somethingelse where something = #something ";
sql_cmd.parameters.addwithvalue("#something", DataGridView1.Rows[x].Cells["something"].Value);
SQL_reader = SQL_cmd.ExecuteReader;
while (SQL_reader.Read) {
dgvcell = ((DataGridViewComboBoxCell)(this.DataGridView1.Rows(x).Cells["something"]));
dgvcell.Items.Add(SQL_reader("something"));
}
SQL_reader.Close();
}
Basically I want to add another column from a TextBox along with values I have queried from the database. I want my datagridview to show something like
|itemcode|Category|itemDescription|unitcost|quantity|
where itemcode, Category, itemDescription, unitcost is from database and quantity is from a text box input.
private void btnAddToCart_Click(object sender, EventArgs e)
{
con.OpenConnection();
MySqlCommand cmd = con.connection.CreateCommand();
string search = txtSearchProduct.Text;
string quantity = txtQuantity.Text;
string query = "SELECT itemcode, Category, itemDescription, unitcost FROM tblprowareproducts WHERE itemDescription LIKE ?search";
cmd.CommandText = query;
cmd.Parameters.AddWithValue("?search", "%" + search + "%");
using (MySqlDataAdapter mda = new MySqlDataAdapter(cmd))
{
DataTable dt = new DataTable();
mda.Fill(dt);
dgvCart.DataSource = dt;
}
}
Is there a way to add another column after unitcost named quantity and the value of it comes from a TextBox?
There are different solutions for the problem, for example you can add the column to DataTable this way:
DataTable dt = new DataTable();
mda.Fill(dt);
var quantity = dt.Columns.Add("quantity", typeof(int));
quantity.DefaultValue = int.Parse(txtQuantity.Text);
dt.AsEnumerable().ToList().ForEach(r =>
{
r[quantity] = quantity.DefaultValue;
});
dgvCart.DataSource = dt;
Note 1: You may want to use TryParse to get the integer value from text.
Note 2: Default value of column applies to the column when adding the row. So to apply it to existing rows, you need to use a loop like what I did. For new rows that you add after that, it will be applied automatically.
I have a table named orders.
I want to display Order Date, Sum of the product quantity ordered and the product_name.
Here is the data I want to display:
Data to Display
As above, I want product names to be displayed horizontally, with the sum of the product orders displayed vertically by date.
I am using C# and an MS Access database.
I am able to display the data in gridview row-wise. Here is the code:
private void btn_all_orders_Click(object sender, EventArgs e)
{
try
{
connection.open
OleDbCommand command = new OleDbcommand();
command.connection = connection;
string query = "select order_date as 'Order Date', product_name as
'Items', Sum(order_quantity) as 'No of Orders' from order where cust_id =
'" + txt_cust_id.Text + "' group by order_date, product_name";
command.commandText = query;
OleDbDataAdapter da = new OleDbDataAdapter(command);
DataTable dt = new DataTable();
da.Fill(dt);
datagridview.DataSource = dt;
connectionn.Close();
}
catch (Exception ex)
{
Messagebox.Show("Error " + ex);
connection.Close();
}
}
How do I change this to achieve the goal described above?
I think you are asking for is this:
What you will need to do is ADD a Column to your to your datatable.
Then add an expression to that column it.
da.Fill(dt);
dt.Columns.Add("TOTAL");
dt.Columns("Total").Expression = "Count(Product1) + Count(Product2) + Count(Product3)";
datagridview.DataSource = dt;
connectionn.Close();
The totals on the bottom are coming from your SelectQuery => Sum(order_quantity). You can modify the query to get rid of that.
Some info
Of course the query could be changed so that it returns a computed column back and then you do not need to do it in the datatable.
Actual SQL for changing the query so that it returns a computed column back - https://stackoverflow.com/questions/3932205/to-calculate-sum-two-alias-named-columns-in-sql
The code above is pseudo - untested code - so please read the links.
EDIT
You could also look here : Display Data Vertically in the DataGridview
Too much code to post but basically the real work is done by flipping the dataset - as Mr. Gamal did.
public DataSet FlipDataSet(DataSet my_DataSet)
{
DataSet ds = new DataSet();
foreach (DataTable dt in my_DataSet.Tables)
{
DataTable table = new DataTable();
for (int i = 0; i <= dt.Rows.Count; i++)
{ table.Columns.Add(Convert.ToString(i)); }
DataRow r;
for (int k = 0; k < dt.Columns.Count; k++)
{
r = table.NewRow();
r[0] = dt.Columns[k].ToString();
for (int j = 1; j <= dt.Rows.Count; j++)
{ r[j] = dt.Rows[j - 1][k]; }
table.Rows.Add(r);
}
ds.Tables.Add(table);
}
return ds;
}
example I have a textbox input, the contents of the input textbox custom query of the user what the user inputted, an example in the textbox, I try to enter text "select id, name, country from the country" .. from the sql query on the results of the 3 coloumn of the country table, I asked how to take the number of columns, the column name of the textbox custom input .. to the number of columns I want to show in the textbox and the number of rows in the gridview appropriate number of columns in a query, for the names of the columns I want to display in gridview ..
private void BindReportColumn(String report_id)
{
dt = mda.GetData("SELECT column_name,column_text,size,back_color,fore_color FROM report_column INNER JOIN report ON report_column.report_id = report.report_id and report.report_id='" + report_id + "'", connStr).Tables[0];
GridCustomColumn.DataSource = dt;
GridCustomColumn.DataBind();
}
private void addcolumn()
{
int i;
//Add the items to the gridview
DataTable dt = new DataTable();
//Assign the viewstate to the datatable
if (!IsNumeric(txtcolumn_count.Text)) txtcolumn_count.Text = "0";
dt = (DataTable)ViewState["columnreport"];
for (i = 1; i <= Convert.ToInt32(txtcolumn_count.Text); i++)
{
DataRow dr = dt.NewRow();
//dr["report_id"] = txtreport_id.Text;
dr["column_name"] = "";
dr["column_text"] = " ";
dr["size"] = 0;
dr["back_color"] = "";
dr["fore_color"] = "";
//Add the datarow to the datatable
dt.Rows.Add(dr);
//Now bind the datatable to the gridview
GridCustomColumn.DataSource = dt;
GridCustomColumn.DataBind();
//Add the details to viewstate also
ViewState["columnreport"] = dt;
}
}
thanks in advance
i have a DataTable that has a column ("Profit"). What i want is to get the Sum of all the values in this table. I tried to do this in the following manner...
DataTable dsTemp = new DataTable();
dsTemp.Columns.Add("Profit");
DataRow dr = null;
dr = dsTemp.NewRow();
dr["Profit"] = 100;
dsTemp.Rows.Add(dr);
dr = dsTemp.NewRow();
dr["Profit"] = 200;
dsTemp.Rows.Add(dr);
DataView dvTotal = dsTemp.DefaultView;
dvTotal.RowFilter = " SUM ( Profit ) ";
DataTable dt = dvTotal.ToTable();
But i get an error while applying the filter...
how can i get the Sum of the Profit column in a variable
thank you...
Set the datacolumn to a numeric type (int, decimal, whatever):
DataColumn col = new DataColumn("Profit", typeof(int));
dsTemp.Columns.Add(col);
Use Compute:
int total = dsTemp.Compute("Sum(Profit)", "");
Note that aggregation is not a type of filter, which is the main problem with the approach you are tyring.
I used the DataTable's Compute method as suggested, and it works fine. I apply the same filtering as I use for the DataView (which is used to display the sorted and filtered data in the data grid) together with an aggregate function.
string SingleVocheridSale ="1";
DataView view = new DataView(dt);
view.RowFilter = string.Format("VOCHID='" + SingleVocheridSale + "'");
dataGridview1.DataSource = view;
object sumObject;
sumObject = dt.Compute("Sum(NETAMT)", view.RowFilter);
lable1.Text = sumObject.ToString();