Writing in an CSV file using C# - c#

I'm looking for a way to write strings in a different cell of a CSV file.
I'm using this program,
private void button1_Click(object sender, EventArgs e)
{
string filePath = #"E:\test.csv";
string a = "a";
string b = "c";
string c = "d";
string d = "d";
File.WriteAllText(filePath, a);
// how can add the other strings in the next cells ?
}
What I need here is to write "a" in the first cell, "b" in the second cell, c ..

CSV is a pretty simple file format, especially if you don't need any cells to contain nested commas. CSV means comma-separated values, so you just need a way to construct a string with commas between each cell. This will work, although it is only for a single line:
File.WriteAllText(filePath, String.Join(",", a, b, c, d));

CSV is absolutely NOT a SIMPLE file format, it is a sufficiently elaborate format that is able to encompass almost any kind of data regardless of shape or size.
The CSV format is capable of dealing with optional parameters vs non optional, data with or without line breaks, and should be able to work with or without field escaping characters in any field without line breaks and is required to have field escaping characters in fields with line breaks.
You should not ever work with CSV files by hand, you should utilize FileHelpers to work with CSV files.
At this point I no longer use FileHelpers as my goto CSV parsing library I use CsvHelper from Josh Close.

If there are only 4 values, and a single row? (Which I assume is not the case?)
string csv = string.Format("{0},{1},{2},{3}\n", a,b,c,d);
File.WriteAllText(filePath, csv);
If the data is based on some sort of collection, give some more info.

Related

Reading from CSV with value numbers formatted

The process that I wish to achieve it that I read from a CSV file and automatically the system creates a new CSV file in different format.
I am able to read and format the CSV file however I have issues when dealing with number formatting as the values are formatted in thousands(1,000). For example when I read from the CSV and split each line with ',' my values change.
Ex Line 1: Test Name, Test Desc, Test Currency, 12,500
var line1 = line.split(',');
This splits the value 12 & 500 because of the , delimiter. How can I get the number as a whole amount please?
using (var reader = new StreamReader(openFileDialog1.FileName))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
}
}
You cant. When a CSV file contains numbers (or any text with a , in it) it needs to quote the fields. It is impossible for simple code (i.e. not AI) to differentiate in the way your human eye can.
Ex Line 1: Test Name, Test Desc, Test Currency, 12,500
Should be:
Ex Line 1: "Test Name", "Test Desc", "Test Currency", "12,500"
Common CSV parsers/libraries will know how to handle this (e.g. CsvHelper)
If you have control over the CSV file generation, then you should make this change. If it's from a 3rd party then see if you can get them to make a change.
There may be an edge case in your example if there is always a space after fields and not in the number fields. Your delimiter then becomes ", " instead of just ','
Side note:
You should consider not to use culture-specific separators in a .csv file because it always leads to headaches when the data is exported/imported with different regional settings.
Possible solutions:
I suggest to dump and parse numbers (dates, etc.) with invariant culture:
myNumber.ToString(CultureInfo.InvariantCulture)
If you really need to dump numbers with comma decimal sign enclose the field into quotes. This does not turn the numbers strings as .csv has no type information.
Excel vs. the .csv format
Another side note for Excel: Microsoft's .csv handling is somewhat confusing and contradicts the RFC Standard. When you export a .csv in Excel the numbers are always dumped using the regional settings. To avoid the confusion with delimiters, Excel uses a different character (usually semicolon) as delimiter if the decimal separator is comma.
The used delimiter is the one is set as the list separator in the operating system's regional settings and in .NET can be retrieved via the CultureInfo.TextInfo.ListSeparator property.
I find this solution from Microsoft quite unfortunate as .csv files dumped by different regional settings cannot be always read on another computer and this only causes troubles since decades.

importing Data table to Excel text becomes numeric

Hi just want to ask I am trying to import Datatables to excel and one of the columns becomes exponent like 444201000100100 becomes 4442exp8? here's my script
protected void btnExportfromDt_Click(object sender, EventArgs e)
{
string strFilename = "FinanceforBulkupload.xls";
UploadDataTableToExcel(LoadData(), strFilename);
}
protected void UploadDataTableToExcel(DataTable dtEmp,string filename)
{
string attachment = "attachment; filename="+filename;
Response.ClearContent();
Response.AddHeader("content-disposition", attachment);
Response.ContentType = "application/vnd.ms-excel";
string tab = string.Empty;
foreach (DataColumn dtcol in dtEmp.Columns)
{
Response.Write(tab + dtcol.ColumnName);
tab = "\t";
}
Response.Write("\n");
foreach (DataRow dr in dtEmp.Rows)
{
tab = "";
for (int j = 0; j < dtEmp.Columns.Count; j++)
{
Response.Write(tab + Convert.ToString(dr[j]));
tab = "\t";
}
Response.Write("\n");
}
Response.End();
}
Pre-append a single quote to the value before you store it. Instead of:
444201000100100
store:
'444201000100100
must write the cell formatted text but the method we're using to write the cell does not allow you to add formatting, you should try another method to write the Excel file
You can also format the destination column to be of type text (or whatever Excel format you'd prefer), to prevent it from doing this as well as removing leading zeros and other interpretations of the "General" cell formating rules.
As you're creating your output document on-the-fly, you'd need to set either specific columns or the entire worksheet to have this format rule. in VBA, this command is:
Columns("A:A").NumberFormat = "#" ' This is the Text format
In C#, you should be able to do something along the lines of:
Excel.Range rng = this.Application.get_Range("A:A");
rng.NumberFormat = "#";
However this would require a reference to the Excel object, and from your existing code it looks as though you're working without that for the moment.
Gary's Student's answer will work as well, but doing so will cause those cells to ignore any formatting that is applied later when it is opened in Excel. The user would be required to remove the leading ' manually to control the format as expected.
You have different options as others proposed.
Understand that you are generating a CSV and not an Excel file so you are limited.
Since a cell format is an excel property and cannot be specified in a CSV file, I would recommend creating an excel file (.xlsx) with EPPlus and write code to specify the column format as TravelinGuy suggested. http://epplus.codeplex.com/
If you want to stick to CSV then you are limited as to how the data will be displayed in Excel. Either you accept that Excel infers a number format from what it is reading or you put a leading quote...
Unfortunately, you have to manually perform minor encoding when sending data to Excel. This is true of the automation API as well as any text-based file formats like CSV or (as in your case) tab-separated files.
A robust solution must prepend a single ' character to a string in the following cases.
The string can be parsed as a number (Excel uses VariantChangeTypeEx, but since you're using C#, Double.TryParse will do the trick)
The string already already starts with a tick ('). (For example, if you have the string 'quoted', Excel will interpret it as quoted' unless you put another single tick at the front -- ''quoted'.)
The string starts with an = character. Even in the case of CSV files, Excel inteprets this to be a worksheet function. Putting a tick at the front prevents this (e.g. '=This is not a worksheet function).
If you still find this unacceptable, please know that you have no other option when you're writing text files manually like you're doing. If you object so strongly, you can try using the Open XML SDK or some other 3rd-party tool for building Excel workbooks. However, given what looks like a very simple use case, you'll almost certainly end up with a more complex solution that is slower and requires more code. I recommend just sucking it up and writing a simple routine that abides by the rules above.

What is the best way to check a .TXT extension file for CSV format data?

I need to Export & Import TXT file fill-up with CSV format data. I need want to do it in MVC4. What is the best approach to do this ?
Txt file can contain a large number of CSV format data,
Just run it through a CSV parser (I've used this one in the past - worked fine) and check that it makes semantic sense, and has the same number of columns on each row. That would be very unlikely if it wasn't CSV data. Note: columns != commas - you need to watch out for quoted data "like, this", and line-breaks - both of which a parser will help you with. You cannot just Split by ',' or use line-endings to detect rows - CSV is more complex than that.
If all you want is to check the file extension, then using lastIndexOf or Split will pretty much do an excellent trick for you.
Using endsWith
String myFile = "some.file.txt";
System.out.println(myFile.endsWith(".txt"));
Using split
String myFile = "some.file.txt";
String[] myFileArray = myFile.split("\\.(?=[^\\.]+$)");
if (myFileArray[myFileArray.length - 1].equalsIgnoreCase("txt")) {
System.out.println("Ends with .txt");
}

creating a difference file from .csv files

I am creating an application which converts a MS Access table and an Excel sheet to .csv files and then differences the access table with the excel sheet. The .csv files are fine but the resulting difference file has errors in fields that contain html (the access table has fields with the html). I'm not sure if this is a special character issue because the special characters were not an issue in creating the .csv file in the first place, or if it is an issue with the way I am differencing the two files.
Part of the problem I suppose could be that in the access .csv file, the fields that contain the html are formatted so that some of the information is on separate lines instead of all on one line, which could be throwing off the reader, but I don't know how to correct this issue.
This is the code for creating the difference file:
string destination = Form2.destination;
string path = Path.Combine(destination, "en-US-diff.csv");
string difFile = path;
if (File.Exists(difFile))
{
File.Delete(difFile);
}
using (var wtr = new StreamWriter(difFile))
{
// Create the IEnumerable data sources
string[] access = System.IO.File.ReadAllLines(csvOutputFile);
string[] excel = System.IO.File.ReadAllLines(csvOutputFile2);
// Create the query
IEnumerable<string> differenceQuery = access.Except(excel);
// Execute the query
foreach (string s in differenceQuery)
{
wtr.WriteLine(s);
}
}
Physical line versus logical line. One solution is to use a sentinel, which is simply an arbitrary string token selected in such a way so as not to confound the parsing process, for example "##||##".
When the input files are created, add the sentinel to the end of each line...
1,1,1,1,1,1,###||##
Going back to your code, the System.IO.File.ReadAllLines(csvOutputFile); uses the Environment.Newline string as its sentinel. This means that you need to replace this statement with the following (pseudo code)...
const string sentinel = "##||##";
string myString = File.ReadAllText("myFileName.csv");
string[] access = myString.Split(new string[]{sentinel},
StringSplitOptions.RemoveEmptyEntries);
At that point you will have the CSV lines in your 'access' array the way you wanted as a collection of 'logical' lines.
To make things further conformant, you would also need to execute this statement on each line of your array...
line = line.Replace(Environment.NewLine, String.Empty).Trim();
That will remove the culprits and allow you to parse the CSV using the methods you have already developed. Of course this statement could be combined with the IO statements in a LINQ expression if desired.

String manipulation in C#: split on `/`

I need to extract headstone data from an inscription file (structured text file). From this file I am supposed to extract the name of a deceased person, date of birth (or age) and also personal messages. The application should be able to analyse a raw text file and then extract information and display it in tabular form.
The raw text files looks like this:
In loving memory of/JOHN SMITH/who died on 13.02.07/at age 40/we will
miss you/In loving memory of/JANE AUSTIN/who died on 10.06.98/born on
19.12.80/hope you are well in heaven.
Basically / is a delimiter and the name of a deceased person is always in capital letters. I have tried to use String.Split() and substring methods but I can't get it to work for me; I can only get raw data without the delimiter (Environment.Newline) but I don't know how to extract specific information.
You'll need something like:
Open your data file (System.IO)
For each line, do (tip: pick a stream where you can read line by line)
Split them by "/" getting a string[]
Arrays in C# starts at 0; so splitted[1] will be that name, ans so on
Store that information in a managed collection (maybe to use generics?)
Display that collection in a tabular view
Check out How to: Use Regular Expressions to Extract Data Fields. I know the example is in C++, but the Regex and Match classes should help you get started
Here is another good example of parsing out individual sentences.
I would have thought something like this would do the trick
private static void GetHeadStoneData()
{
using(StreamReader read = new StreamReader("YourFile.txt"))
{
const char Delimter = '/';
string data;
while((data = read.ReadLine()) != null)
{
string[] headStoneInformation = data.Split(Delimter);
//Do your stuff here, e.g. Console.WriteLine("{0}", headStoneInformation[0]);
}
}
}

Categories