I am writing csv file from Datatable. Check my code below
public static void SaveDataTableToCsvFile(string AbsolutePathAndFileName, DataTable TheDataTable, params string[] Options)
{
//variables
string separator;
if (Options.Length > 0)
{
separator = Options[0];
}
else
{
separator = ""; //default
}
string quote = "";
FileInfo info = new FileInfo(AbsolutePathAndFileName);
if (IsFileLocked(info))
{
MessageBox.Show("File is in use, please close the file");
return;
}
//create CSV file
StreamWriter sw = new StreamWriter(AbsolutePathAndFileName);
//write header line
int iColCount = TheDataTable.Columns.Count;
for (int i = 0; i < iColCount; i++)
{
sw.Write(TheDataTable.Columns[i]);
if (i < iColCount - 1)
{
sw.Write(separator);
}
}
sw.Write(sw.NewLine);
//write rows
foreach (DataRow dr in TheDataTable.Rows)
{
for (int i = 0; i < iColCount; i++)
{
if (!Convert.IsDBNull(dr[i]))
{
string data = dr[i].ToString();
data = data.Replace("\"", "\\\"").Replace(",", " ");
sw.Write(quote + data + quote);
}
if (i < iColCount - 1)
{
sw.Write(separator);
}
}
sw.Write(sw.NewLine);
}
sw.Close();
}
Code works for me ,but I need to add color code in some cells of csv.
How can I do that ?
CSV is a pure data format without any formatting. It's a plain text file after all. So no, there is no way of adding colour.
You might want to output an .xls (or equivalent) instead of a .csv using some external utility Or convert the csv to .xls in order to have color coding even possible
Joey is absolutely right.
But if your situation allows you to output an XLSX instead of a CSV, then EPPlus might be the solution for you.
e.g.
using (ExcelPackage ep = new ExcelPackage(AbsolutePathAndFileName))
{
ExcelWorksheet worksheet = ep.Workbook.Worksheets.Add("Worksheet1");
worksheet.Cells["A1"].LoadFromDataTable(TheDataTable, true);
worksheet.Cells["F4"].BackgroundColor.SetColor(Color.Red);
ep.Save();
}
A CSV (comma-separated values) file is a text file. There is no way to add color too the file without changing it to another file format (such as RTF).
Related
Im trying to process a set of files, i have a given number of txt files, which im currently joining into 1 txt file to apply filters to. The creation of the 1 file from multiple works great. But i have 2 questions and 1 error i cant seem to get around.
1 - Im getting an error when i try to read the newly created file so i can apply the filters. "The process cannot access the file because it is being used by another process."
2 - Am i approaching this the correct or more efficient way? by that i mean can the reading and filtering be applied before creating the concatenated file? I mean i still need to create a new file, but it would be nice to be able to apply everything before creating so that the file is already cleaned and ready for use outside the application.
Here is the current code that is having the issue and the 1 commented line that was my other attempt at releasing the file
private DataTable processFileData(string fname, string locs2 = "0", string effDate = "0", string items = "0")
{
DataTable dt = new DataTable();
string fullPath = fname;
try
{
using (StreamReader sr = new StreamReader(File.OpenRead(fullPath)))
//using (StreamReader sr = new StreamReader(File.Open(fullPath,FileMode.Open,FileAccess.Read, FileShare.Read)))
{
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
if (!String.IsNullOrWhiteSpace(line))
{
string[] headers = line.ToUpper().Split('|');
while (dt.Columns.Count < headers.Length)
{
dt.Columns.Add();
}
string[] rows = line.ToUpper().Split('|');
DataRow dr = dt.NewRow();
for (int i = 0; i < rows.Count(); i++)
{
dr[i] = rows[i];
}
dt.Rows.Add(dr);
}
}
//sr.Close();
sr.Dispose();
}
string cls = String.Format("Column6 NOT LIKE ('{0}')", String.Join("','", returnClass()));
dt.DefaultView.RowFilter = cls;
return dt;
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
return dt;
}
Here is the concatenation method:
private void Consolidate(string fileType)
{
string sourceFolder = #"H:\Merchant\Strategy\Signs\BACKUP TAG DATA\Wave 6\" + sfld;
string destinationFile = #"H:\Merchant\Strategy\Signs\BACKUP TAG DATA\Wave 6\" + sfld + #"\"+ sfld + #"_consolidation.txt";
// Specify wildcard search to match TXT files that will be combined
string[] filePaths = Directory.GetFiles(sourceFolder, fileType);
StreamWriter fileDest = new StreamWriter(destinationFile, true);
int i;
for (i = 0; i < filePaths.Length; i++)
{
string file = filePaths[i];
string[] lines = File.ReadAllLines(file);
if (i > 0)
{
lines = lines.Skip(1).ToArray(); // Skip header row for all but first file
}
foreach (string line in lines)
{
fileDest.WriteLine(line);
}
}
if (sfld == "CLR")
{
clrFilter(destinationFile);
}
if (sfld == "UPL")
{
uplFilter(destinationFile);
}
if (sfld == "HD")
{
hdFilter(destinationFile);
}
if (sfld == "PD")
{
pdFilter(destinationFile);
}
fileDest.Close();
fileDest.Dispose();
}
What im trying to accomplish is reading min(2 or 3 txt files and as much as 13 txt files) and applying some filtering. But im getting this error:
"The process cannot access the file because it is being used by another process."
You're disposing the stream reader with the following line
sr.Dispose();
Using a 'Using' statement will dispose after the stream goes out of context. So remove the Dispose line (if it wasn't clear below)
I have used ext.net 1.6 tool. I tried to convert data datatable to csv but i am getting error status code : 200 and status text : Bad Request.
And I also exported data from ext.net gridpanel to csv but now i want to export directly datatable to csv.
I passed Jason string for datatable same as passed for gridpanel but gridpanel data is exported perfectly, but datatable does not export with same method
can you suggest me?
what is exact problem with that?
Thanks
Use the below
Method to convert the Datatable data to export into CSV in c#:
void ToCSVDownload(DataTable dtDataTable)
{
var stream = new MemoryStream();
StreamWriter sw = new StreamWriter(stream);
//Writing Headers
for (int i = 0; i < dtDataTable.Columns.Count; i++)
{
sw.Write(dtDataTable.Columns[i]);
if (i < dtDataTable.Columns.Count - 1)
{
sw.Write(",");
}
}
sw.Write(sw.NewLine);
//Writing Data
foreach (DataRow dr in dtDataTable.Rows)
{
for (int i = 0; i < dtDataTable.Columns.Count; i++)
{
if (!Convert.IsDBNull(dr[i]))
{
string value = dr[i].ToString();
if (value.Contains(','))
{
value = String.Format("\"{0}\"", value);
sw.Write(value);
}
else
{
sw.Write(dr[i].ToString());
}
}
if (i < dtDataTable.Columns.Count - 1)
{
sw.Write(",");
}
}
sw.Write(sw.NewLine);
}
sw.Close();
//converting it to the Bytes
byte[] byteArray = stream.ToArray();
//Dowloading the file by writing Bytes
Response.AddHeader("Content-Disposition", "attachment; Filename = test.csv");
Response.ContentType = "application/octet-stream";
Response.BinaryWrite(byteArray);
Response.End();
}
I have a project which should include a download function whereby when the user press the download button, the contents of the SQL Server table will be downloaded as a csv file.
Is there any way I can do this?
The contents of the table called Characters will be downloaded as a csv file. What I know is that I have use the query Select* from Characters, but I do not know how to implement it.
protected void btnDownload_Click(object sender, EventArgs e)
{
string fileName = string.Empty;
string filepath = Request.MapPath("~/Uploads");// this needs to be changed with the SQL query, but I do not know how to implement it
string downloadFileName = "Attendance.zip";
Response.ContentType = "application/zip";
Response.AddHeader("content-disposition", "filename=" + downloadFileName);
using (ZipFile zip = new ZipFile())
{
foreach (GridView row in gvFiles.Rows)
{
CheckBox cb = (CheckBox)row.FindControl("chkSelect");
if (cb != null && cb.Checked)
{
fileName = (row.FindControl("lblFileName") as Label).Text;
zip.AddFile(Server.MapPath(Path.Combine(filepath, fileName)), "");
}
}
zip.Save(Response.OutputStream);
}
I'm not sure how the code you posted relates to the problem, but here's how you can take the contents of a table and turn it into a CSV file. The sample assumes you have an already filled DataTable (dtTable):
StringBuilder sb = new StringBuilder();
for (int i = 0; i < dtTable.Columns.Count; i++)
{
sb.Append(dtTable.Columns[i].ColumnName);
sb.Append(",");
}
// Remove the trailing ,
sb.Remove(sb.Length - 1, 1);
sb.Append(Environment.NewLine);
for (int i = 0; i < dtTable.Rows.Count; i++)
{
for (int j = 0; i < dtTable.Columns.Count; j++)
{
sb.Append(dtTable.Rows[i][j].ToString());
sb.Append(",");
}
sb.Remove(sb.Length - 1, 1);
sb.Append(Environment.NewLine);
}
string csvFileString = sb.ToString();
For performance and economy of resource use, I would use a SQL Command and a forward-only SqlDataReader to get the data.
These articles might help you understand what's required.:
http://www.developerfusion.com/article/4278/using-adonet-with-sql-server/2/
http://wiki.asp.net/page.aspx/401/export-to-csv-file/
You havn't told much about your environment. For example:
Which data access technology do you use ?
Do you have to escape the fields in your csv file?
For dealing with csv files i recommend using the filehelpers library.
If you are free in choosing data access, maybe you should take a look at LINQ2SQL or ADO EF or just use plain SqlCommand/SqlDataReader.
I have the below code to generate a CSV file from DataGridView and working fine. But it is not preserving the exact formats. For example, I have 125600.00 in one cell and 08 in another cell in the DataGridView. When I opened the CSV file using Excel, it is showing them as 125600 and 8. And when I opened the CSV file using a notepad, it shows them correct 125600.00 and 08. Is there something that I can do to see the same formats in the excel?
Thanks for any suggestions.
private void btnPrint_Click(object sender, EventArgs e)
{
sbMainFile = new StringBuilder();
int dgcolcount = this.dataGridView1.Columns.Count;
for (int i = 0; i < dgcolcount; i++)
{
sbMainFile.Append(this.dataGridView1.Columns[i].Name);
if (i < dgcolcount - 1)
{
sbMainFile.Append(",");
}
}
sbMainFile.Append("\r\n");
StringBuilder sbRow = null;
foreach (DataGridViewRow row in this.dataGridView1.Rows)
{
sbRow = new StringBuilder();
for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
sbRow.Append(row.Cells[i].Value.ToString());
if (i < dgcolcount - 1)
{
sbRow.Append(",");
}
}
sbMainFile.AppendLine(sbRow.ToString());
}
SaveFileDialog savefile = new SaveFileDialog();
savefile.FileName = "default";
savefile.Filter = "CSV Files | *.csv";
savefile.DefaultExt = "csv";
if (savefile.ShowDialog() == DialogResult.OK)
{
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(savefile.FileName))
sw.Write(sbMainFile.ToString());
}
}
You could save the "column values" as a string; e.g. 08 as ="08"
change
sbRow.Append(row.Cells[i].Value.ToString());
to
sbRow.AppendFormat("=\"{0}\"", row.Cells[i].Value.ToString());
There is nothing wrong with your code. That is actually a problem with Excel formatting your data for you. You don't actually lose any data. You simply have to specify the format in Excel. (If you click on one of your cells where the format is mangled you can actually see the "raw" value in the f(x) editor.)
I need to read from a CSV/Tab delimited file and write to such a file as well from .net.
The difficulty is that I don't know the structure of each file and need to write the cvs/tab file to a datatable, which the FileHelpers library doesn't seem to support.
I've already written it for Excel using OLEDB, but can't really see a way to write a tab file for this, so will go back to a library.
Can anyone help with suggestions?
.NET comes with a CSV/tab delminited file parser called the TextFieldParser class.
http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser.aspx
It supports the full RFC for CSV files and really good error reporting.
I used this CsvReader, it is really great and well configurable. It behaves well with all kinds of escaping for strings and separators. The escaping in other quick and dirty implementations were poor, but this lib is really great at reading. With a few additional codelines you can also add a cache if you need to.
Writing is not supported but it rather trivial to implement yourself. Or inspire yourself from this code.
Simple example with CsvHelper
using (TextWriter writer = new StreamWriter(filePath)
{
var csvWriter = new CsvWriter(writer);
csvWriter.Configuration.Delimiter = "\t";
csvWriter.Configuration.Encoding = Encoding.UTF8;
csvWriter.WriteRecords(exportRecords);
}
Here are a couple CSV reader implementations:
http://www.codeproject.com/KB/database/CsvReader.aspx
http://www.heikniemi.fi/jhlib/ (just one part of the library; includes a CSV writer too)
I doubt there is a standard way to convert CSV to DataTable or database 'automatically', you'll have to write code to do that. How to do that is a separate question.
You'll create your datatable in code, and (presuming a header row) can create columns based on your first line in the file. After that, it will simply be a matter of reading the file and creating new rows based on the data therein.
You could use something like this:
DataTable Tbl = new DataTable();
using(StreamReader sr = new StreamReader(path))
{
int count = 0;
string headerRow = sr.Read();
string[] headers = headerRow.split("\t") //Or ","
foreach(string h in headers)
{
DataColumn dc = new DataColumn(h);
Tbl.Columns.Add(dc);
count++;
}
while(sr.Peek())
{
string data = sr.Read();
string[] cells = data.Split("\t")
DataRow row = new DataRow();
foreach(string c in cells)
{
row.Columns.Add(c);
}
Tbl.Rows.Add(row);
}
}
The above code has not been compiled, so it may have some errors, but it should get you on the right track.
You can read and write csv file..
This may be helpful for you.
pass split char to this parameter "serparationChar"
Example : -
private DataTable dataTable = null;
private bool IsHeader = true;
private string headerLine = string.Empty;
private List<string> AllLines = new List<string>();
private StringBuilder sb = new StringBuilder();
private char seprateChar = ',';
public DataTable ReadCSV(string path, bool IsReadHeader, char serparationChar)
{
seprateChar = serparationChar;
IsHeader = IsReadHeader;
using (StreamReader sr = new StreamReader(path,Encoding.Default))
{
while (!sr.EndOfStream)
{
AllLines.Add( sr.ReadLine());
}
createTemplate(AllLines);
}
return dataTable;
}
public void WriteCSV(string path,DataTable dtable,char serparationChar)
{
AllLines = new List<string>();
seprateChar = serparationChar;
List<string> StableHeadrs = new List<string>();
int colCount = 0;
using (StreamWriter sw = new StreamWriter(path))
{
foreach (DataColumn col in dtable.Columns)
{
sb.Append(col.ColumnName);
if(dataTable.Columns.Count-1 > colCount)
sb.Append(seprateChar);
colCount++;
}
AllLines.Add(sb.ToString());
for (int i = 0; i < dtable.Rows.Count; i++)
{
sb.Clear();
for (int j = 0; j < dtable.Columns.Count; j++)
{
sb.Append(Convert.ToString(dtable.Rows[i][j]));
if (dataTable.Columns.Count - 1 > j)
sb.Append(seprateChar);
}
AllLines.Add(sb.ToString());
}
foreach (string dataline in AllLines)
{
sw.WriteLine(dataline);
}
}
}
private DataTable createTemplate(List<string> lines)
{
List<string> headers = new List<string>();
dataTable = new DataTable();
if (lines.Count > 0)
{
string[] argHeaders = null;
for (int i = 0; i < lines.Count; i++)
{
if (i > 0)
{
DataRow newRow = dataTable.NewRow();
// others add to rows
string[] argLines = lines[i].Split(seprateChar);
for (int b = 0; b < argLines.Length; b++)
{
newRow[b] = argLines[b];
}
dataTable.Rows.Add(newRow);
}
else
{
// header add to columns
argHeaders = lines[0].Split(seprateChar);
foreach (string c in argHeaders)
{
DataColumn column = new DataColumn(c, typeof(string));
dataTable.Columns.Add(column);
}
}
}
}
return dataTable;
}
I have found best solution
http://www.codeproject.com/Articles/415732/Reading-and-Writing-CSV-Files-in-Csharp
Just I had to re-write
void ReadTest()
{
// Read sample data from CSV file
using (CsvFileReader reader = new CsvFileReader("ReadTest.csv"))
{
CsvRow row = new CsvRow();
while (reader.ReadRow(row))
{
foreach (string s in row)
{
Console.Write(s);
Console.Write(" ");
}
Console.WriteLine();
row = new CsvRow(); //this line added
}
}
}
Well, there is another library Cinchoo ETL - an open source one, for reading and writing CSV files.
Couple of ways you can read CSV files
Id, Name
1, Tom
2, Mark
This is how you can use this library to read it
using (var reader = new ChoCSVReader("emp.csv").WithFirstLineHeader())
{
foreach (dynamic item in reader)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
}
If you have POCO object defined to match up with CSV file like below
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}
You can parse the same file using this POCO class as below
using (var reader = new ChoCSVReader<Employee>("emp.csv").WithFirstLineHeader())
{
foreach (var item in reader)
{
Console.WriteLine(item.Id);
Console.WriteLine(item.Name);
}
}
Please check out articles at CodeProject on how to use it.
Disclaimer: I'm the author of this library