I have two DataTables and I am trying to determine if the tables contain the strings from a list, one string at a time. If the either table contains each string from the list of strings, return true, else false.
Example:
public static bool MyMethod()
{
DataTable table1 = GetMyTable1();
DataTable table2 = GetMyTable2();
List<string> requiredList = new List<string>();
requiredList.Add("foo");
requiredList.Add("bar");
requiredList.Add("foobar");
int counter = 0;
foreach (DataRow row in table1.Rows)
{
if (requiredList.Contains(row["ColumnName"].ToString()))
{
counter++;
}
}
foreach (DataRow row in table2.Rows)
{
if (requiredList.Contains(row["ColumnName2"].ToString()))
{
counter++;
}
}
return (counter == requiredList.Count);
}
The list and the datatables will not have duplicates, and I only care about one column. There won't be any duplicates between tables either.
Is there a more efficient way? Is there a way to search through both datatable's columns at the same time instead of having two foreachs?
If you don't want to loop, there are other options for getting rows from DataTables. You could try a .Select().
foreach(string req in requiredList)
{
DataRow[] rowsTable1 = table.Select("ColumnName LIKE " + req);
DataRow[] rowsTable2 = table.Select("ColumnName LIKE " + req);
counter = counter + rowsTable1.Length + rowsTable2.Length;
}
Of course you can replace the LIKE in the filter string with whatever operator works best for the string comparison you want.
I can't be certain this will be any quicker, but it at least looks shorter.
Not sure if this is the best answer, but you could select matching rows from each table and then count those rows like below:
string listItems = String.Join(",", requiredList);
DataRow[] table1Rows = table1.Select("ColumnName IN (" + listItems + ")");
DataRow[] table2Rows = table2.Select("ColumnName IN (" + listItems + ")");
counter = table1Rows.Length + table2Rows.Length;
What you could try to do is to do a for loop that iterates until max(table1.Rows,table2.Rows), as the previous answer said.
Also put an if statement to take care of being out of bounds
Related
I have two string lists:
currentRow = contains the info that the row should have
currentCol = contains the names of the columns that data from currentRow should go in.
each List contains 25(0-24) items, and is ordered in the same way as the dataRow it should be written to.
I am filling the Lists here, from labels and textboxes on a form:
List<string> currentRow = new List<string>();
List<string> currentCol = new List<string>();
foreach (var c in form11.Controls)
{
if (c.GetType() == typeof(TextBox))
{
var str = c.ToString();
var str1 = str.Substring(35);
currentRow.Add(str1);
}
if (c.GetType() == typeof(Label))
{
var str = c.ToString();
var str1 = str.Substring(34);
currentCol.Add(str1);
}
}
I then select the row in the dataTable that needs to be updated from the 3rd item in currentRow, which is a unique identifier.
var updateRow = arraysDt.Select("SERIAL =" + "'" + currentRow.ElementAtOrDefault(2) + "'");
Now i try to update the row from the items in the Lists here:
for (int i = 0; i < currentRow.Count; i++)
{
//MessageBox.Show(currentCol.ElementAtOrDefault(i).ToString() + " " + currentRow.ElementAtOrDefault(i).ToString());
updateRow[0][currentCol.ElementAtOrDefault(i)] = currentRow.ElementAtOrDefault(i);
}
As soon as it gets inside the for loop i throws a "index was out of bounds of the array" error.
As i said, currentCol contains column names and currentRow is the value.
So when it get here i expect it to find the column name and then update it with the value.
updateRow[0][currentCol.ElementAtOrDefault(i)] = currentRow.ElementAtOrDefault(i);
What am i doing wrong?
I have found out the issue:
"SERIAL =" + "'" + currentRow.ElementAtOrDefault(2) + "'"
will give me this:
SERIAL=' XXXXX'
What i need is:
SERIAL='XXXXX'
so to fix it i did:
string SMnum = currentRow.ElementAt(2).ToString().Replace(" ", string.Empty);
string query = string.Format("SERIAL='{0}'", SMnum.Replace(#"'", "''"));
var updateRow = arraysDt.Select(query);
This removes any white space in the string that i am looking for.
Synopsis :-
Two datatables with lists of filenames in the first column.
Using filename in datatable A to "search" datatable B & update a third datatable with the results.
Struggling with the If statements to work with the foundRows part.
Any hints on how I can get this to function?
// Iterate through the leftFileDT, extract the filename & search rightFileDT
for (int i = 0; i < leftFileDT.Rows.Count - 1; i++)
{
// Extract the leftFileName & store it in a string variable
leftFileMatch = leftFileDT.Rows[i][0].ToString();
// Search the rightFileDT for the leftFileMatch string
string expression;
expression = "Right_File_Name = '" + leftFileMatch + "'";
DataRow[] foundRows;
foundRows = rightFileDT.Select(expression);
// If no match is found
if (notfound)
{
matchedFileDataRow["File_Match"] = "False";
matchedFileDataRow["Left_File_Name"] = leftFileMatch;
matchedFileDT.Rows.Add(matchedFileDataRow);
}
// If a match is found
if (found)
{
// Update the matchedFileDT datatable
matchedFileDataRow["File_Match"] = "True";
matchedFileDataRow["Left_File_Name"] = leftFileMatch;
matchedFileDT.Rows.Add(matchedFileDataRow);
}
// Report progress to 'UI' thread
comparerWorker_Left.ReportProgress(i);
The Select method of a datatable returns an array of rows that match the filter criteria.
If no rows match then the array is empty.
DataRow[] foundRows = rightFileDT.Select(expression);
if (foundRows.Length == 0)
{
matchedFileDataRow["File_Match"] = "False";
}
else
{
matchedFileDataRow["File_Match"] = "True";
}
matchedFileDataRow["Left_File_Name"] = leftFileMatch;
matchedFileDT.Rows.Add(matchedFileDataRow);
int rowPosition = 0;
string WorkerName = "";
DataTable dtAllotedManpower = new DataTable();
dtAllotedManpower.Columns.Add("WorkerName");
foreach (GridViewRow row in GridViewTotalManpower.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
DataRow drAllotedManpower = dtAllotedManpower.NewRow();
CheckBox chkChild = (CheckBox)GridViewTotalManpower.Rows[rowPosition].FindControl("chkChild");
if (chkChild.Checked == true)
{
WorkerName = Convert.ToString(GridViewTotalManpower.DataKeys[rowPosition]["WorkerName"].ToString()) + "," + WorkerName;
}
rowPosition++;
}
hidfWorker.Value = WorkerName;
I have Written the following piece of code. My hidden field values are coming like this
"HARSH,RIMA,"
But i want the value "HARSH,RIMA" (without ',' after the last word). how to construct the code for that ? . there will be no 'comma' after last word .
Add them to a collection then use string.Join:
var list = new List<string>();
foreach (GridViewRow row in GridViewTotalManpower.Rows) {
// ...other code here...
list.Add(Convert.ToString(GridViewTotalManpower.DataKeys[rowPosition]["WorkerName"].ToString()));
}
hidfWorker.Value = string.Join(", ", list);
You can use string.TrimEnd()
hidfWorker.Value = WorkerName.TrimEnd(',');
This will remove the last comma from the string.
you can use the substring method
hidfWorker.Value=WorkerName.Substring(0,WorkerName.Length-1);
Use StringBuilder instead of string if you are frequently changing the string like in loops, because when you use string it will create new string object every time you changes it,
StringBuilder workerName = new StringBuilder();
And in your loop
workerName.Append(Convert.ToString(GridViewTotalManpower.DataKeys[rowPosition]["WorkerName"].ToString()) + ",");
Then trim last ',' character using TrimEnd method
hidfWorker.Value = workerName.ToString().TrimEnd(',');
Hope this helps.
When the following is executed:
foreach (String fromList in columns)
{
query += "`" + fromList + "`,";
}
query.TrimEnd(',');
The comma is not trimmed from the string.
What am I doing wrong?
TrimEnd returns the new string. You need:
query = query.TrimEnd(',');
Strings are immutable, so you need to store the return value from TrimEnd.
query = query.TrimEnd(',');
Though there is an easier way to do this:
var query = String.Join(",", columns.Select(fromList => String.Format("`{0}`", fromList)));
TrumEnd returns a string. Are you assigning it to a variable ?
Use the below example:
var trimmed = query.TrimEnd(',');
Console.WriteLine(trimmed);
It should be
foreach (String fromList in columns)
{
query += "`" + fromList + "`,";
}
query = query.TrimEnd(',');
Strings are immutable. If you want the result after applying TrimEnd, you have to assign that result to a variable:
foreach (String fromList in columns)
{
query += "`" + fromList + "`,";
}
query = query.TrimEnd(',');
Here I've assigned it back to itself.
Of course, better would be something like:
query = String.Join(",",fromList.Select(a=>"`" + a + "`"));
instead of the loop + edit.
I want to take each row in a datagridview and add it to a string variable that I will then print using a custom PrintDocument class. Everything in my program works, except for getting the data from the datagridview into the string variable. I can't find an example on how to do this. Wouldn't I just use a "foreach(DataRow Row in dataGridView1)..." to loop through the data table and add it to my string variable? Can someone show me an example of this?
Right now, my code looks like this, but it won't compile (getting an error message on the way I'm trying to get the value from the column.row into the string. The error message is "The best overloaded method match for 'System.Windows.Form.DataGridViewRowCollection.This[int]' has some invalid arguments).:
//Loop through the dataGridView1 and add it to the text
//that we want to print
foreach (DataRow row in dataGridView1.Rows)
{
textToPrint = textToPrint + dataGridView1.Rows[row][0].ToString() + "\t" +
dataGridView1.Rows[row][1].ToString() + "\t" +
dataGridView1.Rows[row][2].ToString() + "\t" +
dataGridView1.Rows[row][3].ToString() + "\t";
}
I recommend a more generic method for doing this so you don't have to rewrite it in the future. This will also be independent of how many columns you might have in your DataGridView.
public static string DGVtoString(DataGridView dgv, char delimiter)
{
StringBuilder sb = new StringBuilder();
foreach (DataGridViewRow row in dgv.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
sb.Append(cell.Value);
sb.Append(delimiter);
}
sb.Remove(sb.Length - 1, 1); // Removes the last delimiter
sb.AppendLine();
}
return sb.ToString();
}
Try this
dataGridView.Rows[RowIndex].Cells[ColumnIndex].Value as string
for (int row = 0 ; row < dataGridView1.Rows.Count; row ++)
{
textToPrint = textToPrint +
dataGridView1.Rows[row].Cells[0].Value.ToString() + "\t" +
dataGridView1.Rows[row].Cells[1].Value.ToString() + "\t" +
dataGridView1.Rows[row].Cells[2].Value.ToString() + "\t" +
dataGridView1.Rows[row].Cells[3].Value.ToString() + "\t";
}