retrieving number value from datagridview C# - c#

I am trying to retrieve a numerical value from datagridview. The data type for both the value in the table, and the variable (weeklyTotal), are integer. Also I am trying to cast it into integer. I looked through the whole website for similar problems, and yet none of the solutions were helpful. The error message that I am getting is “when casting form a number, the value must be less than infinity”. I went back to my table more than one time to make sure that I don’t have invalid value.
it's a runtime error and the IDE always point at this line
weeklyTotal += (int)dataGridView1.Rows[i].Cells[1].Value;
for (int i = 0; i < this.dataGridView1.Rows.Count; i++)
{
sdate = dataGridView1.Rows[i].Cells[2].Value.ToString();
ddate = dataGridView1.Rows[i].Cells[3].Value.ToString();
if ((weekFirstDay <= Convert.ToInt32(sdate) &&
Convert.ToInt32(sdate) <= (weekFirstDay + 7))||(weekFirstDay <= `Convert.ToInt32(ddate) &&`
Convert.ToInt32(ddate) <= (weekFirstDay + 7)))
{
dataGridView1.Rows[i].Selected = true;
dataGridView1.Rows[i].Visible = true;
weeklyTotal += (int)dataGridView1.Rows[i].Cells[1].Value;
//weeklyTotalString = dataGridView1.Rows[i].Cells[1].Value.ToString();
//weeklyTotal += Convert.ToInt32(weeklyTotalString);
}
else

That's because the following won't cast your cell value to the int type:
(int) dataGridView1.Rows[i].Cells[1].Value
You're just taking the string saying "hey compiler, please treat it as an int type", but it will still be a string type underneath. Use the Convert.ToInt32 method like you did earlier.
weeklyTotal += Convert.ToInt32(dataGridView1.Rows[i].Cells[1].Value);

int num = Convert.ToInt32(dgv.Rows[i].Cells["col_name"].Value);

You may be trying to to an (int) cast on a DBNull value. I'm assuming that you populating the datagridview with data from the database.
Try this:
if(dataGridView1.Rows[i].Cells[1].Value != DBNull.Value)
{
weeklyTotal += (int)dataGridView1.Rows[i].Cells[1].Value;
}

Related

How to compare a fixed value against multiple values and find if any one fails to match

I have a fixed int value - 1050. I have around 50 dynamic values that I want to compare with the fixed value. So I compare it in a for loop. I have a public variable which I set as ok or notok depending on result. But my problem is that the value of the public variable is always the last value that I compared. Example, If I have the 20th dynamic value as 1000, it should return notok, but the value of the variable is always the last compared value. How do I set the variable to notok even if one/multiple of the values of dynamic variable doesnt match with fixed variable? I also display the total number of notok values in a listbox.
Here is what I have:
string result;
for(int i = 0; i < dynamicvalue.count; i++)
{
if(dynamicvalue[i] != setvalue)
{
result = "notok";
listBox1.Items.Add(result);
}
else
{
result = "ok";
}
}
To have "notok" if theres at least one not matching, one way to do it in plain code:
string result = "ok";
for(int i=0; i<dynamicvalue.count; ++i)
{
if(dynamicvalue[i] != setvalue)
{
result = "notok";
break;
}
}
You can use .Any() from Linq,
Determines whether any element of a sequence exists or satisfies a
condition.
string result = dynamicvalue.Any(x => x == setValue) ? "Ok" : "Not Ok";
If you want to use for loop without a break statement, you are just increasing the time complexity of your code.
I will never recommend it, but if you want you can try the below code
string result = "Ok";
bool flag = true;
//This for loop will iterate for n times.
for(int i = 0; i < dynamicvalue.Count; i++)
{
if(dynamicvalue[i] != setvalue && flag)
{
result = "Not Ok";
flag = false; //flag will help us to execute this block of code only once.
}
}
Perhaps the most performant way to answer this would be to keep your numbers in a HashSet instead (make dynamicvalue a HashSet<int>), then it's:
dynamicvalue.Contains(setvalue) ? "ok" : "notok"
A HashSet can much more quickly answer "do you contain this value?" than a list/array can
By the discussion going on in the comments I'm thinking that you want to go through all the elements in dynamicvalue and check all if any of them are ok or notok. If that is the case, you should turn result into an array. You get the last compared result because each time the cycle loops, the string gets assigned a new value all over again so the previous value gets discarded.
Is this what you want to do? I wrote it in c++
int setvalue = 1050;
int notok = 0;
int dynamicvalue[5] = {1, 2, 3, 1050, 4}; //for example
string result[5];
for (int i = 0; i < sizeof(dynamicvalue); i++){
if (dynamicvalue[i] != setvalue){
result[i] = "notok";
notok++; //to keep track of notok
}
else{
result[i] = "ok";
}
}
Afterwards if you cycle through the result array you will see that all the values were saved. I find it simpler to have an int variable to know how many times the result was notok
You forgot to get the actual value within dynamicvalue: your test should be if (dynamicvalue[i] != setvalue).
EDIT: And add a break; after the result="ok"; instruction to break the loop, too.
EDIT 2: An above answer gives the corrected code using a break.
I found a solution to this by reading #deminalla 's answer.
I added two more integers to work as counters and after the for loop I compare the values of these integers to get the final result.
Here's what I did:
string result;
int okcounter = 0;
int notokcounter = 0;
for(int i = 0; i < dynamicvalue.count; i++)
{
if(dynamicvalue[i] != setvalue)
{
notokcounter ++;
listBox1.Items.Add(notokcounter);
}
else
{
okcounter++;;
}
}
if(notokcounter >=1)
{
result = "notok";
}
else if(okcounter == dynamicvalue.count)
{
result = "ok";
}

I got this exception: System.FormatException: 'Input string was not in a correct format.'

I want to make a management program with an SQL database attached.
My problem is that I want to gather all the values ​​from one column to a textbox.
That column [7] from the datagridview has values ​​based on the calculation of 2 other columns [4]and [5] in the same datagridview formated as money.
I tried to convert it to string or int without success. Please Help!
public void gridTotal()
{
double sum = 0;
for (int i = 0; i < dataGridView1.Rows.Count; ++i)
{
sum += Convert.ToDouble(dataGridView1.Rows[i].Cells[7].Value);
}
facturaTotal.Text = sum.ToString("C");
}
dataGridView1.Rows[i].Cells[7].Value
may be null or empty String or something else, which cannot be converted into double. Instead I would recommend
double val = 0;
if (double.TryParse(dataGridView1.Rows[i].Cells[7].Value, out val)) sum += val;
If the cells contain real numbers written with a dot, like 2.3, this error will occur. It is common mistake, you should use CultureInfo to avoid this problem.
sum += Double.Parse(dataGridView1.Rows[i].Cells[7].Value, CultureInfo.InvariantCulture);

Pass data from a CSVReader to a method inside a loop

I have a CSV with the following data
month,year,speed
12,2010,76
2,2000,45
12,1940,30
and I'm loading using a 3rd party that reads it. In short, it is a CSVReader class and able to get the data from a file called input like this
List<Dictionary<string, object>> data = CSVReader.Read("input");
Then, using a for loop I'm capable of retrieving the data this way
for(var i=0; i < data.Count; i++) {
print ("month" + data[i]["month"] + " " +
"year" + data[i]["year"] + " " +
"speed " + data[i]["speed"]);
}
Except inside of the for loop I want to pass each year and month (one by one) to another function that takes as argument something like doubles (not objects) and i don't know how
for(var i=0; i < data.Count; i++) {
// Get month and year
function(month, year);
}
If I correctly interpret this and your question is: "How do I pass a value of type object to a function that takes a parameter of type double?", then you could either:
1) Cast the value
like this:
for (var i = 0; i < data.Count; i++) {
double month = (double)data[i]["month"];
// Same for year.
function(month, year);
}
Note that if the values you are casting cannot be casted to the target type (i.e., csv you are reading contains some corrupted rows), that would cause an exception to be thrown. If you're certain that won't be the problem, you can just do this, however, if you want to be sure, you can go with the option 2 which is
2) Use the as operator
like this:
for (var i = 0; i < data.Count; i++) {
double? month = data[i]["month"] as double?;
if (!month.HasValue) {
Console.WriteLine($"Month value on line {i + 1} is corrupted; Skipping...");
break;
}
// Same for year.
function(month.Value, year.Value);
}
In this case if the value is not of the double type, the month will be assigned the value of null (that's why we use the nullable double? type). That allows you to check whether the conversion was successful without having to handle possible exceptions.

C# issue when calculating a reference

I put together this little script whose goal is to calculate a reference according to the document type chosen in a form, and to concatenate a number that's auto-incremented. I am however getting this error when saving:
the string or binary data would be truncated
string typeDocAbbr = doc.GetStringValue("Document_type_Abbr");
string textRef = doc.GetStringValue("text_reference");
if (typeDocAbbr == "DIV")
returnValue = string.Format("{0}-{1}", typeDocAbbr, textRef);
if ((typeDocAbbr == "FIC") || (typeDocAbbr == "FTC") || (typeDocAbbr == "FDP"))
returnValue = string.Format("{0}-{1}", typeDocAbbr, textRef);
else
{
int chrono = 0;
string schrono = "";
if(string.IsNullOrEmpty(doc.GetStringValue("Reference")))
{
if (!string.IsNullOrEmpty(typeDocAbbr))
{
EDITOR.Documents.DataSource.ChronoManagerWrapper cmw =
new EDITOR.Documents.DataSource.ChronoManagerWrapper();
string Key = typeDocAbbr;
chrono = cmw.GetNewChrono("Process Studio", Key);
if (chrono < 10)
schrono = "0" + chrono.ToString();
else
schrono = chrono.ToString()};
}
}
returnValue = string.Format("{0}-{1}", typeDocAbbr, schrono);
}
This error :
the string or binary data would be truncated
is NOT on the code you shown. It is a SQL Server error.
It means that DB field is too small for the value you tried to insert.
Okay people, my bad.
I actually figured out where I went wrong. The returnValue of the script I shared went to feed a column the max size of which was 10 for some reason. However, as some of you so nicely pointed out to a beginner like me, the error was originating from the table, not the script, indicating that the value was too big for the column (that's what she said).
Thank you for some constructive criticism!

Specified cast is not valid error in Datagridview c#

This is a really weird error I've never had before. I have added a checkbox to my datagridview like this:
DataGridViewCheckBoxColumn checkBoxColumn = new DataGridViewCheckBoxColumn();
datagrid.Columns.Insert(0, checkBoxColumn);
I get the error
Specified cast is not valid
And it highlights this in cell formating of the datagrid:
for (int i = 0; i <= this.datagrid.Rows.Count - 1; i++)
{
if ((int)datagrid.Rows[e.RowIndex].Cells[7].Value <= 5)
{
this.datagrid.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Red;
}
This checks if a value in cell 7 is below the value or equal to 5 and if it is changes it to red. I have tried changing the cell to 8 because I thought it had moved since I've added a new column at 0 however it didn't work.
Try this
for (int i = 0; i <= this.datagrid.Rows.Count - 1; i++)
{
if (Convert.ToInt32(datagrid.Rows[e.RowIndex].Cells[7].Value) <= 5)
{
}
Try using int.TryParse which will only parse the cell's value if it can be successfully parsed to an int. Like this:
int temp;
for (int i = 0; i <= this.datagrid.Rows.Count - 1; i++)
{
if (int.TryParse(datagrid.Rows[e.RowIndex].Cells[7].Value.ToString(), out temp) == true)
{
if (temp <= 5)
{
this.datagrid.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Red;
}
}
At the very least this will stop throwing an exception and you can determine if your cell formatting is working correctly or not. I'm guessing you have a row in your data set that has a bad or null value in column 7 and/or 8. If you added this new checkbox column at position zero then you will need to now reference .Cells[8].
A better way to reference columns is by their name. Then if you add or delete columns in the future you don't mess up the rest of your column index references throughout your code. Try this if you get the above working:
if (int.TryParse(datagrid.Rows[e.RowIndex].Cells["yourColumnName"].Value, out temp) == true)
In order to use this method, you must specify the .Name column when you create and add the columns.

Categories