CSV Line Breaks - c#

I'm building a csv file from database values. When I open the csv in excel everything is on one row. To counter this I've added either \n or \r after each row. Now when I open in excel starting at the second row there is an empty value throughout the rest of the first column.
IE:
value 1, value 2, value 3
, value 1, value 2, value 3
, value 1, value 2, value 3
, value 1, value 2, value 3
I can add a newline or return before the first value, but then there is an empty row and column. How can I get this lined up?
My code:
try
{
connection = new iDB2Connection(connectionString);
connection.Open();
command = new iDB2Command(commandString, connection);
reader = command.ExecuteReader();
var dt = new DataTable();
dt.Load(reader);
List<string> CsvList = new List<string>();
foreach (DataRow row in dt.Rows)
{
foreach (var item in row.ItemArray)
{
CsvList.Add(item.ToString());
}
if (i == 1)
{
CsvList.Add(" ");
CsvList.Add("Customer Service");
CsvList.Add("Customer Service Representative" + "\r");
// \r and \n not working
}
}
System.IO.StreamWriter streamWriter;
streamWriter = new System.IO.StreamWriter(fileName, true);
string CsvString = string.Join(",", CsvList.ToArray());
streamWriter.WriteLine(CsvString);
streamWriter.Close();
Console.WriteLine("File saved as " + fileName);
i++;
}

It'll be a heck of a lot easier if you just build up a list of lines, rather than a flattened list of single values. Since you've flattened your list already when you use Join you're putting commas after newlines values, for example.
Instead join together the values for each line, and then just keep track of the entire lines:
foreach (DataRow row in dt.Rows)
{
CsvList.Add(string.Join(",", row.ItemArray));
}
Now that you have a list of lines, we can just use File.AppendAllLines to simply and easily write out all of the lines to the end of the file:
File.AppendAllLines(fileName, CsvList);
Or, if you would like to stream the results to the file rather than copying all of the data over to a list and holding it all in memory at once, you can do this:
var lines = dt.AsEnumerable()
.Select(row => string.Join(",", row.ItemArray));
File.AppendAllLines(fileName, lines);

Instead of creating an array and handling adding new-lines yourself, use a StringBuilder, and commit each row one at a time:
var sb = new StringBuilder();
foreach (DataRow row in dt.Rows)
{
List<string> csvList = new List<string>();
foreach (var item in row.ItemArray)
{
csvList.Add(item.ToString());
}
if (i == 1)
{
csvList.Add(" ");
csvList.Add("Customer Service");
csvList.Add("Customer Service Representative");
}
sb.WriteLine(string.Join(",", csvList));
}
System.IO.StreamWriter streamWriter;
streamWriter = new System.IO.StreamWriter(fileName, true);
streamWriter.WriteLine(sb.ToString());
streamWriter.Close();
Console.WriteLine("File saved as " + fileName);

Related

Remove last (empty) entry from StringBuilder object, when exporting to CSV

I want to remove the last (empty) row of a StringBuilder Object
EDIT: The empty row is from the "AllowUserToAddRows" how can i skip it?
c# Forms application
dataGridView1 on form2
I want Export to CSV (separated by semicolon) [btw. it's just one column]
It Could happen, that a previously created CSV is parsed to the dataGridView again
I use a altered solution from here:
Exporting datagridview to csv file
my code
void SaveDataGridViewToCSV(string filename)
{
var sb = new StringBuilder();
var headers = dataGridView1.Columns.Cast<DataGridViewColumn>();
sb.AppendLine(string.Join(";", headers.Select(column => "" + column.HeaderText + ";").ToArray()));
foreach (DataGridViewRow row in dataGridView1.Rows)
{
var cells = row.Cells.Cast<DataGridViewCell>();
sb.AppendLine(string.Join(";", cells.Select(cell => "" + cell.Value + ";").ToArray()));
}
try
{
File.WriteAllText(filename, sb.ToString());
}
catch (Exception exceptionObject)
{
MessageBox.Show(exceptionObject.ToString());
}
}
The sb.ToString looks like this {Coumn;90;90;626;626;;}
The "real" StringBuilder Object as String is: {Coumn;\r\n90;\r\n90;\r\n626;\r\n626;\r\n;}
I want to remove the empty last row.
I tried to parse the stringbuilder to a string, and then remove last semicolon
but with no success (i have problem with the End Of Line.)
string s = sb.ToString();
while (s.EndsWith(";\r\n;") == true)
{
s.Substring(0, s.Length - 5);
}
I tried to remove last element of array, but StingBuilder is no array
I'm stuck.
As i found out the empty set is always exported to the csv.
It's from the ability that the user can input data to the dataGridView, and there is always a empty, active row.
if i disable dataGridView1.AllowUserToAddRows the empty row for userinput is not within the stringbuilder set of data.
void SaveDataGridViewToCSV(string filename)
{
var sb = new StringBuilder();
//SOLUTION disable AllowUserInput to avoid empty set saved to CSV
dataGridView1.AllowUserToAddRows = false;
var headers = dataGridView1.Columns.Cast<DataGridViewColumn>();
sb.AppendLine(string.Join(";", headers.Select(column => "" + column.HeaderText + ";").ToArray()));
foreach (DataGridViewRow row in dataGridView1.Rows)
{
var cells = row.Cells.Cast<DataGridViewCell>();
sb.AppendLine(string.Join(";", cells.Select(cell => "" + cell.Value + ";").ToArray()));
}
try
{
File.WriteAllText(filename, sb.ToString());
}
catch (Exception exceptionObject)
{
MessageBox.Show(exceptionObject.ToString());
}
}
thanks for help!

Encoding Issue in C#

I am getting data from a Stored Procedure and creating a text file, below is my code for converting a datatable to a text file by calling this method.
StreamWriter str = new StreamWriter(filename, false, Encoding.Default);
if (writeWithColumns)
{
string Columns = string.Empty;
foreach (DataColumn column in datatable.Columns)
{
Columns += column.ColumnName.Trim() + delimiter;
}
str.WriteLine(Columns.Remove(Columns.Length - 1, 1));
foreach (DataRow datarow in datatable.Rows)
{
string row = string.Empty;
foreach (object items in datarow.ItemArray)
{
row += items.ToString().Trim() + delimiter;
}
str.WriteLine(row.Remove(row.Length - 1, 1));
}
str.Flush();
str.Close();
}
The problem that I am facing is that when converting some files I am getting correct ANSI format, with an Û delimiter:
but some files are changing the delimiter to л:
I don't understand why some files are having correct encoding while some are having incorrect one.

Import Part of CSV to datagridview

What I have is a CSV that I have imported into a Datagridview.
I am now looking for a way to only import the column with the header # and Delay and not all info in the CSV, so any help on this would be appreciated.
Here is the Code I have thus far:
private void button1_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK) // Test result.
{
String Fname = openFileDialog1.FileName;
//String Sname = "export";
string[] raw_text = System.IO.File.ReadAllLines(Fname);
string[] data_col = null;
int x = 0;
foreach (string text_line in raw_text)
{
data_col = text_line.Split(';');
if (x == 0)
{
for (int i = 0; i < data_col.Count(); i++)
{
dt.Columns.Add(data_col[i]);
}
x++;
}
else
{
dt.Rows.Add(data_col);
}
}
dataGridView1.DataSource = dt;
}
}
When I read from CSV files, I create a list of values that I want for each row and use that list as the basis for my INSERT statement to the database.
I know where to find the data I want in the CSV file so I specifically target those items while I'm building my list of parameters for the query.
See the code below:
// Read the file content from the function parameter.
string content = System.Text.Encoding.ASCII.GetString(bytes);
// Split the content into an array where each array item is a line for
// each row of data.
// The Replace simply removes the CarriageReturn LineFeed characters from
// the source text and replaces them with a Pipe character (`|`)
// and then does the split from that character.
// This is just personal preference to do it this way
string[] data = content.Replace("\r\n", "|").Split('|');
// Loop through each row and extract the data you want.
// Note that each value is in a fixed position in the row.
foreach (string row in data)
{
if (!String.IsNullOrEmpty(row))
{
string[] cols = row.Split(';');
List<MySqlParameter> args = new List<MySqlParameter>();
args.Add(new MySqlParameter("#sid", Session["storeid"]));
args.Add(new MySqlParameter("#name", cols[0]));
args.Add(new MySqlParameter("#con", cols[3]));
try
{
// Insert the data to the database.
}
catch (Exception ex)
{
// Report an error.
}
}
}
In the same way, you could build your list/dataset/whatever as a data source for your datagridview. I would build a table.
Here's a mockup (I haven't got time to test it right now but it should get you on the right track).
DataTable table = new DataTable();
table.Columns.Add("#");
table.Columns.Add("Delay");
foreach (var line in raw_text)
{
DataRow row = table.NewRow();
row[0] = line[0]; // The # value you want.
row[1] = line[1]; // The Delay value you want.
table.Rows.Add(row);
}
DataGridView1.DataSource = table;
DataGridView1.DataBind();
Using TextFieldParser can make handling CVS input less brittle:
// add this using statement for TextFieldParser - needs reference to Microsoft.VisualBasic assembly
using Microsoft.VisualBasic.FileIO;
...
// TextFieldParser implements IDisposable so you can let a using block take care of opening and closing
using (TextFieldParser parser = new TextFieldParser(Fname))
{
// configure your parser to your needs
parser.TextFieldType = FieldType.Delimited;
parser.Delimiters = new string[] { ";" };
parser.HasFieldsEnclosedInQuotes = false; // no messy code if your data comes with quotes: ...;"text value";"another";...
// read the first line with your headers
string[] fields = parser.ReadFields();
// add the desired headers with the desired data type
dt.Columns.Add(fields[2], typeof(string));
dt.Columns.Add(fields[4], typeof(string));
// read the rest of the lines from your file
while (!parser.EndOfData)
{
// all fields from one line
string[] line = parser.ReadFields();
// create a new row <-- this is missing in your code
DataRow row = dt.NewRow();
// put data values; cast if needed - this example uses string type columns
row[0] = line[2];
row[1] = line[4];
// add the newly created and filled row
dt.Rows.Add(row);
}
}
// asign to DGV
this.dataGridView1.DataSource = dt;

Edit and/or Delete a row on CSV file

I have a CSV file. I need to write a code that we can get a row from CSV by username. And I need to either update or delete that row from the CSV file. I was managed to get the row data by username. But I haven't got any idea how to write the code for Update or delete function. My code to get single row as follows
StreamReader reader = new StreamReader(System.IO.File.OpenRead(#"C:\Test\test.CSV"));
UserDetailsViewModel objInput = new UserDetailsViewModel();
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
if (!String.IsNullOrWhiteSpace(line))
{
string[] values = line.Split(',');
if (values[0] == "Bharat")
{
objInput.FirstName = values[0];
objInput.LastName = values[1];
objInput.Address1 = values[2];
objInput.Address2 = values[3];
objInput.City = values[4];
objInput.State = values[5];
objInput.ZipCode = values[6];
break;
}
}
}
reader.Dispose();
return View(objInput);
Please someone help me to write a code for Update and delete on CSV file.
Thanks in Advance.
You can achieve your desired result, using below approach.
-> First you have to read your .csv file.
-> Then iterate through every line of file, meanwhile you can choose any row for edit/delete then make change to that row and store that row into string list.
-> At last you have to write string list to file. that's all.
For Example:
List<String> lines = new List<String>();
using (StreamReader reader = new StreamReader(System.IO.File.OpenRead(#"C:\Test\test.CSV"));)
{
String line;
while ((line = reader.ReadLine()) != null)
{
if (line.Contains(","))
{
String[] split = line.Split(',');
if (//condition for Edit record like : split[1] == "abc" etc.)
{
// update that
split[1] = "xyz";
line = String.Join(",", split);
lines.Add(line);
}
if (//condition for Delete row.)
{
// don't add that row into string list
}
}
}
}
using (StreamWriter writer = new StreamWriter(#"C:\Test\test.CSV", false))
{
foreach (String line in lines)
writer.WriteLine(line);
}
Reading and wirting csv is typically trickier than it seems to be at first glance.
Use a library like KBCsv (https://github.com/kentcb/KBCsv) for that task

How to comma-separate a set of strings without the final comma

int rowPosition = 0;
string WorkerName = "";
DataTable dtAllotedManpower = new DataTable();
dtAllotedManpower.Columns.Add("WorkerName");
foreach (GridViewRow row in GridViewTotalManpower.Rows)
{
if (row.RowType == DataControlRowType.DataRow)
{
DataRow drAllotedManpower = dtAllotedManpower.NewRow();
CheckBox chkChild = (CheckBox)GridViewTotalManpower.Rows[rowPosition].FindControl("chkChild");
if (chkChild.Checked == true)
{
WorkerName = Convert.ToString(GridViewTotalManpower.DataKeys[rowPosition]["WorkerName"].ToString()) + "," + WorkerName;
}
rowPosition++;
}
hidfWorker.Value = WorkerName;
I have Written the following piece of code. My hidden field values are coming like this
"HARSH,RIMA,"
But i want the value "HARSH,RIMA" (without ',' after the last word). how to construct the code for that ? . there will be no 'comma' after last word .
Add them to a collection then use string.Join:
var list = new List<string>();
foreach (GridViewRow row in GridViewTotalManpower.Rows) {
// ...other code here...
list.Add(Convert.ToString(GridViewTotalManpower.DataKeys[rowPosition]["WorkerName"].ToString()));
}
hidfWorker.Value = string.Join(", ", list);
You can use string.TrimEnd()
hidfWorker.Value = WorkerName.TrimEnd(',');
This will remove the last comma from the string.
you can use the substring method
hidfWorker.Value=WorkerName.Substring(0,WorkerName.Length-1);
Use StringBuilder instead of string if you are frequently changing the string like in loops, because when you use string it will create new string object every time you changes it,
StringBuilder workerName = new StringBuilder();
And in your loop
workerName.Append(Convert.ToString(GridViewTotalManpower.DataKeys[rowPosition]["WorkerName"].ToString()) + ",");
Then trim last ',' character using TrimEnd method
hidfWorker.Value = workerName.ToString().TrimEnd(',');
Hope this helps.

Categories

Resources