C# While loop skipping virst line when parsing csv - c#

I have a simple CSV file I need to parse that has variable column lengths. CSV File for reference.
I'm attempting to write some conditions to parse each line and store into a discreet string based off what value the first column contains in each line.
The first issue that I'm running into is that my loop seems to start reading at row 2. Is this because TextFieldParser assumes a header?
The second issue is that my if statements don't seem to be evaluating correctly. If I shift the order of the rows within the file, my first if in the order is supposed to parse the "Lighting" rows (regardless of which rows in the file contain "Lighting").
Just as a note, I am working in a .net 3.5 environment
Here's what I've got so far:
namespace CSV_Handler_Console
{
public class Program
{
public static void Main(string[] args)
{
//Console.WriteLine("Press Enter");
string filePath = "C:\\Users\\chris\\Desktop\\ConfigFile.csv";
string subLight = "Lighting";
string subPin = "PIN";
string subProc = "Processor";
string subFab = "Fabuloso";
string subQuirky = "Quirky";
//string[] fields = csvParser.ReadFields();
string category = string.Empty;
string index = string.Empty;
string load1 = string.Empty;
string load2 = string.Empty;
string load3 = string.Empty;
string load4 = string.Empty;
string value = string.Empty;
string light1 = string.Empty;
string light2 = string.Empty;
string light3 = string.Empty;
string pin = string.Empty;
string processor1 = string.Empty;
string processor2 = string.Empty;
string processor3 = string.Empty;
string processor4 = string.Empty;
string processor5 = string.Empty;
string processor6 = string.Empty;
string processor7 = string.Empty;
string processor8 = string.Empty;
string display1 = string.Empty;
string display2 = string.Empty;
string display3 = string.Empty;
string display4 = string.Empty;
string display5 = string.Empty;
string display6 = string.Empty;
string display7 = string.Empty;
string display8 = string.Empty;
var path = String.Format("{0}", filePath);
using (TextFieldParser csvParser = new TextFieldParser(path))
{
csvParser.SetDelimiters(new string[] { "," });
//csvParser.HasFieldsEnclosedInQuotes = false;
string row = csvParser.ReadLine();
while (!csvParser.EndOfData)
{
if (row.Contains(subLight))
{
string[] fields = csvParser.ReadFields();
category = fields[0];
index = fields[1];
load1 = fields[2];
load2 = fields[3];
load3 = fields[4];
load4 = fields[5];
if(index.Contains("1"))
{
light1 = row;
}
else if (index.Contains("2"))
{
light2 = row;
}
else if (index.Contains("3"))
{
light3 = row;
}
string rowData = string.Format("{0},{1},{2},{3},{4},{5}", category, index, load1, load2, load3, load4);
Console.WriteLine(rowData);
//Console.ReadLine();
}
else if (row.Contains(subPin))
{
string[] fields = csvParser.ReadFields();
category = fields[0];
index = fields[1];
value = fields[2];
string rowData = string.Format("{0},{1},{2}", category, index, value);
Console.WriteLine(rowData);
}
else if (row.Contains(subProc))
{
string[] fields = csvParser.ReadFields();
category = fields[0];
index = fields[1];
value = fields[2];
if (index.Contains("A"))
{
processor1 = row;
}
else if (index.Contains("B"))
{
processor2 = row;
}
else if (index.Contains("C"))
{
processor3 = row;
}
else if (index.Contains("D"))
{
processor4 = row;
}
else if (index.Contains("E"))
{
processor5 = row;
}
else if (index.Contains("F"))
{
processor6 = row;
}
else if (index.Contains("G"))
{
processor7 = row;
}
else if (index.Contains("H"))
{
processor8 = row;
}
string rowData = string.Format("{0},{1},{2}", category, index, value);
Console.WriteLine(rowData);
}
else if (row.Contains(subQuirky) || row.Contains(subFab))
{
string[] fields = csvParser.ReadFields();
category = fields[0];
index = fields[1];
value = fields[2];
if (index.Contains("A"))
{
display1 = row;
}
else if (index.Contains("B"))
{
display2 = row;
}
else if (index.Contains("C"))
{
display3 = row;
}
else if (index.Contains("D"))
{
display4 = row;
}
else if (index.Contains("E"))
{
display5 = row;
}
else if (index.Contains("F"))
{
display6 = row;
}
else if (index.Contains("G"))
{
display7 = row;
}
else if (index.Contains("H"))
{
display8 = row;
}
string rowData = string.Format("{0},{1},{2}", category, index, value);
Console.WriteLine(rowData);
}
else
{
Console.WriteLine("No Match Found");
}
}
Console.ReadLine();
}
}
}
Any guidance would be appreciated.

It's your implementation. You first grab the first row with ReadLine, which advances the cursor to the next line. Then if the row contains your search property, you do a ReadFields, which is the 2nd line of the document.
If your data is always guaranteed to have the category, you could just use ReadFields and compare against the first element. You could look at PeekChars if you want to look at the content of the current row without advancing the cursor.
TextFieldParser.ReadLine: Returns the current line as a string and
advances the cursor to the next line.
TextFieldParser.ReadFields: Reads all fields on the current line,
returns them as an array of strings, and advances the cursor to the
next line containing data.
TextFieldParser.PeekChars: Reads the specified number of characters without advancing the cursor.

Related

How to replace column data with blank inside C# script

I have been trying to add code to replace column data that has the word "null" to just a blank. I am not proficient in C#, so have no idea where to add it or how to code it. Below is the snippet of code that reads from the text file. I have no clue if the current code supports adding the replacement logic, so I am open to modifying the code to make it happen.
public override void PreExecute()
{
base.PreExecute();
int columnIndex;
string columnName = string.Empty;
string currentFile = Variables.vCurrentInputFile;
string[] currentRowValues;
string delimiter = Variables.vFileDelimiter;
Type fieldDataType;
string messageText;
DataRow row;
int upperBound;
bool skippedColumn = false;
var skippedColumns = new StringBuilder();
_FormatProvider = CultureInfo.GetCultureInfo(ComponentMetaData.LocaleID);
if (BuildImportBuffer())
{
try
{
using (var fileReader = new TextFieldParser(currentFile))
{
fileReader.SetDelimiters(delimiter);
fileReader.TrimWhiteSpace = false;
var fileColumns = fileReader.ReadFields();
while (!fileReader.EndOfData)
{
currentRowValues = fileReader.ReadFields();
if (currentRowValues != null)
{
upperBound = currentRowValues.GetUpperBound(0);
row = _BufferTable.NewRow();
try
{
var loopTo = upperBound;
for (columnIndex = 0; columnIndex <= loopTo; columnIndex++)
{
columnName = fileColumns[columnIndex];
if (!skippedColumn || skippedColumn && !skippedColumns.ToString().Contains(columnName))
{
fieldDataType = _BufferTable.Columns[columnName].DataType;
row[columnName] = Convert.ChangeType(currentRowValues[columnIndex].Trim(), fieldDataType, _FormatProvider);
}
}
}
I really need help with the code since I don't even know how to modify the current logic.

Dynamics NAV Webservice Fails on 2nd Loop

I have created a C# program to read a pipe ("|") delimited file and create purchase invoices and lines. Essentially, I have it loop through each line, if the "Report ID" has not been used, it creates a header, then the line, if the header has been created, it skips the header creation and is supposed to add the subsequent line. However, when I reach my object assignment for the line, it errors with:
"ArgumentException was unhandled"
"Must specify valid information for parsing the string."
The PIheader function works fine, so I have not included here. Please advise if more information/code is needed.
//Parse selected SAE File
SAEline[] sae = ParseSAE.Parse(file);
//Begin Analyzing Data
int saesize = sae.Length;
int i = 0;
List<string> cashIDs = new List<string>();
string paymentterms = "";
string invno = "";
string company = "";
string[] getcompany = new string[2];
string reportid = sae[i].ReportID;
int lineno = 0;
while(i < 10) //limit the loop for testing
//while (i < saesize)
{
if (sae[i].ReportEntryPaymentCodeCode != "CBCP")
{
if (!cashIDs.Contains(reportid))
{
cashIDs.Add(reportid);
getcompany = WebServices.GetCompany(sae[i].EmployeeID.ToUpper());
paymentterms = sae[i].ReportEntryPaymentCodeCode;
invno = WebServices.PIheader(getcompany[0], getcompany[1], 0, sae[i]);
lineno = 0;
}
lineno = lineno + 10000;
company = getcompany[0];
lineno = WebServices.PIlines(invno, lineno, company, sae[i]);
}
i++;
}
The WebService.cs contains:
//Web Service Client
PurchLines.PurchLines_PortClient piClient =
new PurchLines_PortClient((System.ServiceModel.Channels.Binding)basicHttpBindingNTLM,
new EndpointAddress("URL" + company + "/Page/PurchLines"));
//Conditional variables
string joblinetype = "";
string qty = "";
if (sae.ReportEntryCustom1 == "Billable")
{
joblinetype = "3";
}
if (sae.BusinessDistance == "")
{
if (sae.ReportCustom2 == "")
{
qty = "1";
}
else
{
qty = sae.ReportCustom2;
}
}
else
{
qty = sae.BusinessDistance;
}
string unitcost = (Convert.ToDecimal(sae.ReportEntryApprovedAmount)/Convert.ToDecimal(qty)).ToString();
//Line Creation
PurchLines.PurchLines line = new PurchLines.PurchLines()
{
No = sae.JournalAccountCode,
Line_No = Convert.ToInt16(lineno),
Line_NoSpecified = true,
Job_Line_TypeSpecified = true,
Job_Line_Type = (PurchLines.Job_Line_Type) (Enum.Parse(typeof (PurchLines.Job_Line_Type), joblinetype)),
QuantitySpecified = true,
Quantity = Convert.ToDecimal(qty),
TypeSpecified = true,
Type = (PurchLines.Type) (Enum.Parse(typeof (PurchLines.Type), "1")),
Direct_Unit_CostSpecified = true,
Direct_Unit_Cost = Convert.ToDecimal(unitcost),
Job_Unit_PriceSpecified = true,
Job_Unit_Price = Convert.ToDecimal(unitcost),
Job_No = sae.ReportEntryCustom5,
Job_Task_No = sae.ReportEntryCustom6,
Document_TypeSpecified = true,
Document_Type = (PurchLines.Document_Type)(Enum.Parse(typeof(PurchLines.Document_Type),"2")),
Document_No = invno
};
piClient.Create(ref line);
PurchLines.Create_Result result = new PurchLines.Create_Result(line);
int lin = result.PurchLines.Line_No;
return lin;
}
I realized that I didn't assign a value to joblinetype in the event that it is not "Billable", so the webservice was unable to Parse the blank string
Job_Line_Type = (PurchLines.Job_Line_Type) (Enum.Parse(typeof (PurchLines.Job_Line_Type), joblinetype)),

search a Text File for a sentence by date AND name

I am trying to search my text-file for a sentence by date and by name. Then I want this sentence to load it to some textboxes in my form. I am new in VS but I know some things about C.
I have came up with this code:
string pattern = dateTimePicker1Is.Text;
string pattern1 = _txtNameIs.Text;
IList<string> result = new List<string>();
using (var reader = new StreamReader(#"C:\Users\user\Desktop\Testet System\isto.txt"))
{
string currentLine;
while ((currentLine = reader.ReadLine()) != null)
{
if (currentLine.Contains(pattern))
{
if (currentLine.Contains(pattern1))
{
result.Add(currentLine);
string[] tempArray = currentLine.Split(',');
_txtNameIs.Text = tempArray[0];
_txtSurnameIs.Text = tempArray[1];
_txtApokxT.Text = tempArray[2];
_txtApoktT.Text = tempArray[3];
_txtEpanxT.Text = tempArray[4];
_txtEpandT.Text = tempArray[5];
_txtApokkT.Text = tempArray[6];
_txtEpankT.Text = tempArray[7];
_txtApoksT.Text = tempArray[8];
_txtEpansT.Text = tempArray[9];
_txtGenSun.Text = tempArray[10];
break;
}
else
{
MessageBox.Show("There are no records!");
}
}
}
}
When I press the search button it loads me all the data that I need, but if I have the same name and different date a message-box pops up and tells 'there are no records'.
I believe there is better way doing this:
string pattern = dateTimePicker1Is.Text;
string pattern1 = _txtNameIs.Text;
string pathToFile = #"C:\Users\user\Desktop\Testet System\isto.txt";
List<string> result = new List<string>();
foreach (var line in File.ReadAllLines(pathToFile))
{
if (line.Contains(pattern) && line.Contains(pattern1))
{
result.Add(line);
string[] tempArray = line.Split(',');
if(tempArray.Length >= 11)
{
_txtNameIs.Text = tempArray[0];
_txtSurnameIs.Text = tempArray[1];
_txtApokxT.Text = tempArray[2];
_txtApoktT.Text = tempArray[3];
_txtEpanxT.Text = tempArray[4];
_txtEpandT.Text = tempArray[5];
_txtApokkT.Text = tempArray[6];
_txtEpankT.Text = tempArray[7];
_txtApoksT.Text = tempArray[8];
_txtEpansT.Text = tempArray[9];
_txtGenSun.Text = tempArray[10];
break;
}
}
}
It is better to show message if the list count is 0.
I think your There are no records error should happen
AFTER the while statement
IF no matches were found
Right?
So put if there was a match found in a bool, and then after the while if !IsMatchFound then throw your error.

Comparing user Input to data in comma-delimited file and return data from file if matches input

I have a CSV file with a single column containing people names.
I need to take both the user input and the data in the file, strip all non-alphabetical characters, then convert to lower case before comparing with the two.
The file looks like this:
For Example:
Lets say the user enters: Obrien and the csv file contains O'Brien. To compare the two I need to make both lowercase, remove the apostrophe before comparing.
If the name matches, then I will return the name in the file (not the user input).
I am unable to compare the data when there is more then one name or row in the file.
public string MatchedName(string input)
{
string nameMatch = null;
string[] matchList = null;
const string matchFile = #"C:\matchedfile.txt";
using (StreamReader r = new StreamReader(matchFile))
{
string matchContent = "";
while ((matchContent = r.ReadLine()) != null)
{
matchList = matchContent.Split(',');
}
}
foreach (string name in matchList)
{
nameMatch = name;
}
if (String.Equals(RemoveCharTab(input), RemoveCharTab(nameMatch)))
{
return nameMatch;
}
else
{
return input;
}
}
And the following Regex to strip unwanted characters.
public string RemoveCharTab(string input)
{
return Regex.Replace(input.ToLower(), #"[^a-zA-Z]", "");
}
Your code selects values in last row, not the column with names.
Try the following code:
public string MatchedName(string input)
{
const int nameColumnIndex = 0;
const string matchFile = #"C:\matchedfile.txt";
string normalizedInput = RemoveCharTab(input);
string[] names = File.ReadAllLines(matchFile)
.Select(l => l.Split(',')[nameColumnIndex])
.Select(s => s.Trim())
.ToArray();
return names.FirstOrDefault(n => string.Equals(RemoveCharTab(n), normalizedInput)) ?? input;
}
I am unable to compare the data when there is more then one name or row in the file.
Because according to given code you are just splitting last row of text file. If a file contains just one name that will be fine. Otherwise if there are multiple rows then you are just comparing last row only.
You have to split and compare each row in while loop. See following code:
public string MatchedName(string input)
{
string nameMatch = null;
string[] matchList = null;
const string matchFile = #"C:\matchedfile.txt";
using (StreamReader r = new StreamReader(matchFile))
{
string matchContent = "";
while ((matchContent = r.ReadLine()) != null)
{
matchList = matchContent.Split(',');
foreach(string name in matchList)
{
if (String.Equals(RemoveCharTab(input), RemoveCharTab(name)))
{
nameMatch = name;
break;
}
else
{
continue;
}
}
if(string.IsNullOrEmpty(nameMatch) == false)
break;
else
continue;
} //end of While
}
if (string.IsNullOrEmpty(nameMatch) == true)
{
return input;
}
else
{
return nameMatch;
}
return string.Empty; //or something as per your requirements
}
NOTE: if input is comma-separated then you need to split otherwise you can use just string.

Unable to modify a dataset before binding to gridview in asp.net

I need to modify a dataset before binding it to a gridview.
When I walk through the complete code block, and hover over dsEmployeeOrg, that records
dont appear modified. What am I missing here?
My code is:
DataSet dsEmployeeOrg = eCorporateStaffMgr.GetEmployeeAccessLevel(oEmp);
DataTable dt = dsEmployeeOrg[0];
string sManagerID = "";
string sSupervisorID = "";
string sEmployeeID = "";
for (int i = 0; i < dsEmployeeOrg.Tables[0].Rows.Count; i++)
{
sManagerID = dt.Rows[i].ItemArray[3].ToString().Trim();
sSupervisorID = dt.Rows[i].ItemArray[4].ToString().Trim();
sEmployeeID = dt.Rows[i].ItemArray[5].ToString().Trim();
if ((sManagerID.ToString().Trim() != sSupervisorID.ToString().Trim()) && (sManagerID.ToString().Trim() != sEmployeeID.ToString().Trim()))
{
if (sSupervisorID.ToString().Trim() == sEmployeeID.ToString().Trim())
{
// This is a Supervisor record
dt.Rows[i].ItemArray[2] = "1111";
}
else if (sSupervisorID.ToString().Trim() != sEmployeeID.ToString().Trim())
{
//This is a Employee record
dt.Rows[i].ItemArray[2] = "0000";
}
}
}
Please modify your code as below
DataSet dsEmployeeOrg = eCorporateStaffMgr.GetEmployeeAccessLevel(oEmp);
DataTable dt = dsEmployeeOrg[0];
string sManagerID = "";
string sSupervisorID = "";
string sEmployeeID = "";
for (int i = 0; i < dsEmployeeOrg.Tables[0].Rows.Count; i++)
{
sManagerID = dt.Rows[i].ItemArray[3].ToString().Trim();
sSupervisorID = dt.Rows[i].ItemArray[4].ToString().Trim();
sEmployeeID = dt.Rows[i].ItemArray[5].ToString().Trim();
if ((sManagerID.ToString().Trim() != sSupervisorID.ToString().Trim()) && (sManagerID.ToString().Trim() != sEmployeeID.ToString().Trim()))
{
if (sSupervisorID.ToString().Trim() == sEmployeeID.ToString().Trim())
{
// This is a Supervisor record
dt.Rows[i][2] = "1111";
}
else if (sSupervisorID.ToString().Trim() != sEmployeeID.ToString().Trim())
{
//This is a Employee record
dt.Rows[i][2] = "0000";
}
}
}

Categories

Resources