C# Read List values into Textboxes [duplicate] - c#

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 5 years ago.
I've been stuck on this problem for a little while now. I'm able to read information from a bunch (100) Textboxes and save the data into a CSV file but reading that information back into the form has me a little befuddled, I'm only trying to load the first 11 strings to start with. I can load the CSV into a List but I can't seem to move that data from the list to my Textboxes. Is there something I'm missing with my approach?
public List<string> LoadCsvFile(string filePath)
{
var reader = new StreamReader(File.OpenRead(filePath));
List<string> searchList = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
searchList.Add(line);
for (int i = 0; i < 11; i++)
{
string date = searchList[i];
string dropdownindex = searchList[i];
LasttextBox.Text = searchList[i];
FirsttextBox.Text = searchList[i];
EmailtextBox.Text = searchList[i];
PhonetextBox.Text = searchList[i];
HometextBox.Text = searchList[i];
InfotextBox.Text = searchList[i];
PrimarytextBox.Text = searchList[i];
EmailtextBox.Text = searchList[i];
SecondaryEmailtextBox.Text = searchList[i];
}
}
return searchList;
}
The error I'm getting is:
System.ArgumentOutOfRangeException: 'Index was out of range. Must be
non-negative and less than the size of the collection. Parameter name:
index'
I appreciate any help you can provide.

You are confusing lines with fields, and you don't even really need the List based on what it looks like you are trying to do. It seems like you are trying to assign field values to your text boxes.
Assuming your csv file looks similar to below(You have the e-mail textbox duplicated by the way):
Date,DropDownIndex,LastName,FirstName,Email,Phone,Home,Info,Primary,Email,SecondaryEmail
You can use Linq to parse your CSV file into an anonymous class with all the values you want and then loop through and assign those to your text boxes
For example:
var csvRecords = File
.ReadAllLines(filePath)
.Select(c => c.Split(',')).Select(c => new
{
Date = c[0],
DropDown = c[1],
LastName = c[2],
FirstName = c[3],
Email = c[4],
Phone = c[5],
Home = c[6],
Info = c[7],
Primary = c[8],
Email2 = c[9],
SecondaryEmail = c[10]
}).ToList();
foreach (var csvRecord in csvRecords)
{
var date = csvRecord.Date;
var dropdownindex = csvRecord.DropDown;
LasttextBox.Text = csvRecord.LastName;
FirsttextBox.Text = csvRecord.FirstName;
EmailtextBox.Text = csvRecord.Email;
PhonetextBox.Text = csvRecord.Phone;
HometextBox.Text = csvRecord.Home;
InfotextBox.Text = csvRecord.Info;
PrimarytextBox.Text = csvRecord.Primary;
EmailtextBox.Text = csvRecord.Email2;
SecondaryEmailtextBox.Text = csvRecord.SecondaryEmail;
}
Some things you will need to consider is if your CSV file only contains comma delimiters and no double quote qualifiers as there could potentially be commas in the actual values which will then throw off the positions of your various fields. If you are still wanting to return a List via the method, you can't return the anonymous typed list, so you will need to create a class, and then instead of using the new in the Linq select, you would use new and assign the fields the same way.

This approach is more scalable, i.e., it will work with any number of csv file rows and/or text boxes so long as you have control over the names of the text boxes. This design ignores lines from the csv file that there is no text box for
public Form1()
{
InitializeComponent();
//simulate a list loaded from a csv file
IList<string> stringsFromCsv = new List<string>
{
"from csv line dog",
"from csv line cat",
"from csv line fish",
"from csv line frog",
"from csv line squirrel",
"from csv line turtle",
"from csv line squid",
"from csv line bass",
"from csv line tiger",
"from csv line lion"
};
//make a collection of all the controls in the groupbox (or form, or whatever)
Control.ControlCollection controls = groupBox1.Controls;
int listIndex = 0;
//loop based on the number of items from the csv file
while (listIndex <= stringsFromCsv.Count - 1)
{
//create a text box name from the current list index
string expectedTextBoxName = "textBox" + ((listIndex + 1).ToString());
//this is brute force, but step thru all the controls until
//you find a text box whose name matches
foreach (Control control in controls)
{
//skip the control if its not a text box
if (control.GetType().Name != "TextBox")
continue;
if (control.Name == expectedTextBoxName)
{
control.Text = stringsFromCsv[listIndex];
break;
}
}
listIndex = listIndex + 1;
if (listIndex > stringsFromCsv.Count - 1)
break;
}
}

Related

C#, Read CSV for repeated cell values in 2 columns, count how many times something appears, add 1 to it and append it to a string for number increment

Basically, I have a friendly name generator that consist of Project Name_Project Build_, and a number at the end indicating that its for example 3rd of 3 total of same project and build. Example: This is what I have in CSV File: the number at the end keeps incrementing counting rows +1.
Project Name, Project Build
Toyota, 2007
Toyota, 2007
Friendly name = Toyota_2007_01 > where 1 indicates that Toyota and 2007 only appears once in same row.
Adding 1 more Toyota 2007, would generate a friendly name: Toyota_2007_02 where 02 indicates that there are 2 of same Toyota 2007 in the csv so if I add next, it will append 03 for the 3rd entry
This is what the csv should have now:
(csv Header)
Project Name, Project Build, Friendly Name.
Toyota, 2007, Toyota_2007_01.
Toyota, 2007, Toyota_2007_02
If I add a different project in the same csv in the next available row,
Honda 2009
than code should find that Honda and 2009 in "same row" only appears once so friendly name should be Honda_2009_01....
My code already generates the friendly name up to "build year" but I want it to actually go in the csv, read it and find how may time project name and build year appear in same row and count, than add 1 to append that number at the end depending on how many of those things are in the file.
Here is the Code so far.
some code above...
{
// counting lines in CSV file
// This method counts the number of Rows in the File skipping over the header row assigns value to variable, increments by 1 for next entry
using (StreamWriter sw = new StreamWriter(path, true)) // true for appending data to file, false to overwrite in file
{
if (headerLine)
{
sw.WriteLine(header);
sw.WriteLine(string.Format(projectName + "," + projetcBuild.ToString() + "," + projectSN.ToString()));
}
else if (File.Exists(path))
{
sw.WriteLine(string.Format(projectName + "," + projetcBuild.ToString() + "," + projectSN.ToString()));
}
}
int counter = 0;
string line;
StreamReader file = new StreamReader(#"C:\LOG.csv");
string headerLine = file.ReadLine();
while ((line = file.ReadLine()) != null)
{
counter++;
}
string FreindlyName = ProjectName_TextBox.Text + "_" + ProjectBuild_TextBox.Text + "_" + counter;
file.Close();
The CSV should have, this
I hope I did not over explain this. Thanks in advance.
First, I noticed your counter is totally wrong. I just fixed your counter hope this can solve your problem.
string line;
StreamReader file = new StreamReader(#"C:\LOG.csv");
string headerLine = file.ReadLine() ;
var counter = new List<string>();
while (!string.IsNullOrWhiteSpace( (line = file.ReadLine()) ))
{
var cells = line.Split(','); // use your seprator => , |
var projectFullName = $"{cells[0]}_{cells[1]}"; // eg Toyota_2007
counter.Add(projectFullName);
}
var newName = ProjectName_TextBox.Text + "_" + ProjectBuild_TextBox.Text
var newCount = counter.Where(q=> q == newName).Count() + 1;
string freindlyName = $"{newName}_{newCount.ToString("00")}"; // freindlyName with correct number
file.Close();
UPDATE:
A better counter.
just add this function to your code and use it to get correct count of your records.
public int CountFromLogFile(string projectName, string projectBuild, char seprator ,string csvPath)
{
var isHeader = true;
var counterDic = new Dictionary<string,int>();
foreach (var line in File.ReadLines(csvPath))
{
if (isHeader)
{
isHeader = false;
continue;
}
var cells = line.Split(seprator); // 0 => projectName & 1 => projectBuild
var fName = $"{cells[0]}_{cells[1]}";
if (counterDic.ContainsKey(fName))
counterDic[fName]++;
else
counterDic.Add(fName,0);
}
var qName = $"{projectName}_{projectBuild}";
return counterDic.ContainsKey(qName) ? counterDic[qName] : 0 ;
}
Usage:
var count = CountFromLogFile(ProjectName_TextBox.Text , ProjectBuild_TextBox.Text , ',' , #"C:\LOG.csv");

How to incorporate a text qualifier in a file name used as a variable?

I have a C# script which takes in two CSV files as input, combines the two files, performs numerous calculations on them, and writes the result in a new CSV file.
These two input CSV file names are declared as variables and are used in the C# script by accessing those variable names.
The data in the input CSV files looks like this:
Since the data has values in thousands and millions, line splits in the C# code are truncating the data incorrectly. For instance a value of 11,861 appears only as 11 and 681 goes in the next columns.
Is there any way in C#, by which I can specify a text qualifier (" in this case) for the two files ?
Here is the C# code snippet:
string[,] filesToProcess = new string[2, 2] { {(String)Dts.Variables["csvFileNameUSD"].Value,"USD" }, {(String)Dts.Variables["csvFileNameCAD"].Value,"CAD" } };
string headline = "CustType,CategoryType,CategoryValue,DataType,Stock QTY,Stock Value,Floor QTY,Floor Value,Order Count,Currency";
string outPutFile = Dts.Variables["outputFile"].Value.ToString();
//Declare Output files to write to
FileStream sw = new System.IO.FileStream(outPutFile, System.IO.FileMode.Create);
StreamWriter w = new StreamWriter(sw);
w.WriteLine(headline);
//Loop Through the files one by one and write to output Files
for (int x = 0; x < filesToProcess.GetLength(1); x++)
{
if (System.IO.File.Exists(filesToProcess[x, 0]))
{
string categoryType = "";
string custType = "";
string dataType = "";
string categoryValue = "";
//Read the input file in memory and close after done
StreamReader sr = new StreamReader(filesToProcess[x, 0]);
string fileText = sr.ReadToEnd();
string[] lines = fileText.Split(Convert.ToString(System.Environment.NewLine).ToCharArray());
sr.Close();
where csvFileNameUSD and csvFileNameCAD are variables with values pointing to their locations.
Well, based on the questions you have answered, this ought to do what you want to do:
public void SomeMethodInYourCodeSnippet()
{
string[] lines;
using (StreamReader sr = new StreamReader(filesToProcess[x, 0]))
{
//Read the input file in memory and close after done
string fileText = sr.ReadToEnd();
lines = fileText.Split(Convert.ToString(System.Environment.NewLine).ToCharArray());
sr.Close(); // redundant due to using, but just to be safe...
}
foreach (var line in lines)
{
string[] columnValues = GetColumnValuesFromLine(line);
// Do whatever with your column values here...
}
}
private string[] GetColumnValuesFromLine(string line)
{
// Split on ","
var values = line.Split(new string [] {"\",\""}, StringSplitOptions.None);
if (values.Count() > 0)
{
// Trim leading double quote from first value
var firstValue = values[0];
if (firstValue.Length > 0)
values[0] = firstValue.Substring(1);
// Trim the trailing double quote from the last value
var lastValue = values[values.Length - 1];
if (lastValue.Length > 0)
values[values.Length - 1] = lastValue.Substring(0, lastValue.Length - 1);
}
return values;
}
Give that a try and let me know how it works!
You posted a very similar looking question few days ago. Did that solution not help you?
If so, what issues are you facing on that. We can probably help you troubleshoot that as well.

Problems reading multiple lines from a text file and saving them into an array c#

So what I want to be able to do is read a file that has one data segment that reads like this. So far the program opens the file from a drop down menu but I am having a hard time saving them into array. I wish to be able to click a next button after opening the file (Where it prints the last three lines from the text file into the text boxes) on a form application, and it prints each information line in the text file example below into a separate text box. This is where I am having the problem.
The names and addresses are to be saved to a EmpNames Class, and then the .split() numbers below are to be saved into their own respective Employee Class so as to be set into a series of calculations, then print the result in a text box.
1
John MerryWeather
123 West Main Street
5.00 30
There will be multiple data segments like this, but no more than 10. This is what I have so far.
public partial class Form1 : Form
{
const int MAX = 10;
public Form1()
{
InitializeComponent();
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog theDialog = new OpenFileDialog();
theDialog.Title = "Open Text File";
theDialog.Filter = "TXT files|*.txt";
theDialog.InitialDirectory = #"C:\";
if (theDialog.ShowDialog() == DialogResult.OK)
{
//Declarations:
// linesPerEmployee: Controls the number of lines to be read.
// currEmployeeLine: Controls where in the file you are reading.
Employee employee = new Employee();
NameAdd empNames = new NameAdd();
string filename = theDialog.FileName;
List<Employee> employeeList = new List<Employee>();
int linesPerEmployee = 4;
int currEmployeeLine = 0;
//parse line by line into instance of employee class
while (employeeList != null)
{
string[] filelines = File.ReadAllLines(filename);
if (filelines != null)
{
employee.EmpNum = int.Parse(filelines[0]);
empNames.Name =
}
}
Instead of reading all lines in one chunk you could read them line by line and add each line into a List<string> for example, to easier handle the "lines"
var employees = new List<string>();
Stream file = theDialog.File.OpenRead();
while((line = file.ReadLine()) != null)
{
employees.Add(line);
}
And then loop through the employee list to parse each 4 lines into an Employee()
Still, I agree with the comments about using a better format instead.
too agree with the others about a better file format, but also, what happens if your data gets out of whack, missing or extra lines, any confirmation about sequence numbering between employees, bad data that can't be converted... all this and more say bad idea to current format.
However, that being said, and what you already have going, I would wrap it up something like...
string[] filelines = File.ReadAllLines(filename);
if (filelines != null)
{
if (filelines.Length % 4 == 0)
{
// which array element are we getting to at the start of each employee.
int arrayBase = 0;
for( int i=0; i < (int)(filelines.Length / 4); i++ )
{
arrayBase = i*4;
employee.EmpNum = int.Parse(filelines[arrayBase]);
empNames.Name = filelines[arrayBase + 1];
empNames.Address = filelines[arrayBase + 2];
string[] rateAndHours = filelines[arrayBase + 3].Split(' ');
// you would still have to parse the rate and hours though.
double justRate = double.Parse(rateAndHours[0]);
int justHours = int.Parse(rateAndHours[1]);
// obviously add your own try\catch confirmation on parsing issues
// and ultimately store in your record entries
}
}
}

Eliminate special characters from CSV with C#

I am getting data from a CSV file through my Web Api with this code
private List<Item> items = new List<Item>();
public ItemRepository()
{
string filename = HttpRuntime.AppDomainAppPath + "App_Data\\items.csv";
var lines = File.ReadAllLines(filename).Skip(1).ToList();
for (int i = 0; i < lines.Count; i++)
{
var line = lines[i];
var columns = line.Split('$');
//get rid of newline characters in the middle of data lines
while (columns.Length < 9)
{
i += 1;
line = line.Replace("\n", " ") + lines[i];
columns = line.Split('$');
}
//Remove Starting and Trailing open quotes from fields
columns = columns.Select(c => { if (string.IsNullOrEmpty(c) == false) { return c.Substring(1, c.Length - 2); } return string.Empty; }).ToArray();
var temp = columns[5].Split('|', '>');
items.Add(new Item()
{
Id = int.Parse(columns[0]),
Name = temp[0],
Description = columns[2],
Photo = columns[7]
});
}
}
But the CSV file returned data with special characters instead of an apostrophe.
For example in the CSV file the are values such as There’s which should be "There's" or "John’s" which should be "John's".
This ’ is there instead of an apostrophe.
How do I get rid of this to just show my apostrophe.
This kind of data is being returned in
Name = temp[0],
Description = columns[2],
You can use the HttpUtility.HtmlDecode to convert the characters. Here's an example:
var withEncodedChars = "For example in the CSV file the are values such as There’s which should be There's or John’s which should be John's. This ’ is there instead of an apostrophe.";
Console.WriteLine(HttpUtility.HtmlDecode(withEncodedChars));
If you run this in a console app it outputs:
For example in the CSV file the are values such as There's which should be There's or John's which should be John's. This ' is there instead of an apostrophe.

csv file reading only first line

I'm trying to upload a series of client info's through a csv ,I had some trouble with this in the eginning but my previous post was answered so I was able to start reading in the data however it only reads the first line. Just wondering if anyone had any ideas. I've included the code below
private void btnUpload_Click(object sender, EventArgs e)
{
//Browse for file
OpenFileDialog ofd = new OpenFileDialog();
//Only show .csv files
ofd.Filter = "Microsoft Office Excel Comma Separated Values File|*.csv";
DialogResult result = ofd.ShowDialog();
//If the user selects a valid file
if (result == DialogResult.OK)
{
//File is delimited by a comma
char[] laClientDelim = { ',' };
//New object for string manipulation
objStringManipulation = new StringManipulation();
// Parse the csv file
List<string[]> lsClientList = objStringManipulation.parseCSV(ofd.FileName, laClientDelim);
foreach (string[] laClient in lsClientList)
{
//Create new object for manipulating the database
objSqlCommands = new SqlCommands("Client", "ClientName");
string[] records = File.ReadAllLines(ofd.FileName); // read the file completely line by line
char splitChar = ',';
int splitCharCount = 0;
int k = 0;
string[] fields = records[k].Split(splitChar); // reads all the single values per line. 'splitChar' should be the delimiter.
splitCharCount++;
if (splitCharCount >= 4 && splitCharCount <= 10)
{
var stuff = from l in File.ReadLines(ofd.FileName)
let x = l.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Skip(1)
.Select(s => char.Parse(s))
select new
{
Client = x,
ClientName = x
};
}
//Inserts the client info into datbase
objSqlCommands.sqlCommandInsertorUpdate("INSERT", records[k]);//laClient[0]);
k++;
//Refreshs the Client table on display from the
this.clientTableAdapter.Fill(this.kIIDImplementationCalcDataSet.Client);
//MAKE SURE TO ONLY ADD IN CLIENT AND CLIENT NAME
//update the view
dgvClientlst.Update() ;
}
}
}
your loop looks like this essentially :
foreach (string[] laClient in lsClientList)
{
int k = 0;
string[] records = File.ReadAllLines(ofd.FileName);
string[] fields = records[k].Split(splitChar);
k++;
}
Your 'k' value never makes it past 0 for each laClient. You need to loop internally for each line.
I know my answer is not exactly what you are looking for but if you convert the .csv file to .xls file then you can manipulate it very easily. I have done this on multiple occasions and if you want I can provide you instructions with code.
Expanding on Jonesy's answer (because I can't yet comment), declare the variable k outside the loop. It's being reset to zero each time through.
int k = 0;
foreach (string[] laClient in lsClientList)
{
string[] records = File.ReadAllLines(ofd.FileName);
string[] fields = records[k].Split(splitChar);
k++;
}

Categories

Resources