Check value of datatable with C# - c#

I want to check if values of datatable of the same column are equals to "int" or not , so if it's true i want to calculate with content value the sum. This is my code which return always when i click on sum button "pas tous entier" .
Thank you in advance!
private void button7_Click(object sender, EventArgs e)
{
int i = 0, s = 0;
String type ="int";
DataTable dt = new DataTable("Table_insertion");
bool exists = dt.AsEnumerable().Any(row => type == row.Field<String>("Type"));
if (exists== true)
{
for (i = 0; i < dataGridView1.Rows.Count; ++i)
{
s += Convert.ToInt32(dataGridView1.Rows[i].Cells[2].Value);
}
label5.Text = s.ToString();
}
else
{
MessageBox.Show("pas tous entiers");
}
}

The datatable seems unnecessary here.
Maybe the following is enough.
for (i = 0; i < dataGridView1.Rows.Count; ++i)
{
var str = dataGridView1.Rows[i].Cells[2].Value?.ToString();
if( !string.IsNullOrEmpty(str) && Int32.TryParse(str, out var parsed)
{
s += parsed;
}
}
If you want to check the type of the column in a datatable you can check its DataType.
foreach (var col in datatable1.Columns)
{
if ( col.DataType == typeof(System.Int16) || col.DataType == typeof(System.Int32)) // Or other types
{
....

Are you just trying to evaluate if the string returned contains only numbers? If so, you may want to use a regex match on the data. There is a great example here: Regex for numbers only

Related

How can i use LINQ to pass highlighted Cells to another DataGridView?

Is there any way to use a LINQ style query to pass the Value of the highlighted Cells(without ComboBox) to another DataGridView? In the figure below, the cells to be transferred are marked.
Many thanks in advance for your ideas!
private void Button3_Click(object sender, EventArgs e)
{
for (int i = 0; i < dataGridView2.Rows.Count; i++)
{
for(int j = 0; j < dataGridView2.Columns.Count; j++)
{
if (!(dataGridView2.Rows[i].Cells[j].Value == null))
{
var cr =
dataGridView2.Rows[i].Cells[j].Style.BackColor =
Color.Red;
var cg =
dataGridView2.Rows[i].Cells[j].Style.BackColor =
Color.LawnGreen;
dataGridView3.Rows.Add(cr);
dataGridView3.Rows.Add(cg);
}
}
}
}
Ok, here's some sample code using linq which will copy values where a cell has a certain background color. The key to using Linq is the Cast method which can take non-generic IEnumerable and turn it into a generic IEnumerable so we can use the linq syntax. It also uses the Select overload which includes a parameter for the index, so you can easily index into the second data grid to get to the correct row / column.
var linqable = dataGridView2.Rows.Cast<DataGridViewRow>().Select((r, y) => new
{
row = r,
rowNum = y,
cells = r.Cells.Cast<DataGridViewCell>().Select((a, b) =>
new
{
cell = a,
cellNum = b
})
});
foreach(var row in linqable)
{
foreach(var cellWithRed in row.cells.Where(x => x.cell.Style.BackColor == Color.Red))
{
dataGridView3.Rows[row.rowNum].Cells[cellWithRed.cellNum].Value = cellWithRed.cell.Value;
}
}

How To Compare a Textbox With An Array in C#

I'm pretty new in C# and i couldn't find an answer for this.
I'm getting the values of a column named NUMERO_CTA from my DB in an array within valores variable. But I have to compare this array of values with a textbox to check if one of the values contained in valores matches with the value of the textbox named txtCuentaDestino. How can I compare a textbox.text with an array?. Thanks in advanced!
Here's my code:
DataTable tbl = ds.Tables[0];
for (int i = 0; i < tbl.Rows.Count; i++)
{
DataRow myRow = tbl.Rows[i];
valores = new string[] {myRow["NUMERO_CTA"].ToString()};
}
if (ds.Tables[0].Rows.Count == 0)
{
GuardaCuenta();
return false;
}
else if (txtCuentaDestino.Text == resultado)
{
return true;
}
else
{
return false;
}
You can't compare an array of strings and a string. You want to compare the string from the textbox to each string in your array, one at a time.
In this case if you want to check if there is a string in the array which matches your textbox string you can use the linq method Contains.
Ex.
if (arrayOfStrings.Contains(singleString))
{
// Do something
}
you need to iterate over the valores array and make the comparison.
foreach(string s in valores)
{
if(s == txtCuentaDestino.Text)
{
//do something magical
}
}
Thanks for the answers:
Both helped me a lot! Here is the result:
for (int i = 0; i < tbl.Rows.Count; i++)
{
DataRow myRow = tbl.Rows[i];
valores = new string[] { myRow["NUMERO_CTA"].ToString() };
foreach (string x in valores)
{
if (x.Contains(cuentaDestino))
{
f_Script("alerta", "<script>alert('Cuenta a crear ya Existe.');window.location.href = 'RW_CuentasBancarias.aspx';</script>");
contador = 1;
}
}
if (contador == 1)
{
break;
}
}
if(contador != 1){
GuardaCuenta();
f_Script("alerta", "<script>alert('Su cuenta ha sido creada.');window.location.href = 'RW_Solicitud_Reembolso.aspx';</script>");
}

Unable to list the dates from filtered datagridview into combobox

My dataGridView_flaggedComments is filled with some original comments.
I then use comboBox_stockIndex_SelectedIndexChanged function to filter the comments in dataGridView_flaggedComments according to Tickers_Ticker_ID.
Next, with the filtered comments, I want to list out the comments' dates to comboBox_stockDates, using PopulateStockDatesIndex() function.
However, PopulateStockDatesIndex() function is listing all the dates (of the original non-filtered comments). How can I only list the dates that come from the filtered comments?
My code as below. Any help would be much appreciated. Thank you!
private void comboBox_stockIndex_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (DataRow db in LoadTickers().Rows)
{
if (comboBox_stockIndex.SelectedItem.ToString() == db["Symbol"].ToString())
{
(dataGridView_flaggedComments.DataSource as DataTable).DefaultView.RowFilter = string.Format("Tickers_Ticker_ID = '{0}'", db["Ticker_ID"].ToString());
}
}
PopulateStockDatesIndex();
}
private void PopulateStockDatesIndex()
{
comboBox_stockDates.Items.Clear();
comboBox_stockDates.Items.Add("Choose to Filter");
comboBox_stockDates.FormatString = "dd-MM-yyyy";
DataTable dt_filterDate = (DataTable)(dataGridView_flaggedComments.DataSource);
foreach (DataRow row in dt_filterDate.Rows)
{
for (int i = 0; i < dataGridView_flaggedComments.Rows.Count - 1; i++)
{
if (dataGridView_flaggedComments.Rows[i].Cells["Comments_Date"].Value.ToString() != "")
{
string date = row.Field<DateTime>(1).ToString("dd-MM-yyyy");
if (!comboBox_stockDates.Items.Contains(date))
{
comboBox_stockDates.Items.Add(date);
}
}
}
}
}
P/S: I tried my best to explain my question and put my question into proper formatting and I have also done quite some research regarding this, kindly don't downvote me and let me know where I did wrongly or if my question is not clear enough. I apologise if there are similar questions!
When you applied the filter beforehand, you set the filter on the DataView, not the actual DataTable. When you access the data in the datatable in PopulateStockDatesIndex(), you are accessing the unfiltered DataTable and not the view. Try to change to
private void comboBox_stockIndex_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (DataRow db in LoadTickers().Rows)
{
if (comboBox_stockIndex.SelectedItem.ToString() == db["Symbol"].ToString())
{
(dataGridView_flaggedComments.DataSource as DataTable).DefaultView.RowFilter = string.Format("Tickers_Ticker_ID = '{0}'", db["Ticker_ID"].ToString());
}
}
PopulateStockDatesIndex((dataGridView_flaggedComments.DataSource as DataTable).DefaultView.RowFilter);
}
private void PopulateStockDatesIndex(string rowFilter)
{
comboBox_stockDates.Items.Clear();
comboBox_stockDates.Items.Add("Choose to Filter");
comboBox_stockDates.FormatString = "dd-MM-yyyy";
DataTable dt_filterDate = (DataTable)(dataGridView_flaggedComments.DataSource);
dt_filterDate.DefaultView.RowFilter = rowFilter;
foreach (DataRow row in dt_filterDate.Rows)
{
for (int i = 0; i < dataGridView_flaggedComments.Rows.Count - 1; i++)
{
if (dataGridView_flaggedComments.Rows[i].Cells["Comments_Date"].Value.ToString() != "")
{
string date = row.Field<DateTime>(1).ToString("dd-MM-yyyy");
if (!comboBox_stockDates.Items.Contains(date))
{
comboBox_stockDates.Items.Add(date);
}
}
}
}
}
private void PopulateStockDatesIndex()
{
comboBox_stockDates.Items.Clear();
comboBox_stockDates.Items.Add("Choose to Filter");
foreach (DataGridViewRow row in dataGridView_flaggedComments.Rows)
{
for (int i = 0; i < dataGridView_flaggedComments.Rows.Count - 1; i++)
{
if (dataGridView_flaggedComments.Rows[i].Cells["Comments_Date"].Value.ToString() != "")
{
string str = dataGridView_flaggedComments.Rows[i].Cells["Comments_Date"].Value.ToString();
DateTime date = DateTime.ParseExact(str, "dd/MM/yyyy h:mm:ss tt", CultureInfo.GetCultureInfo("en-GB"));
if (!comboBox_stockDates.Items.Contains(date.ToString("dd/MM/yyyy")))
{
comboBox_stockDates.Items.Add(date.ToString("dd/MM/yyyy"));
}
comboBox_stockDates.SelectedIndex = 0;
}
}
}
}

Delete and remove the row matching string?

I want to search for a string in DataTable if it starts with "null" delete this string, if this row has no values then erase this row too. Can someone show me how to do it?
ID Name Comment
2 lola hallo
5 miky hi
null0 // delete null0 and remove this row
null1 ko // delete null1 but do not remove this row
1 hub why
3 null2 //delete null2 but do not remove this row
I tried to delete "null" but it doesn't work.
My Code:
int ct1 = 0;
for (int i = 0; i < resE1.Rows.Count; i++ )
{
if(resE1.Rows[i]["SignalName"].ToString() == "null" + ct1)
{
resE1.Rows[i].SetField<String>(2, "");
}
ct1++;
}
I find a solution to replace "null*" with empty spaces, but now I want to erase this row if the cells values of this row are empty, how can i do it?
int ct1 = 0;
for (int i = 0; i < resE1.Rows.Count; i++)
{
string fix = resE1.Rows[i]["SignalName"].ToString();
if(fix.Contains("null"))
{
resE1.Rows[i].SetField<String>(2, "");
}
ct1++;
}
I tried this. Works for me.
List<DataRow> rowsToRemove = new List<DataRow>();
foreach (DataRow dr in resE1.Rows)
{
if (dr["Name"].ToString().IndexOf("null") == 0)
{
dr.SetField("Name", "");
}
bool hasValue = false;
for (int i = 0; i < dr.ItemArray.Count(); i++)
{
if (!dr[i].ToString().Equals(String.Empty))
hasValue = true;
}
if (!hasValue) rowsToRemove.Add(dr);
}
foreach(DataRow dr in rowsToRemove)
{
dr.Delete();
}
Here is your code changed so it works although I don't like how it is written. Check the answer:
int ct1 = 0;
int i = 0;
while(i < dt.Rows.Count)
{
if ( dt.Rows[i]["Name"].ToString() == "null" + ct1)
{
if ((dt.Rows[i][0] == null || dt.Rows[i][0].ToString() == string.Empty) && (dt.Rows[i][2] == null || dt.Rows[i][2].ToString() == string.Empty))
{
dt.Rows.RemoveAt(i);
i--;
}
else
{
dt.Rows[i].SetField<String>(1, "");
}
ct1++;
}
i++;
}
Assuming your DataTable has column "Name" of type string you can achieve it like this:
private DataTable RemoveUnwanted(DataTable source)
{
var rowsEnu = source.Rows.GetEnumerator();
while (rowsEnu.MoveNext())
{
((DataRow)rowsEnu.Current)["Name"] = ((DataRow)rowsEnu.Current)["Name"].ToString().StartsWith("null") ? string.Empty : ((DataRow)rowsEnu.Current)["Name"];
}
return (from i in source.AsEnumerable()
where !(i.ItemArray.All(o => string.IsNullOrEmpty(o.ToString())))
select i).CopyToDataTable();
}
You will also need reference to System.Data.DataSetExtensions.
To answer one of your questions, to delete the entire row do something like this:
if(resE1.Rows[i].Contains("null") && (resE1.Rows[i]["ID"].ToString() == "") && (resE1.Rows[i]["Comment"].ToString() == ""))
{
resE1.Rows[i].Delete();
}
bool emptyFlag = false;
if(resE1.Rows[i].Contains("null"))
{
for(int j = 0; j < resE1.Columns.Count; j++)
{
if(resE1.Rows[i][j].Equals(""))
emptyFlag = true;
else
emptyFlag = false;
}
if(emptyFlag)
resE1.Rows[i].Delete();
}
You need something like this:
String test = "Null01";
if (test.IndexOf("Null") == 0)
{
test = test.Replace("Null", String.Empty);
}
For second part of your question, just check if Comments are null or empty then replace the string too.
Arrange code according to your own requirement.

Datagridview sorting column based on matching string

I have a datagridview that I would like to have rows sorted based on the portion of a string entered from a user. The entered string is compared with all of the strings in a particular column. For instance, if I gave "comp" as the search word, the program would try to compare the search word with the strings on first column and sort the rows in a descending order which starts with "comp", such as "compare", "composition", "computer" etc. Rest of the words that do not match is either left alone or sorted in an alphabetical order (whichever is easier).
In LINQ, I am aware that you can apply the following code to achieve what you wanted with a string array:
var sortedWords = words.Where(x => x.Contains("comp"))
.OrderByDescending(x => x);
How can I achieve the same thing in Datagridview as I need to have the rows sorted, not just the items inside a particular column?
Edit:
The following code is giving a System.InvalidOperationException. (SetCurrentCellAddressCore is being called twice)
private void DGVPointCtrl_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
MatchComparer mc = new MatchComparer();
DGVPointCtrl.Sort(mc); //Error
}
I'm probably doing something wrong but I'm not sure why. Here is the code that programatically adds the rows for testing purposes:
private void BtnRefresh_Click(object sender, EventArgs e)
{
try
{
DGVPointCtrl.Rows.Clear();
int mainIndex = CmbMainDevice.SelectedIndex;
int subIndex = CmbSubDevice.SelectedIndex;
DDCDAO ddcdao = new DDCDAO(DDCGlobal.ddcEngineIP, ddc.Ip);
string pointListType;
object rs;
//Currently only supports IO DDC Request
//TO DO: Change DDCDAO to send proper subdevice requests
if (mainIndex == 0) //IO
{
#region Main Device: IO
}
//First row is for searching items
DGVPointCtrl.Rows.Add(new DataGridViewRow());
for (int i = 1; i < 5; i++)
{
DGVPointCtrl.Rows.Add(new DataGridViewRow());
DGVPointCtrl.Rows[i].ReadOnly = true;
}
DGVPointCtrl.Columns[0].SortMode = DataGridViewColumnSortMode.Programmatic;
DGVPointCtrl.Rows[0].DefaultCellStyle.Font =
new Font(DGVPointCtrl.DefaultCellStyle.Font, FontStyle.Italic | FontStyle.Bold);
if (subIndex == 1) //BI
{
PointDGVColumnGenerate("IO_BI");
}
else if (subIndex == 2) //BO
{
PointDGVColumnGenerate("IO_BO");
}
else if (subIndex == 3) //AI
{
PointDGVColumnGenerate("IO_AI");
}
else if (subIndex == 4) //AO
{
PointDGVColumnGenerate("IO_AO");
}
DGVPointCtrl.Rows[1].Cells[0].Value = "IO12314";
DGVPointCtrl.Rows[2].Cells[0].Value = "IO21948";
DGVPointCtrl.Rows[3].Cells[0].Value = "IO28194";
DGVPointCtrl.Rows[4].Cells[0].Value = "VP12984";
DGVPointCtrl.Rows[2].Cells[1].Value = "asdf";
#endregion
}
catch
{
}
}
private void PointDGVColumnGenerate(string key)
{
int colCount = 0;
DGVColumnTable.Clear();
for (int i = 0; i < COL_MAX; i++)
{
DGVPointCtrl.Columns[i].HeaderText = " ";
DGVPointCtrl.Columns[i].Visible = true;
}
foreach (string s in UIConstant.DDCPCtrlListColumnText[key])
{
DGVPointCtrl.Columns[colCount].HeaderText = s;
DGVColumnTable.Add(DGVPointCtrl.Columns[colCount]);
colCount++;
}
}
Edit2:
public class MatchComparer : IComparer
{
private static IComparer defaultComparer = new CaseInsensitiveComparer();
int IComparer.Compare(object x, object y)
{
DataGridViewRow xr = (DataGridViewRow)x;
DataGridViewRow yr = (DataGridViewRow)y;
string xs = "";
string ys = "";
try
{
xs = xr.Cells[0].Value.ToString();
}
catch
{
}
try
{
ys = yr.Cells[0].Value.ToString();
}
catch
{
}
if (HasMatch(xs) && !HasMatch(ys)) return -1;
else if (!HasMatch(xs) && HasMatch(ys)) return 1;
else return defaultComparer.Compare(xs, ys);
}
This is possible only if you are populating the grid yourself as opposed to binding it to the database.
Set DataGridViewColumn.SortMode to Programmatic.
Use DataGridView.Sort to impose a comparer like this:
public class MatchComparer : IComparer {
int IComparer.Compare(object x, object y) {
if (HasMatch(x) && !HasMatch(y)) return -1;
else if (!HasMatch(x) && HasMatch(y)) return 1;
else return defaultComparer.Compare(x, y);
}
private bool HasMatch(object x) {
return x is string && ((string)x).StartsWith("comp");
}
private static IComparer defaultComparer = new CaseInsensitiveComparer();
}

Categories