iam developing a invoice program
in invoice form i have textboxes and a datagridview
here is my sample code
DataTable dt = new DataTable();
dt.Columns.Add("productCode");
dt.Columns.Add("qty");
dt.Columns.Add("price");
dt.Columns.Add("total");
string prodCode = txtProductCode.Text;
decimal qty = Convert.ToInt32(txtQty.Text);
decimal price = Convert.ToInt32(txtPrice.Text);
decimal total = qty*price;
dt.Rows.Add(prodCode,qty,price,total);
dataGridView1.DataSource = dt;
what i want to do is if i add same prodCode again i want to update qty and total in existing row instead of add new row
Using strongly typed datasets would make parts of this easier (Actually, they nearly always make all work with datatable and dataset easier; I would use them by default)
I would perform the following steps:
Add a DataSet to your project
Add a table to it (open it in the visual designer, right click the surface, add a datatable)
Add your columns to the table and choose their data types (string, decimal etc) - right click the datatable and choose "add column"
Right click the prodCode column and set it to be the primary key
Set the Expression property of the Total column to be [Qty] * [Price] - it will now auto-calculate itself, so you don't need to do the calc in your code
In your code:
string prodCode = txtProductCode.Text;
decimal qty = Convert.ToInt32(txtQty.Text);
decimal price = Convert.ToInt32(txtPrice.Text);
//does the row exist?
var ro = dt.FindByProdCode(prodCode); //the typed datatable will have a FindByXX method generated on whatever column(s) are the primary key
if(ro != null){
ro.Price = price; //update the existing row
ro.Qty += qty;
} else {
dt.AddXXRow(prodCode, qty, price); //AddXXRow is generated for typed datatables depending on the table name
}
If you have a back end database related to these datatables, you life will get a lot easier if you connect your dataset to the database and have visual studio generate mappings between the dataset and the tables in the database. The TableAdapters it generates take the place of generic DataAdapters, and manage all the db connections, store the SQLs that retrieve and update the db etc.
You can use DataTable.NewRow() method to have a reference to the new row.
var rowNew = dt.NewRow()
...
dt.AddRow(rowNew);
Prefer using strong typed DataTable if the schema is not generated at runtime.
Also you can find an existing row using:
int found = -1;
for (int index = 0; i < dt.Count; index++)
{
if ( !condition ) continue;
found = index;
break;
}
Or use the Find() method.
You can loop the whole datagridview rows and check if there is existing row with same new row product code, if yes update the columns you want of this row. This is not tested but something like this:
string prodCode = txtProductCode.Text;
decimal qty = Convert.ToInt32(txtQty.Text);
decimal price = Convert.ToInt32(txtPrice.Text);
decimal total = qty*price;
bool isRowExist = false;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[0].Value.ToString().Equals(prodCode))
{
var totalQty = Convert.ToInt32(row.Cells[1].Value.ToString()) + qty ;
var updateTotal = Convert.ToInt32(row.Cells[3].Value.ToString()) + total ;
row.Cells[1].Value = totalQty;
row.Cells[3].Value = total;
isRowExist = true
}
}
if(!isRowExist)
dt.Rows.Add(prodCode,qty,price,total);
Related
I have a problem with format in C#.
I have a DataGridView and a TextBox. In this datagridview, there is a column: the single price (format int).
I want sum every elements of single price's column and insert the result into this textbox, but Visual Studio gives me a problem with format of string input ("Format of input's string is not correct").
this is the code than i used:
int TOT = 0;
for (int i = 0; i < dataGridView3.Rows.Count; i++)
{
TOT = TOT + Convert.ToInt32(dataGridView3.Rows[i].Cells[6].ToString());
}
textBoxTot.Text = Convert.ToString(TOT);
Can you help me with this bad error?
UPDATE:
I think that the problem now is another. I can't find the methods of MySql.Data.MySqlClient library that it can give me the result of query.
MySqlCommand command = new MySqlCommand();
String sumQuery = "SELECT SUM(`prezzo`) FROM `fatturetemp`";
command.CommandText = sumQuery;
command.Connection = conn.getConnection();
command.Parameters.Add("#prezzo", MySqlDbType.Int32).Value = costo;
conn.openConnection();
conn.closeConnection();
How is the command that give me the result of sumQuery. If i find this command, i can take the result of query and paste in textbox
If your datagridview is showing a datatable (I.e. your data is stored in a datatable) you can add a DataColumn to the datatable whose .Expression property is set to the string "SUM([Price])", where Price is the name of your numeric datatyped column holding the price info.
Now every row in the table will have the sum of the prices (the same value over and over again), so if you want to databind your textBox to this new column then it will always show the sum no matter which row is the current row (because all rows have the same value). It will also auto update without you having to do anything!
And if you're not using databinding to a datatable, I recommend that you do do it, because it represents good MVC practice of keeping your data in one thing (DataTable) and showing it in another (DataGridView) and keeping these concerns separate
It would look something like this, as a quick example:
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Price", typeof(int));
dt.Columns.Add("CalculatedTotal", typeof(int)).Expression = "SUM([Price])";
dt.Rows.Add("Apples", 100);
dt.Rows.Add("Oranges", 200);
BindingSource bs = new BindingSource();
bs.DataSource = dt;
WhateverDataGridView.DataSource = bs;
totalTextBox.DataBindings.Add(new Binding("Text", bs, "CalculatedTotal", true));
Here we have a data model (the datatable) where we keep our data. It has a couple of things we can set directly, and an third column that calculates based on the existing prices in all the table. If you look at this in the datagridview (assuming you have autogeneratecolumns turned on) you'll see that both rows have 300 for the CalculatedTotal, but they have individual amounts for price. There is a device called a BindingSource that sits between the datatable and the UI controls; you don't have to have one but it makes certain things easier regards updating controls when the data changes, and it maintains a concept of "current" - essentially whatever the current row is you're looking at in the datagridview; it all helps to avoid having to ask the DGV for anything - we just let the user type into the DGV, and it shows the data out of the datatable. All our dealings can be with the datatable directly - if you wrote a button to loop through the table and double all the prices, the controls in the UI would just reflect the change automatically. The textbox is connected to the CalculatedValue column via databinding; whatever the current row is, the textbox will show the CalculatedValue. Because the CalculatedValue column has the same value on every row, and they always all update if any price changes, the total textbox will always show the total. Add another textbox bound to Name to see what I mean; as you click around the grid and select different rows to be the "Current" row, the Name will change but the total does not. In truth it is actually changing in the same way that Name is, it's just that because the actual numeric value is the same on every row the contents of the textbox look like they don't change
UPDATE: I think that the problem now is another. I can't find the methods of MySql.Data.MySqlClient library that it can give me the result of query.
public string sommaFattura(String costo)
{
MySqlCommand command = new MySqlCommand();
String sumQuery = "SELECT SUM(`prezzo`) FROM `fatturetemp`";
command.CommandText = sumQuery;
command.Connection = conn.getConnection();
command.Parameters.Add("#prezzo", MySqlDbType.Int32).Value = costo;
conn.openConnection();
conn.closeConnection();
}
How is the command that give me the result of sumQuery. If i find this command, i can take the result of query and paste in textbox
It is weird that you are first converting to a string and then to an int.
int TOT = 0;
for (int i = 0; i < dataGridView3.Rows.Count; i++)
{
if (!dataGridView3.Rows[i].IsNewRow &&
int.TryParse(dataGridView3.Rows[i].Cells[6].Value.ToString(), out int v))
TOT += v;
}
textBoxTot.Text = TOT.ToString();
EDIT: Edited for your updated question. You shouldn't ask question inside a question buy anyway:
string sumQuery = "SELECT SUM(`prezzo`) FROM `fatturetemp`";
decimal total = 0M;
using (MySqlConnection cn = new MySqlConnection(" your connection string here "))
using (MySqlCommand cmd = new MySqlCommand(sumQuery, cn))
{
cn.Open();
total = Convert.ToDecimal(cmd.ExecuteScalar());
cn.Close();
}
Console.WriteLine(total);
How can i read the value from every row of a specific column?
I have a table shown here Table Image, i want to get the model name from the "Model" column and i have a database and "SELECT" query behind depending on the "Model" that is shown, it will show the quantity of the "Model" can someone help me?
here is a sample code of my .cs
foreach (GridViewRow row in gv1.Rows)
{
for(int i = 0; i<gv1.Columns.Count;i++)
{
string model = row.Cells[i].Text;
string quan = row.Cells[3].Text;
string ams = row.Cells[4].Text;
}
}
Note:-
data shown in the table are already in the database.
i have 2 seperate View tables for the Models and the Quantity.
If i understand well what you want it's clearly not the best approach, but i will try to help you.
In my opinion you have to get the quantity value before the display of your dataTable, inside this DataTable, but anyway i think this is the type of code that you requested :
//My dataTable to test , with 3 columns
DataTable dt = new DataTable();
dt.Columns.Add("Model");
dt.Columns.Add("Other");
dt.Columns.Add("QuantityFromDB");
//Add some test data in my dataTable
for(int i=0;i<15;i++)
{
DataRow dr = dt.NewRow();
dr[0] = i*2+"";
dr[1] = "XX data XX";
dt.Rows.Add(dr);
}
//Foreach row in your datatable ( your data )
for(int y=0;y<dt.Rows.Count;y++)
{
//Get the value of the current "Model" Column value
string currentModel = dt.Rows[y]["Model"].ToString();
//make your request in the db to get the quantity
int quantityfromdb = 50; //REQUEST
//Update the value of the QuantityFromDB column for this model row
dt.Rows[y]["QuantityFromDB"] = quantityfromdb;
}
You read the value of a specific row, and edit the value of it's other column.
EDIT :
If you want to work directly on the gridview, you can moove your code in the row_databound event of your gridview.
See doc : https://msdn.microsoft.com/fr-fr/library/system.web.ui.webcontrols.gridview.rowdatabound(v=vs.110).aspx
I have 2 DataGridViews: productsDataGridView and promotionsDataGridView.
The first one, productsDataGridView, which reads ALL values from a file with this method:
public static List<Products> LoadUserListFromFile(string filePath)
{
var loadProductsData = new List<Products>();
foreach (var line in File.ReadAllLines(filePath))
{
var columns = line.Split('\t');
loadProductsData.Add(new Products
{
InventoryID = "BG" + columns[0],
Brand = columns[1],
Category = columns[2],
Description = columns[3],
Promotions = Convert.ToInt32(columns[4]),
Quantity = Convert.ToInt32(columns[5]),
Price = Convert.ToDouble(columns[6])
});
}
return loadProductsData;
}
The first DataGridView (productsDataGridView) is filled correctly with ALL the values. Now in my productsDataGridView I have set-up a check-box column called "Promotion" (column Promotion reads integer values from the file): if it has value of 0 - the box is not checked, if greater than 1: is checked.
Now what I WANT to do is to FILTER/MOVE (I don't care which of both exactly) the values from productsDataGridView to promotionsDataGridView where we have a >0 value in the check-box column (promotions).
Example:
If productsDataGridView has 25 total products, from which 8 are promotional products (have value >0 in the check-box column), promotionsDataGridView should be filled with 8 values, which are copied/moved/filtered/whatever from DataGridView.
So far I can only copy the data from the first DataGridView to the second one with the following code:
public void Experimental2()
{
dataGridView1.DataSource = Products.LoadUserListFromFile(filePath);
//Bind datagridview to linq
var dg1 =
(from a in productsDataGridView.Rows.Cast<DataGridViewRow>()
select new { Column1 = a.Cells["Column1"].Value.ToString() }).ToList();
//loop dg1 and save it to datagridview2
foreach (var b in dg1)
{
dataGridView1.Rows.Add(b.Column1);
}
}
I made few pitiful attempts to insert an IF check, which would do the job for me (copy only IF columnt[4] > 0) but I am really new to DataGridView so I just couldn't write anything which would even compile at all...
Please, help me!
If both grids have same schema (and I assume they have) then we are going to find which rows are checked, get product bound to given row, create new result list and bind it to the next grid.
var results = new List<Products>(); //our new data source with only checked items
foreach (DataGridViewRow row in productsDataGridView.Rows)
{
var item = row.DataBoundItem as Products; //get product from row (only when grid is databound!)
if (item.Promotions > 0)
{
results.Add(item);
}
}
promotionsDataGridView.DataSource = results;
If you want to delete rows from first grid that are checked then create temporary list of rows, add to it checked rows and at the end iterate over them and remove one by one. Hope that help You out :)
This is my fist time here so i'll do my best describing what's my problem:
I have one form, and on that form I have two datagrids,let's call them dg1 and dg2.
dg1 is connected to an mssql database via dataadapter,while dg2 is not!. Lets say I have in dg1 information about a product:
productID
description
price
In dg2 i have something we might call bill.
So in dg2 i have columns
billID
accountnumberID
productID
description
price
Quantity
As you may predict billID is primary key, all the other one are Foreign. Since dg1 is filled with data from database i want when user clicks on a row in dg1 to pass data to dg2, while other data from dg2 are need to be inserted somehow(that is my problem anyway).
I have in database table bill, but i want to pass data from one to another by celldoubleclickevent, and all that data to be stored in bill table in database.
public void loadData()
{
try
{
SqlConnection con1 = getConnection();
con1.Open();
SqlCommand com1 = new SqlCommand();
com1.Connection = con1;
com1.CommandType = CommandType.Text;
com1.CommandText = "select * from bill";
SqlDataReader reader = com1.ExecuteReader();
dataGridView2.Rows.Clear();
while (reader.Read())
{
dataGridView1.AutoGenerateColumns = false;
dataGridView2.Rows.Add();
dataGridView2.Rows[i].Cells[0].Value = reader["billID"].ToString();
dataGridView2.Rows[i].Cells[1].Value = reader["acountnumberID"].ToString();
dataGridView2.Rows[i].Cells[2].Value = reader["productID"].ToString();
dataGridView2.Rows[i].Cells[3].Value = reader["Quantity"].ToString();
dataGridView2.Rows[i].Cells[4].Value = reader["Description"].ToString();
dataGridView2.Rows[i].Cells[5].Value = reader["price"].ToString();
i++;
}
}
Thx
There are several steps here.
First, you need to get the information from dg1. You can do that using the RowIndex property of the event args, although you'll need to check that the user didn't double click a header.
//This will depend on how the grid is bound
var dg1ProductID = GetProductID(dg1.datasource, e.RowIndex);
The body of this method could be quite simple
private void GetProductID(Int32 RowIndex)
{
return (Int32)(dg1.Rows[RowIndex].Cells[0]);
}
Second you'll need to put the information in dg2.
var newRow = dataGridView2.Rows.Add();
var bill = dataSet1.Tables[0].NewRow();
var accountNumber = GetCurrentAccountNumber();
var userQuantity = AskUserForQuantity();
dataGridView2.Rows[newRow].Cells[0].Value = -1;
dataGridView2.Rows[newRow].Cells[1].Value = accountNumber;
dataGridView2.Rows[newRow].Cells[2].Value = dg1ProductID;
dataGridView2.Rows[newRow].Cells[3].Value = userQuantity;
dataGridView2.Rows[newRow].Cells[4].Value = dg1Description;
dataGridView2.Rows[newRow].Cells[5].Value = dg1price;
Since the bill id is the primary key I assume it's automatically filled in.
Third you want to save the data to the bill, not sure if you want to do this in the double click event or a seperate button click event (like when the user hits OK).
If you are doing it in the double click then just pass the same values just added to a method to save them to the db.
Save(accountNumber, dg1ProductID, userQuantity, dg1Description, dg1price);
If not then you can enumerate the data and save from the Cell values
foreach(DataGridViewRow Row in dg2.Rows)
{
if (Row.Cells[0] == -1)
{
Save(Row.Cells[1], Row.Cells[2], Row.Cells[3], Row.Cells[4], Row.Cells[5]);
}
}
I am getting the Data table a output from my DataAccess Layer.
In My Datatable I am getting users Name,Number,Qualification
I want to assign a users name,number,qualification to a textbox for a particular user id,
How can i do that.
Help
Suppose you got datatable dt from the DAL
Then
var row = from t in dt
where t["userId"]='userid'
select t;
since you got row related to a user now you can use it to assign to the textboxs
txtName.Text = row["Name"]
assuming the datatable has 1 row:
DataRow row = table.Rows[0];
textbox1.text = row["Name"];
textbox2.text = row["Number"];
and so on
if there are multiple rows in the datatable, you need to select the row with that particular used id
DataRow row = table.Select("ID=" + UserID.ToString());
You have to pay attention to NULL values and number of rows.
if (table.Rows.Count == 1)
{
DataRow row = table.Rows[0];
NameTextBox.Text = row.IsNull("name") ? string.Empty : row["name"];
NumberTextBox.Text = row.IsNull("number") ? string.Empty : row["number"];
}
else
{
// Deal with no rows from DL
}
Using ternary operator makes you sure, you delete content of TextBoxes in case you reload row within already filled up page.
Also you may consider to used typed dataset, and access to columns will be generated by xsd.exe.