How to insert single value in single cell to CSV file? - c#

I have this problem. I would like to create a csv file by using C#. So I try to development this code:
public static void creaExcel(Oggetto obj)
{
string filePath = #"C:\Temp\test.csv";
string delimiter = ",";
string[][] output = new string[][]{
new string[]{"TobRod Porosity", "Batch code", "Nu.","PAD","G.Po","L.PoD "},
new string[]{"Col1 Row 2", "Col2 Row 2", "Col3 Row 2"}
};
int length = output.GetLength(0);
StringBuilder sb = new StringBuilder();
for (int index = 0; index < length; index++)
sb.AppendLine(string.Join(delimiter, output[index]));
File.WriteAllText(filePath, sb.ToString());
// open xls file
}
This code found but I would like to insert single value in a single cell, so with this code I insert all value ([]{"TobRod Porosity", "Batch code", "Nu.","PAD","G.Po","L.PoD "}, ) in a single row, in a single cell, instead I would like to insert every value a single cell.
Can we help me?
Best reguards

The code is working fine because the result is:
TobRod Porosity,Batch code,Nu.,PAD,G.Po,L.PoD
Col1 Row 2,Col2 Row 2,Col3 Row 2
Can you confirm this?
Here is how it is displayed on my PC:
If you see all the values in a single cell on your machine, this means that there is a problem identifying the correct separator. In order to fix this, add this line: sep=, at the beginning of your CSV content, so the resulting content would be:
sep=,
TobRod Porosity,Batch code,Nu.,PAD,G.Po,L.PoD
Col1 Row 2,Col2 Row 2,Col3 Row 2
This way you can force certain devices (I know for sure that iPhones have an issue with this) to use the correct separator.
I would also suggest you to use " as a string qualifier. Example:
sep=,
"TobRod Porosity","Batch code","Nu.","PAD","G.Po","L.PoD"
"Col1 Row 2","Col2 Row 2","Col3 Row 2"

the created file is a - more or less - correct csv (comma separated values) file.
however if you open that file with excel and it puts all values in one cell, it doesn't know that you want to separate it with the comma. you can however teach it to. with excel 2013 you mark the cell and go to the tab DATA and the "text to Columns" button.
edit: however, i have the feeling that you would like to use CSV to create excel documents. thats not what CSV is made for. if you want to create real excel sheets have a look here: Create Excel (.XLS and .XLSX) file from C#

the thing is that you are selection the full array when you make the insertion
Here you accesing to the global array and getting or the first array or the second
output[index]
If you want to insert each value of the chosen array , you just have to loop again the selected array
output[index][anotherIndex]
For example
output[0][0]
Will return "TobRod Porosity" as selected value

I have fixed my error, so I have write this method
public static void creaExcel(Oggetto obj)
{
try
{
string filePath = #"TOBROD_POROSITY_" + Utility.getData() + ".csv";
string delimiter = ";";
string[][] output = new string[][]{
new string[]{"TobRod Porosity", "Batch code", "Nu.","PAD","G.Po","L.PoD "}
};
int length = output.GetLength(0);
StringBuilder sb = new StringBuilder();
for (int index = 0; index < length; index++)
sb.Append(string.Join(delimiter, output[index]));
sb.AppendLine("");
//una volta, settato l'header del file bisogna inserire i valori
if (obj != null && obj.listaMisure != null)
{
for (int i = 0; i < obj.listaMisure.Count(); i++)
{
ValoriMisure v = obj.listaMisure[i];
sb.AppendLine(obj.tobaccoPorosity
+ delimiter + obj.batchCode
+ delimiter + v.nu
+ delimiter + v.pad
+ delimiter + v.gPo
+ delimiter + v.lPod);
}
}
File.WriteAllText(filePath, sb.ToString());
//muovi il file nel percorso di destinazione
File.Move(filePath, pathFolderDestination+"\\"+filePath);
}
catch (Exception e)
{
log.Error(e);
}
}
We should see this code:
string delimiter = ";";
because if you insert this delimiter ";" you can write a value in different cell on CSV file.

Related

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

Importing a space delimited file into a DataGridView

I have the following data that I wish to import into a DataGridView:
01-29-15 04:04AM 505758360 examplefilename1.zip
01-28-15 12:28AM 501657000 this_is_another_file.zip
01-29-15 02:27AM 1629952132 random.data.for.example.zip
This data isn't delimited by and particular number of characters or by any characters. I need to import this data into a DataGridView, I have the following code:
public void LoadDataToGrid(string pProfile)
{
string[] lvTextData = File.ReadAllLines(Global.lvPath + #"\" + pProfile + ".txt");
DataTable dtTextData = new DataTable();
dtTextData.Columns.Add("Company Name", typeof(string));
dtTextData.Columns.Add("Size", typeof(string));
dtTextData.Columns.Add("File Name", typeof(string));
dtTextData.Columns.Add("Last Upload", typeof(string));
for(int i=1; i < lvTextData.Length; i++)
dtTextData.Rows.Add(lvTextData[i].Split());
grdData.DataSource = dtTextData;
}
The data comes in fine but only sits in one column, how can I change define the column widths?
There seem to be a few problems with your code (and the data you provide):
when you split the string
01-29-15 04:04AM 505758360 examplefilename1.zip
It splits it into an array of strings of Length == 16 (cause it splits all the whitespace characters). But you're providing only 4 Columns. So you want to put an array of 16 strings into 4 columns, which clearly can't be done.
A simple thing to do is: Remove redundant whitespaces of your input string Regex.Replace(s, "\\s+, " ");. (you also could Regex-parse the string and split it into groups). Then you can split your string by whitespaces and you'll get an array of strings of Length == 4
For your example (although your input data obviously is not corresponding with the names of your columns):
for (int i = 1; i < lvTextData.Length; i++)
{
// removes redundant whitespaces
string removedWhitespaces = Regex.Replace(lvTextData[i], "\\s+", " ");
// splits the string
string[] splitArray = removedWhitespaces.Split(' ');
// [0]: 01-29-15
// [1]: 04:04AM
// [2]: 505758360
// [3]: examplefilename1.zip
// do some kind of length checking here
if(splitArray.Length == dtTextData.Columns.Count)
{
dtTextData.Rows.Add(splitArray);
}
}
You can even look for CSV Reader - if you are using NuGet look here
It handles also trailing / ending white spaces automatically. Keep in mind that you have to specify '\t' or ' ' as delimiting character.
void ReadAndBindCsv()
{
// open the file "data.csv" which is a CSV file with headers
using (CsvReader csv = new CsvReader(
new StreamReader("data.csv"), true))
{
csv.TrimSpaces = true;
grdData.DataSource = csv;
}
}

Rich Text to Plain Text via C#?

I have a program that reads through a Microsoft Word 2010 document and puts all text read from the first column of every table into a datatable. However, the resulting text also includes special formatting characters (that are usually invisible in the original Word document).
Is there a way that I can take the string of text that I've read and strip all the formatting characters from it?
The program is pretty simple, and uses the Microsoft.Office.Interop.Word assemblies. Here is the main loop where I'm grabbing the text from the document:
// Loop through each table in the document,
// grab only text from cells in the first column
// in each table.
foreach (Table tb in docs.Tables)
{
for (int row = 1; row <= tb.Rows.Count; row++)
{
var cell = tb.Cell(row, 1);
var listNumber = cell.Range.ListFormat.ListString;
var text = listNumber + " " + cell.Range.Text;
dt.Rows.Add(text);
}
}
EDIT: Here is what the text ("1. Introduction") looks like in the Word document:
This is what it looks like before being put into my datatable:
And this is what it looks like when put into the datatable:
So, I'm trying to figure out a simple way to get rid of the control characters that seem to be appearing (\r, \a, \n, etc).
EDIT: Here is the code I'm trying to use. I created a new method to convert the string:
private string ConvertToText(string rtf)
{
using (RichTextBox rtb = new RichTextBox())
{
rtb.Rtf = rtf;
return rtb.Text;
}
}
When I run the program, it bombs with the following error:
The variable rtf, at this point, looks like this:
RESOLUTION: I trimmed the unneeded characters before writing them to the datatable.
// Loop through each table in the document,
// grab only text from cells in the first column
// in each table.
foreach (Table tb in docs.Tables)
{
for (int row = 1; row <= tb.Rows.Count; row++)
{
var charsToTrim = new[] { '\r', '\a', ' ' };
var cell = tb.Cell(row, 1);
var listNumber = cell.Range.ListFormat.ListString;
var text = listNumber + " " + cell.Range.Text;
text = text.TrimEnd(charsToTrim);
dt.Rows.Add(text);
}
}
I don't know exactly what formatting you're trying to remove, but you could try something like:
text = text.Where(c => !Char.IsControl(c)).ToString();
That should strip the non-printing characters out.
Al alternative can be that You need to add a rich textbox in your form (you can keep it hidden if you don't want to show it) and when you have read all your data just assign it to the richtextbox. Like
//rtfText is rich text
//rtBox is rich text box
rtBox.Rtf = rtfText;
//get simple text here.
string plainText = rtBox.Text;
Why dont you give this a try:
using System;
using System.Text.RegularExpressions;
public class Example
{
static string CleanInput(string strIn)
{
// Replace invalid characters with empty strings.
try {
return Regex.Replace(strIn, #"[^\w\.#-]", "",
RegexOptions.None, TimeSpan.FromSeconds(1.5));
}
// If we timeout when replacing invalid characters,
// we should return Empty.
catch (RegexMatchTimeoutException) {
return String.Empty;
}
}
}
Here's a link for it as well.
http://msdn.microsoft.com/en-us/library/844skk0h.aspx
Totally different approach would be to look at the Open Office XML SDK.
This example should get you started.

Numeric fields lose leading zero while writing CSV in c#

I'm using an ASP.NET application which exports my clients data to CSV, I need my clients Phone number to be with the leading Zero.
I need the phone numbers to be without "-" and without quotations, and due to the nature of my application I cannot use 3rd party products such as EPPLUS.
I've tried to put a space and let the CSV "understand" that I need the phone number as text , but that doesn't seem right.
I would like to know how to make the excel include the leading zero , without using 3rd party products.
Thanks
Change the data that is saved in the csv with the following format:
="00023423"
CSV example:
David,Sooo,="00023423",World
This will show 00023423 in excel and not 23423.
public void CreatingCsvFiles(Client client)
{
string filePath = "Your path of the location" + "filename.csv";
if (!File.Exists(filePath))
{
File.Create(filePath).Close();
}
string delimiter = ",";
string[][] output = new string[][]{
new string[]{ "=\"" + client.phone + "\"", client.name }
};
int length = output.GetLength(0);
StringBuilder sb = new StringBuilder();
for (int index = 0; index < length; index++)
sb.AppendLine(string.Join(delimiter, output[index]));
File.AppendAllText(filePath, sb.ToString());
}
Inspired from http://softwaretipz.com/c-sharp-code-to-create-a-csv-file-and-write-data-into-it/
The important part :
"=\"" + client.phone + "\"", client.name
If the phone number is an int, of course you add .toString().
Print phone number to CSV with prepended ' (single quote), so it looks like:
"Some Name","'0000121212"
Excel should treat this 0000121212 as string then.
I believe converting the number into a formula like the accepted answer might not be a helpful solution for all.
The alternate solution I went with is to just add a tab space before the integer value.
Example:
Taking phoneNumber as a string variable which contains our int value
Solution:
"\t" + phoneNumber
If you know already how much numbers has to be inside phone you can do like this
phoneNumber.ToString("000000000000")
In this example I consider that phoneNumber is an int and required length of numbers is 12.

C# writing out text files matching listbox and contents of another text file

I have a file created from a directory listing. From each of item a user selects from a ListBox, the application reads the directory and writes out a file that matches all the contents. Once that is done it goes through each item in the ListBox and copies out the item that matches the ListBox selection. Example:
Selecting 0001 matches:
0001456.txt
0001548.pdf.
The code i am using isn't handling 0s very well and is giving bad results.
var listItems = listBox1.Items.OfType<string>().ToArray();
var writers = new StreamWriter[listItems.Length];
for (int i = 0; i < listItems.Length; i++)
{
writers[i] = File.CreateText(
Path.Combine(destinationfolder, listItems[i] + "ANN.TXT"));
}
var reader = new StreamReader(File.OpenRead(masterdin + "\\" + "MasterANN.txt"));
string line;
while ((line = reader.ReadLine()) != null)
{
for (int i = 0; i < listItems.Length; i++)
{
if (line.StartsWith(listItems[i].Substring(0, listItems[i].Length - 1)))
writers[i].WriteLine(line);
}
}
Advice for correcting this?
Another Sample:
I have 00001 in my listbox: it returns these values:
00008771~63.txt
00002005~3.txt
00009992~1.txt
00001697~1.txt
00000001~1.txt
00009306~2.txt
00000577~1.txt
00001641~1.txt
00001647~1.txt
00001675~1.txt
00001670~1.txt
It should only return:
00001641~1.txt
00001647~1.txt
00001675~1.txt
00001670~1.txt
00001697~1.txt
Or if someone could just suggest a better method for taking each line in my listbox searching for line + "*" and whatever matches writes out a textfile...
This is all based pretty much on the one example you gave, but I believe the problem is that when you are performing your matching, you are getting the substring if your list item value and chopping off the last character.
In your sample you are attempting to match files starting with "00001", but when you do the match you are getting substring starting at zero and value.length-1 characters, which in this case would be "0000". For example:
string s = "00001";
Console.WriteLine(s.Substring(0,s.Length-1));
results in
0000
So I think if you just changed this line:
if (line.StartsWith(listItems[i].Substring(0, listItems[i].Length - 1)))
writers[i].WriteLine(line);
to this
if (line.StartsWith(listItems[i]))
writers[i].WriteLine(line);
you would be in good shape.
Sorry if I misunderstood your question, but let's start with this:
string line = String.Empty;
string selectedValue = "00001";
List<string> matched = new List<string>();
StreamReader reader = new StreamReader(Path.Combine(masterdin, "MasterANN.txt"));
while((line = reader.ReadLine()) != null)
{
if(line.StartsWith(selectedValue))
{
matched.Add(line);
}
}
This will match all lines from your MasterANN.txt file which begins with "00001" and add them into a collection (later we'll work on writing this into a file, if required).
This clarifies something?

Categories

Resources