I have a problem with DataGridView. I want to multiply two cells and display the result in a third cell.
I have two DataGridViews. The first DataGridView gets data from database. The second DataGridView gets values after I select row from first DataGridView and adds that row to second DataGridView. Column A gets from first DataGridView (from database); in column B the user inserts values manually.
example of second datagridview:
Price | Amount | Total
10.50 | 2 | 21.00
5.20 | 4 | 20.80
7.30 | 5 | 36.50
After that I want to sum column C and display the sum in a text box.
Column A is type decimal; Column B is integer; Column C should be decimal too.
This is solution that one guy gave me on internet but it works only for DataGridView that gets data manually, it doesn't work if data is from database:
decimal sum = 0.0m;
for (int i = 0; i < gridProizvodi.Rows.Count; i++)
{
DataGridViewRow row = gridProizvodi.Rows[i];
if (row.IsNewRow) break;
decimal product = Convert.ToDecimal(row.Cells[1].Value)
* Convert.ToInt32(row.Cells[2].Value);
sum += product;
row.Cells[3].Value = product;
}
txtCijena.Text= sum.ToString();
I get an argument out of range exception was unhandled error in this line
decimal product = Convert.ToDecimal(row.Cells[1].Value)
* Convert.ToInt32(row.Cells[2].Value);
Can someone help me find a solution?
I am not sure if you are using forms or webapp... The folloing option is ususally aplicable to webapps, I don't know about forms.
This usually happens when the GridView columns are generated automatically, i.e. gridview.AutoGenerateColumns = true;. It does not know that there are any columns, therefore gives you anout of range exception. You would need to set it to false and tell it what columns to display. In the template field for the third column, you can simply change the binding property to a multiplicated value.
Another oprion would be to return three columns from the database, third column being your multiplied values.
Hope this helps...
if error happened on the line as you sad. Then faster solution will be to use a column names.
As #Andres mentioned it is better practice then using of indexes.
From form designer check a columns name and then use like this:
decimal product = Convert.ToDecimal(row.Cells[datagridviewTextBoxColumn1.Name].Value)
* Convert.ToInt32(row.Cells[datagridviewTextBoxColumn2.Name].Value);
Or much better will be to used custom names of columns.
Have your second datargidview a predefined columns or it created programmatically?
if they have a predefined names-> then use them
if they not -> then, because you have always same columns in second datagridview, then will be better to create columns once in designer for example
How if you change it like this
decimal sum = 0.0m;
decimal product = 0;
for (int i = 0; i < gridProizvodi.Rows.Count; i++)
{
DataGridViewRow row = gridProizvodi.Rows[i];
if (row.IsNewRow) break;
product = row.item("Price") * row.item("Amount");
'--- if your price and amount field is numeric type, you dont have to convert it
sum += product;
row.item("Total") = product;
}
If you want to do it in VB.NET then......
Dim sum As Decimal = 0D
For i As Integer = 0 To DataGridView1.Rows.Count - 1
Dim row As DataGridViewRow = DataGridView1.Rows(i)
If row.IsNewRow Then
Exit For
End If
Dim product As Decimal = Convert.ToDecimal(row.Cells("Column1").Value) * _
Convert.ToDecimal(row.Cells("Column2").Value)
'sum += product
row.Cells("Column3").Value = product
Next
Thank You!!
Related
I am trying to sort an Excel worksheet using C# EPPLUS. I have reviewed the sort code method here
I am doing this
` var startRow = 11;
var startColumn= 1;
var endRow= 150;
var endColumn= 41;
var sortColumn = 1;
using (ExcelRange excelRange =
yourWorkSheet.Cells[startRow,startColumn, endRow, endColumn])
{
excelRange.Sort(sortColumn, true);
}
`
but that is not working.
The first two columns define what kind of record it is
ex. column one GSMO column 2 is Cost. There are 6 types of record for GSMO
ex GSMO Cost GSMO Profit GSMO LOSS etc.. Then it starts with another value in column 1 such as SESS etc all the way down to the final row
The columns from 3 to 41 are the dollar values associated with the row. So when I sort ascending on column one I want the rest of the columns (2-41) to stay with the same row. I hope this makes sense. Any help would be appreciated Thanks Pene
In Our assignment we were given a task to create a new spreadsheet program with a 26 x 26 grid of textboxes without importing anything and make use of array (in my case I Used array of objects).
I created a 2 d array of objects containing size of grid (27x27). the reason of it being 27 instead of 26 is because the first row and column is to show the ABCDE etc and 12345 etc of the rows and columns.
now the rows indexation I had no problem because it is numeric. however, the letters I solved by creating a string array with alphabet from a to z and entering them through a for loop and it worked.
Now the next step is to be able to link the cells, however, I am a bit stumped, because people told me I have to use Ascii or smthin.
Can anyone help me plz on how to achieve the cell links?
I have been able to past the name of each cell using this code but I fear I just filled the .Text of the cells not the cells name per se:
for (int x = 1; x < TwoDArrayCells.GetLength(0); x++) //nested loop to create the grid of textboxes.
{
for (int y = 1; y < TwoDArrayCells.GetLength(1); y++)
{
Cells CellFields = new Cells(Name = $"{AlphabetRow[x]}{y}", x, y + 3); // called a new cell named CellFields.
CellFields.Text = Name;//Change to location if you wise to take
this.Controls.Add(CellFields);
}
}
The result I would like is to be able to after this be able to link cells. meaning if I insert in a text box A1 + A2 it knows that a1 is the first box in the first row of first column and the a2 is the box in the second row of the first column.
Assuming that Columns can be A-Z only (Capitals), You can extract the column index and row index as follows:
Given a cell, string cell = "A2";
- the column index: int column = cell[0] - 'A' + 1;
- the row index: int row = Convert.ToInt32(cell.Substring(1));
Explanation: for the column, take the first letter, subtract it from 'A' (the subtraction will be performed on the assci codes of the characters) and add 1 since your actual cells are stored starting from index 1. for the row, just parse the rest of the string to int.
I have a C# web form where a user inputs data about an excel file into a number of text boxes, including:
TXT_FirstDataRow - integer field which represents the first row that contains data
TXT_LastDataColumn - string field which represents the last column that contains data
TXT_Range - string field which contains the calculated data range using the above two fields
TXT_ColumnCount - The number of columns in the calculated range
I am currently using jQuery to automatically calculate the data range using the code below which works perfectly:
$('#TXT_FirstDataRow,#TXT_LastDataColumn').keyup(function () {
var row = $('#TXT_FirstDataRow').val();
var column = $('#TXT_LastDataColumn').val();
var range = 'A' + row + ':' + column; //All ranges start at column A
$('#TXT_Range').val(range);
});
I would now like to automatically populate the TXT_ColumnCount with the count of the columns. For example:
Range |Column Count
------+------------
A1:C |3
A7:BX |76
I imagine that this should be made easier as the ranges will always be starting from column A, so the column count should just be the equivalent column number of TXT_LastDataColumn, but I am afraid even this is beyond my slightly limited jQuery knowledge.
Any help would be greatly appreciated.
Thanks
I found an answer on SO that helped me, link below:
Convert excel column alphabet (e.g. AA) to number (e.g., 25)
function letterToNumbers(string) {
string = string.toUpperCase();
var letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', sum = 0, i;
for (i = 0; i < string.length; i++) {
sum += Math.pow(letters.length, i) * (letters.indexOf(string.substr(((i + 1) * -1), 1)) + 1);
}
return sum;
}
This program displays database information in a Data Grid View. I need to add all the numbers in column 1, add all the numbers in column 3, and multiply the two sums together.
This code only multiplies column 1 and column 3 from the last row. Any suggestions?
This is my first time connecting to a database, so I apologize if this seems like a dumb question
foreach (DataRow currentRow in itemDS.Tables[0].Rows)
{
// add to data grid view
invoiceDataGridView.Rows.Add(currentRow[1].ToString(), currentRow[2].ToString(), currentRow[3].ToString());
var itemQuant = Convert.ToDecimal(currentRow[1]);
var priceEach = Convert.ToDecimal(currentRow[3]);
decimal subTotal = itemQuant * priceEach;
subTotalOutput.Text = subTotal.ToString();
}
Do you mean you're not sure how to keep a running total in the looping construction? If so:
decimal total = 0; //declare outside the foreach
foreach (DataRow currentRow in itemDS.Tables[0].Rows)
{
// add to data grid view
invoiceDataGridView.Rows.Add(currentRow[1].ToString(), currentRow[2].ToString(), currentRow[3].ToString());
var itemQuant = Convert.ToDecimal(currentRow[1]);
var priceEach = Convert.ToDecimal(currentRow[3]);
decimal subTotal = itemQuant * priceEach;
total += subTotal;
}
//do something with total here, after for each finishes
you can use linq for taking sum of a column.
var sum = itemDS.Tables[0].AsEnumerable().Sum(dr => dr.Field<int>("value"));
"value" will be the column name of the datatable inside the itemDS. you have to specify your column name here.
Take the sum of next column like the above statement. add multiply it..
Hope this helps.. :)
I have two datagridviews in one form. The first, datagridview1 has columns and data:
name IC EMAIL TELEPHONE
------------------------------------------------------
rOO 898989096677 AB#YAHOO.COM 018-9097878
datagridview2 has
name IC EMAIL TELEPHONE ID
-----------------------------------------------------------
rOO 898989096677 AB#YAHOO.COM 018-9097878 8787
I would like to ask help on how to compare two datagridviews, as you can see in the figure I would like to compare the four columns from one datagridview to another datagridview and see if any results match. For example, does the roo name match with the another datagridview, I want the value in the id (8787) to be sent to another datagridview.
there is a very simple solution to compare twoo datagridview and show their result in 3rd one.
for (int i = 0; i < dtView1.Rows.Count; i++)
{
for (int j = 1; j < dtView1.Columns.Count; j++)
{
if ((dtView1.Rows[i][j]) == (dtView2.Rows[i][j]))
{
// here you can add your own logic
}
else
{
// here you can add your own logic
}
}
|
Let's assume that you populate both datagrids with the same objects that contain these 4 properties from your example. You must check for the selected row from the first datagrid if in the second datagrid there is an matching object, based on your filters. Use Linq. If so, then copy the data from the selected item from the first datagrid into the matching element from the seconds. I am affraid that you will need to do all these steps manually, because there is no method that can compare two data grids and you just set some filters and the job is done. You will have some work to do, but it is not hard. Good luck.
Steve's answer does not work correctly and will not compile.
Here is my solution:
int x = 0;
int y = 0;
int i = -1;
int z = 0;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
i++;
if ((dataGridView1.Rows[i].Cells[i].Value) == (dataGridView2.Rows[z].Cells[i].Value))
{
x++;
}
else
{
y++;
}
if (z < dataGridView2.Rows.Count)
{
z++;
}
if(z == dataGridView2.Rows.Count)
{
z--; //subtract 1 from the total count because the datagrid is 0 index based.
}
MessageBox.Show("Matched: " + x.ToString() + "\r\n" + "Not Matched: " + y.ToString());
A foreach loop on the datagrid will cycle through each row, you can then select a cell or even cells to compare. This code is a bit lengthy and I'm sure it can be simplified, however it does the job.
Currently this will check every row from datagrid 2 for a match in datagrid 2, only on a single column.
Its import to remember the datagrid is 0 index based. The Count property of the datagrid gives a [1]index based count, so we need to subtract the last iteration on datagrid 2.