if statement with datatables - c#

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);

Related

My database query is only querying the last element of my array

My problem in the title i have allcodes array and codes TextBox (kodTxtBox)
i will split textbox like line per element and querying all elements with for loop then
when i run it, it shows the query of only the last element of the allcodes array with the
messagebox, but the others go into else and giving error message box
some turkish words in my codes so.
aciklama = description
birim = monad
birimFiyat = Price per 1 unit
ürünler = products
ürünler.sipariskod = products.ordercode etc.
i did a lot of ways for this i used foreach all variables type is string
allCodes = kodTxtBox.Text.Split('\n');
for (int i = 0; i < allCodes.Length; i++)
{
queryString = "SELECT ürünler.siparisKod, ürünler.aciklama, ürünler.birim, ürünler.fGrup, ürünler.birimfiyat FROM ürünler WHERE (((ürünler.siparisKod)=\"" + allCodes[i] + "\"));";
using (OleDbCommand query = new OleDbCommand(queryString))
{
query.Connection = connection;
reader = query.ExecuteReader();
if (reader.Read())
{
MessageBox.Show(allCodes[i] + " Succesful");
var desc = reader["aciklama"].ToString();
var monad = reader["birim"].ToString();
var sellPrice = reader["birimFiyat"].ToString();
MessageBox.Show("Açıklama: " + desc + " Birim: " + monad + " Satış Fiyatı: " + sellPrice);
reader.Close();
}
else
{
MessageBox.Show("Hata");
}
}
}
I solved the problem by making a single query instead of multiple queries. I saved the values ​​returned in each single query into a list and at the end I made the necessary for loop using the elements of the list

Updating Datarow from List via for loop. Index was out of bounds

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.

Search anywhere in DataGridView

I'm trying to write a program which will made a datagridview based on a text file. See code below.
private void Button1_Click(object sender, EventArgs e)
{
ls_datenTabelle.Clear();
ls_datenTabelle.Columns.Clear();
string kdstr = (comboBox1.SelectedItem.ToString());
string fileName = "ls.txt";
string fileName2 = kdstr + ".txt";
string sourcePath = #"H:\import_directoy\customer\" + kdstr;
string tempPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string dmitempPath = #"program_name\";
string targetPath = Path.Combine(tempPath, dmitempPath);
File.Delete(targetPath + "output");
string sourceFileName = Path.Combine(sourcePath, fileName);
string destFile = Path.Combine(targetPath, fileName2);
Directory.CreateDirectory(targetPath);
File.Copy(sourceFileName, destFile, overwrite: true);
using (var output = File.Create(targetPath + "output"))
{
foreach (var file in new[] { "H:\\directoy1\\directoy2\\index.config", destFile })
{
using (var input = File.OpenRead(file))
{
input.CopyTo(output);
}
}
}
string[] raw_text = File.ReadAllLines(targetPath + "output", Encoding.Default);
string[] data_col = null;
int x = 0;
foreach (string text_line in raw_text)
{
data_col = text_line.Split(';');
if (x == 0)
{
for (int i = 0; i <= data_col.Count() - 1; i++)
{
ls_datenTabelle.Columns.Add(data_col[i]);
}
x++;
}
else
{
ls_datenTabelle.Rows.Add(data_col);
}
}
ls_dataGridView.DataSource = ls_datenTabelle;
this.Controls.Add(ls_dataGridView);
ls_dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
ls_dataGridView.AllowUserToAddRows = false;
}
Now I want to search all over this datatable/datagridview and I will show the rows if the search function found the searchvalue in any column.
But I dodn't know how. The header of the table could change every day. So this code doesn't work for me:
public void findingValue(object sender, EventArgs e)
{
string searchValue = textBox1.Text;
DataView data = ls_datenTabelle.DefaultView;
ls_dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
data.RowFilter = string.Format("Name like '" + searchValue + "%'");
}
The program will find only rows where the searchValue is in the "Name" column and not one of the other 18 (umknown) columns.
Here is an example which uses Linq to loop over the columns in the DataTable:
if (searchValue == "") data.RowFilter = "";
else
{
var cols = ls_datenTabelle.Columns.Cast<DataColumn>().Select(x => x.ColumnName);
var filter = cols.Select(x => x + " like '" + searchValue + "%'")
.Aggregate((a, b) => a + " OR " + b);
data.RowFilter = filter;
}
First we collect the column names and then we build a filter from them, each part connectd with a OR clause.
You could also use Join or good old loops..
Note that this assumes that all columns allow searching for strings, i.e. no numbers etc..
If this is not true you will want to either pick only the string columns or change the filter for non-string columns, if searching them makes any sense.
To restrict the search to string columns simply insert
.Where(x => x.DataType == typeof(string))
between Cast and Select, so that cols contains only searchable columns..
If instead you want to search numeric columns you could write the filter like this:
var filter = cols.Select(x => "Convert(" + x + ", 'System.String') like '"
+ searchValue + "%'").Aggregate((a, b) => a + " OR " + b);
This uses the Convert function of the expression syntax . But why would one search for numbers starting with some digits..?
Here is a test with 2 string, 1 numeric and one datetime columns. The filter works for all; note that for the test I have added an extra '%' to extend the search to the whole values, not just the start..

Searching two DataTables at once for one value

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

Search data gridview using textbox and checkboxlist asp.net c#

I want to use textbox and checkboxlist to search data in gridview using asp.net c#. Using textbox can search the data. But for checkboxlist only can search the data when check only one checkbox. If check more than one checkbox, can't search the data. thanks a lot for helping.
the code:
c# code
protected void btnSearch_Click(object sender, EventArgs e)
{
if (cblDay.SelectedIndex != -1)
{
foreach (ListItem val in cblDay.Items)
{
if (val.Selected == true)
{
RptRateData.Day += val.Value + "";
}
}
}
RptRateData.RateAmount = txtRate.Text.Trim();
BindGrid();
}
code for class:
public string RateAmount { get; set; }
public string Day { get; set; }
internal DataSet GetRptRateSet()
{
DataSet tmpDS = new DataSet();
try
{
string strSQL = #"SELECT ComplexRateInfo.ComplexRateId,
ComplexRateDetailInfo.Day,
ComplexRateInfo.RateAmount
FROM ComplexRateInfo
LEFT JOIN ComplexRateDetailInfo ON ComplexRateInfo.ComplexRateId = ComplexRateDetailInfo.ComplexRateId ";
string whereSQL = " WHERE";
string orderBySQL = " order by Day ;";
int filterCount = 0; //to keep track of needed filter that are going to be used by the sql string
string[] sIndex = new string[2]; //to keep track of scalar variable needed by the sql, four string of sIndex because maximum filter available is 4
int indexCount = 0; //count to access sIndex members
//filter with or without day
if (_ds.Day != null && _ds.Day != "")
{
if (filterCount > 0) //query need additional filter
whereSQL = whereSQL + " AND ComplexRateDetailInfo.Day LIKE '{" + filterCount + "}'";
else //if this is the first filter
whereSQL = whereSQL + " ComplexRateDetailInfo.Day LIKE '{" + filterCount + "}'";
filterCount++;
sIndex[indexCount] = _ds.Day;
indexCount++;
}
//filter with or without rate amount
if (_ds.RateAmount != null && _ds.RateAmount != "")
{
if (filterCount > 0) //query need additional filter
whereSQL = whereSQL + " AND ComplexRateInfo.RateAmount LIKE '{" + filterCount + "}'";
else //if this is the first filter
whereSQL = whereSQL + " ComplexRateInfo.RateAmount LIKE '{" + filterCount + "}'";
filterCount++;
sIndex[indexCount] = _ds.RateAmount;
indexCount++;
}
//build complete query with no filter at all
if (filterCount == 0)
{
strSQL = strSQL + orderBySQL;
tmpDS = Db.GetDataSet(string.Format(strSQL));
}
//build complete query with 1 or more filter
else
{
strSQL = strSQL + whereSQL + orderBySQL;
tmpDS = Db.GetDataSet(string.Format(strSQL, sIndex));
}
}
catch (Exception ex)
{
throw ex;
}
return tmpDS;
}
There are two mistakes in your code.
Assigning values to RptRateData.Day from CheckBoxList.
Description: You assign selected values to object without using any separator. So For example if you have selected 1, 2, 4 days then as per your code, value of RptRateData.Day will be 124. Instead of that, it should be separated with comma as shown below:
var selectedDays = string.Empty;
foreach (ListItem val in cblDay.Items)
{
if (val.Selected == true)
{
selectedDays += "'" + val.Value + "',";
}
}
RptRateData.Day = selectedDays.TrimEnd(new char[] { ',' });
Now come to the second point which is in your SQL query which you make dynamically.
Description: In this query in WHERE clause you use Like operator for ComplexRateDetailInfo.Day. This will not work anymore. Instead of that you should use IN operator.
Note: Are you sure that your Like operator is working with curly braces ('{' and '}') and without '%' symbol ?

Categories

Resources