Matching cell in rows with an input string - c#

I am basically trying to read from an excel file and find a certain ID Number in that file. Right now it is printing all of the rows as a match and I would like help figuring out why.
// input to search for
string value = textBox3.Text;
// verify the input is the correct format
Match match = Regex.Match(value, #".*[0-9].*");
Match myMatch = Regex.Match(value, textBox3.Text);
Console.WriteLine(value);
foreach (DataRow row in xlsDs.Rows)
{
if (match.Success && myMatch.Success)
{
Console.WriteLine(textBox3);
Console.Write(row.ItemArray.ToString());
Console.WriteLine("This was found");
}
}

int rowCount = xlsDs.Rows.Count;

I would still use a foreach loop, then add a simple counter and increment it via counter++ every time you loop, when you find it you can add that value & the data to a collection so you can the reference it later on.
foreach is much safer than a for loop, there are times where for loop is much preferred but I don't see this being one of those times.

You can solve it by following code
if you want to match value to some excel column E.G. ID
Put condition in for loop .... Because i think you want to match value with some column of excel..
string value = textBox3.Text;
Match match = Regex.Match(value, #".*[0-9].*");
Console.WriteLine(value);
int TotalRows = xlsDs.Rows.Count;
for(int i=0;i<TotalRows;i++)
{
DataRow row = xlsDs.Rows[i];
String row_Val=row["Cell_Name"].ToString();//Put Cell you want to match IE ID
Match myMatch = Regex.Match(row_Val, textBox3.Text);
if (match.Success && myMatch.Success)
{
Console.WriteLine(textBox3);
Console.Write(row.ItemArray.ToString());
//Console.WriteLine(row["Cell_Name"]);//if you want to print a specific cell
Console.WriteLine("This was found at row "+i);
}
}

Your error isn't the for vs foreach loop, it's the matching you're doing. Try this instead.
You also were not reading the rows in correctly, you should only look at the one column that you need. Change the column variable below to the correct column.
The primary difference between this and your code is that you want to check each row in the iteration and then if it is a match, print a line saying so. This is compared to what you did originally, where you compare one string once and if that is a match, print that over and over for each row.
string columnName = "Employee ID"; // change to the correct header
// Check the ID from the textbox to make sure it is valid?
Match match = Regex.Match(textBox3.Text #".*[0-9].*");
for(int i = 0; i < xlsDs.Rows.Count; i++)
{
// get the current row
DataRow row = xlsDs.Rows[i];
// get the ID from the row
string idValue = row[columnName].ToString();
// check if the row value is equal to the textbox entry
bool myMatch = idValue.Equals(textBox3.Text);
// if both of the above are true, do this
if (match.Success && myMatch == true)
{
Console.Write(idValue);
Console.WriteLine(" -This id was found");
}
}

Related

Insert a value in a specific line by index

private void Parse_Click(object sender, EventArgs e)
{
for (int i = 0; i < keywordRanks.Lines.Length; i++)
{
int p = keywordRanks.Lines.Length;
MessageBox.Show(p.ToString());
string splitString = keywordRanks.Lines[i];
string[] s = splitString.Split(':');
for (int j = 0; j < keywords.Lines.Length; j++)
{
string searchString = keywords.Lines[j];
if (s[0].Equals(searchString))
{
richTextBox1.Lines[j] = searchString + ':' + s[1];
}
}
}
}
I have an issue with inserting string in a particular line. I have 2 multi line TextBoxes and one RichTextBox.
My application will search for the strings from textbox1 to textbox2 line by line and need to insert those matched values in a RichTextBox control but in the exact index position where it found in textbox2.
If the value found in 5th line of textbox2 then that found line need to be inserted in the RichTextBox 5th line.
Some how my code is not working. I tried a lot but no luck. The code I need something like below but its not working and an IndexOutOfBound exception is raised.
richTextBox1.Lines[j] = searchString + ':' + s[1];
Your RichTextBox must contain all the needed lines before you can set the value using the line index.
If the Control contains no text or line breaks (\n), no lines are defined and any attempt to set a specific Line[Index] value will generate an IndexOutOfRangeException exception.
Here, I'm using a pre-built array, sized as the number of possible matches (the Lines.Length of the keywords TextBox). All matches found are stored here in the original position. The array is then assigned to the RichTextBox.Lines property.
Note: directly using and pre-setting the RichTextBox.Lines won't have effect: the text will remain empty.
string[] MatchesFound = new string[keywords.Lines.Length];
foreach (string currentSourceLine in keywordRanks.Lines)
{
string[] SourceLineValue = currentSourceLine.Split(':');
var match = keywords.Lines.ToList().FindIndex(s => s.Equals(SourceLineValue[0]));
if (match > -1)
MatchesFound[match] = currentSourceLine;
}
richTextBox1.Lines = MatchesFound;
Source Matches Result
(keywordRanks) (keywords) (RichTextBox)
-------------------------------------------
aand:1 aand aand:1
cnd:5 this one
cnds:9 cnds cnds:9
fan:2 another one
gst:0 cnd cnd:5
fan fan:2

How to get MS Word table in a word document next to specific heading using C#?

I am trying to identify specific value under corresponding column in a word table using c#. Tried:
1- If table index is known - get table range as text and iterate over it to reach certain row and column.
Problem is- Table comes under certain heading anywhere in the document. Index is variable, so can't rely on index.
As Cindy has pointed out, the question in a current form is too broad. I'm not sure how you're reading your documents. Also, I'm not sure what you mean by "certain heading", do you know what text will be before the targeted table?
Nevertheless, you could check out the following sample, the code uses GemBox.Document:
string cellValue = null;
string headingText = "My Heading Text";
int rowIndex = 0;
int columnIndex = 0;
// Load Word document.
DocumentModel document = DocumentModel.Load("Sample.docx");
// Iterate through all paragraphs.
foreach (Paragraph paragraph in document.GetChildElements(true, ElementType.Paragraph))
{
// Check that paragraph is of heading style.
ParagraphStyle style = paragraph.ParagraphFormat.Style;
if (style == null || !style.Name.Contains("heading"))
continue;
// Check that heading paragraph contains our text.
if (!paragraph.Content.ToString().Contains(headingText))
continue;
// Get first table after the heading paragraph.
Table table = new ContentRange(paragraph.Content.End, document.Content.End)
.GetChildElements(ElementType.Table)
.Cast<Table>()
.First();
// Get cell value.
cellValue = table.Rows[rowIndex].Cells[columnIndex].Content.ToString();
break;
}
Console.WriteLine(cellValue);

Error trying to read csv file

Good Day,
i am having trouble reading csv files on my asp.net project.
it always returns the error index out of range cannot find column 6
before i go on explaining what i did here is the code:
string savepath;
HttpPostedFile postedFile = context.Request.Files["Filedata"];
savepath = context.Server.MapPath("files");
string filename = postedFile.FileName;
todelete = savepath + #"\" + filename;
string forex = savepath + #"\" + filename;
postedFile.SaveAs(savepath + #"\" + filename);
DataTable tblcsv = new DataTable();
tblcsv.Columns.Add("latitude");
tblcsv.Columns.Add("longitude");
tblcsv.Columns.Add("mps");
tblcsv.Columns.Add("activity_type");
tblcsv.Columns.Add("date_occured");
tblcsv.Columns.Add("details");
string ReadCSV = File.ReadAllText(forex);
foreach (string csvRow in ReadCSV.Split('\n'))
{
if (!string.IsNullOrEmpty(csvRow))
{
//Adding each row into datatable
tblcsv.Rows.Add();
int count = 0;
foreach (string FileRec in csvRow.Split('-'))
{
tblcsv.Rows[tblcsv.Rows.Count - 1][count] = FileRec;
count++;
}
}
}
i tried using comma separated columns but the string that comes with it contains comma so i tried the - symbol just to make sure that there are no excess commas on the text file but the same error is popping up.
am i doing something wrong?
thank you in advance
Your excel file might have more columns than 6 for one or more rows. For this reason the splitting in inner foreach finds more columns but the tblcsv does not have more columns than 6 to assign the extra column value.
Try something like this:
foreach (string FileRec in csvRow.Split('-'))
{
if(count > 5)
return;
tblcsv.Rows[tblcsv.Rows.Count - 1][count] = FileRec;
count++;
}
However it would be better if you check for additional columns before processing and handle the issue.
StringBuilder errors = new StringBuilder(); //// this will hold the record for those array which have length greater than the 6
foreach (string csvRow in ReadCSV.Split('\n'))
{
if (!string.IsNullOrEmpty(csvRow))
{
//Adding each row into datatable
DataRow dr = tblcsv.NewRow(); and then
int count = 0;
foreach (string FileRec in csvRow.Split('-'))
{
try
{
dr[count] = FileRec;
tblcsv.Rows.Add(dr);
}
catch (IndexOutOfRangeException i)
{
error.AppendLine(csvRow;)
break;
}
count++;
}
}
}
Now in this case we will have the knowledge of the csv row which is causing the errors, and rest will be processed successfully. Validate the row in errors whether its desired input, if not then correct value in csv file.
You can't treat the file as a CSV if the delimiter appears inside a field. In this case you can use a regular expression to extract the first five fields up to the dash, then read the rest of the line as the sixth field. With a regex you can match the entire string and even avoid splitting lines.
Regular expressions are also a lot faster than splits and consume less memory because they don't create temporary strings. That's why they are used extensively to parse log files. The ability to capture fields by name doesn't hurt either
The following sample parses the entire file and captures each field in a named group. The last field captures everything to the end of the line:
var pattern="^(?<latitude>.*?)-(?<longitude>.*?)-(?<mps>.*?)-(?<activity_type>.*?)-" +
"(?<date_occured>.*?)-(?<detail>.*)$";
var regex=new Regex(pattern,RegexOptions.Multiline);
var matches=regex.Matches(forex);
foreach (Match match in matches)
{
DataRow dr = tblcsv.NewRow();
row["latitude"]=match.Groups["latitude"].Value);
row["longitude"]=match.Groups["longitude"].Value);
...
tblcsv.Rows.Add(dr);
}
The (?<latitude>.*?)- pattern captures everything up to the first dash into a group named latitude. The .*? pattern means the matching isn't greedy ie it won't try to capture everything to the end of the line but will stop when the first - is encountered.
The column names match the field names, which means you can add all fields with a loop:
foreach (Match match in matches)
{
var row = tblCsv.NewRow();
foreach (Group group in match.Groups)
{
foreach (DataColumn col in tblCsv.Columns)
{
row[col.ColumnName]=match.Groups[col.ColumnName].Value;
}
}
tblCsv.Rows.Add(row);
}
tblCsv.Rows.Add(row);

Exclude last line from StreamReader in C#

I'm saving some DataGridView's data into a text file(for data I'm refering to the content of each cell), and at the last line of the TXT File, I am storing the number of rows of the dataGridView with a "-" at the start of the line.
Now, I can read my data perfectly into my DVG, but how can I exclude the last line which contains my row count and also use it to read its stored int?
The code I use for reading the data into the DVG:
void LoadDVGData()
{
StreamReader sr = new StreamReader(open.FileName);
foreach (DataGridViewRow row in editDGV.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
string content = sr.ReadLine();
cell.Value = content;
}
}
sr.Close();
}
Thanks in Advance. - CCB
You just need to maintain one token of look ahead so that you can answer the question, "Is this the last line?" (if you have a current line, but no next line, you're positioned at the last line.
Here's one approach, which is probably about as simple as it gets:
void LoadDVGData()
{
using ( StreamReader sr = new StreamReader(open.FileName) )
{
string currentLine = sr.ReadLine() ;
string nextLine = sr.ReadLine() ;
foreach (DataGridViewRow row in editDGV.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
if ( currentLine == null ) throw new InvalidOperationException("Hmph. We seem to have run out of input data");
cell.Value = currentLine ;
currentLine = nextLine ;
nextLine = sr.ReadLine() ;
} //end cols loop
} // end rows loop
} // end using block
return;
}
I assume sr is the StreamReader that reads your text file - you should wrap that in a using or try..finally block to ensure correct cleanup in case of errors.
Your current setup doesn't work very well for cases where the text file doesn't match the number of rows / cells that you have in the DataGridView (DGV): you try reading a value from the file for each cell and if the wrong file is specified, you may attempt to read beyond the end of the file. You should have more error handling around this code because there may be various problem spots during reading the file: too few rows, too few cells for a row, invalid value for a particular cell, etc.
Your setup doesn't lend itself very well to handling. If you control the format of the text file, I'd recommend to change the format so that the very first row is the count and then each row in the text file describes a complete row for the DGV, using TAB as the delimiter. It'd be far simpler to load such a file. (You can even have the row count and column count on the first row to give you even more information about the data; you can never have too much metadata about input data.)
So your new textfile format would look something like:
3{TAB}5
R1C1{TAB}R1C2{TAB}R1C3{TAB}R1C4{TAB}R1C5{CRLF}
R2C1{TAB}R2C2{TAB}R2C3{TAB}R2C4{TAB}R2C5{CRLF}
R3C1{TAB}R3C2{TAB}R3C3{TAB}R3C4{TAB}R3C5{CRLF}
If you cannot change the text file format, then just read the file twice - first seek to the end of the file and read back to the end of the line before the last - then just read one line from it - it should be the row count. You can do this by looking for a newline in the file going from the end. Then just seek to the beginning of the file and read so many lines from it.
Edit:
As #vesan commented under the question, if your input file is not huge, you can just call File.ReadAllLines() to get all lines in a string[]. It's trivial to process it then. Using a more convenient file format would work, though, for any file size. Reading all lines assumes that the input file is not huge.
Edit 2:
For example (error handling omitted for brevity):
var sLines = File.ReadAllLines ( open.FileName );
var nRowCount = int.Parse ( sLines[sLines.Length - 1] );
var nIndex = 0;
foreach (DataGridViewRow row in editDGV.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
cell.Value = sLines[nIndex];
nIndex++;
}
}
If your text file is correct, nRowCount will have the correct number of rows and you'll never actually read the last element of your array into the DGV.

Remove certain letters from input string

I'm currently having a problem where when I search for a code I want to remove the any "."'s a user has inputted. The code I've done doesn't seem to be working and was wondering if someone could tell me why and what I need to do. Thanks.
foreach (var letters in id)
{
string letter = letters.ToString();
if (letter == ".")
{
id.Replace(letter, "");
}
}
String in .NET is an immutable type, therefore you can't change the value of an existing string variable, you need to replace it entirely with the value returned by Replace i.e.
id = id.Replace(letter, "");
FYI you don't have to check whether . is contained in the string, you can just call Replace(".", "") on the resultant string and it will remove any . present i.e.
id = id.Replace(".", "");
See example
String replace method
id = id.Replace(",", "");
Programmaticaly, maybe you can use that besides Replace() method
string m_tempStr = "This.is.a.test";
List<string> myList = new List<string>();
for (int i = 0; i < m_tempStr.Length; i++)
{
if (m_tempStr[i].ToString() != ".")
{
myList.Add(m_tempStr[i].ToString());
}
}
And than, you can get each member of list like following sample code
foreach (var item in myList)
{
Console.Write(item);
}

Categories

Resources