I need to build a method to enhance one csv file with values from another. This method would need to:
take the "original" csv file
for each row from its column 0, look up for a matching record in column 0 of "enhancement" csv file
If there is a match, then for this row the record in column 1 of "original" file will get overwritten by corresponding record in column 1 of the "enhancement" file
I 'm trying the below pattern, which seems workable - but it is so slow that I'm not even able to check it. The size of the files should not be an issue, because one is 1MB, another 2MB, but I'm definitely taking some wrong assumptions to do this efficiently. What would be a better way of doing this?
public static string[] LoadReadyCsv()
{
string[] scr = System.IO.File.ReadAllLines(#Path...CsvScr);
string[] aws = System.IO.File.ReadAllLines(#Path...CsvAws);
Regex CSVParser = new Regex(",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");
foreach (var s in scr)
{
string[] fieldsScr = CSVParser.Split(s);
foreach (var a in aws)
{
string[] fieldsAws = CSVParser.Split(a);
if (fieldsScr[0] == fieldsAws[0])
{
fieldsScr[1] = fieldsAws[1];
}
}
}
return scr;
}
EDIT:
I add an example below, as requested
"Original file"
ean, skunum, prodname
111, empty, bread
222, empty, cheese
"Enhancement file"
ean, skunum, prodname
111, 555, foo
333, 444, foo
New "Original file"
ean,skunum,prodname
111, 555, bread
222, empty, cheese
You can read the csv using Oledb and load into a datatable. Then you can modify table and update which will save results back to file. Use code below
public class CSVReader
{
public DataSet ReadCSVFile(string fullPath, bool headerRow)
{
string path = fullPath.Substring(0, fullPath.LastIndexOf("\\") + 1);
string filename = fullPath.Substring(fullPath.LastIndexOf("\\") + 1);
DataSet ds = new DataSet();
try
{
if (File.Exists(fullPath))
{
string ConStr = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}" + ";Extended Properties=\"Text;HDR={1};FMT=Delimited\\\"", path, headerRow ? "Yes" : "No");
string SQL = string.Format("SELECT * FROM {0}", filename);
OleDbDataAdapter adapter = new OleDbDataAdapter(SQL, ConStr);
adapter.Fill(ds, "TextFile");
ds.Tables[0].TableName = "Table1";
}
foreach (DataColumn col in ds.Tables["Table1"].Columns)
{
col.ColumnName = col.ColumnName.Replace(" ", "_");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return ds;
}
}
To modify the two datatables use linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
DataColumn col = null;
DataTable original = new DataTable();
col = original.Columns.Add("ean", typeof(int));
col.AllowDBNull = true;
col = original.Columns.Add("skunum", typeof(int));
col.AllowDBNull = true;
col = original.Columns.Add("prodname", typeof(string));
col.AllowDBNull = true;
original.Rows.Add(new object[] {111, null, "bread"});
original.Rows.Add(new object[] {222, null, "cheese"});
DataTable enhancement = new DataTable();
col = enhancement.Columns.Add("ean", typeof(int));
col.AllowDBNull = true;
col = enhancement.Columns.Add("skunum", typeof(int));
col.AllowDBNull = true;
col = enhancement.Columns.Add("prodname", typeof(string));
col.AllowDBNull = true;
enhancement.Rows.Add(new object[] {111, 555, "foo"});
enhancement.Rows.Add(new object[] {333, 444, "foo"});
var joinedObject = (from o in original.AsEnumerable()
join e in enhancement.AsEnumerable() on o.Field<int>("ean") equals e.Field<int>("ean")
select new { original = o, enhancement = e }).ToList();
foreach (var row in joinedObject)
{
row.original["skunum"] = row.enhancement["skunum"];
row.original["prodname"] = row.enhancement["prodname"];
}
}
}
}
Related
Data:
itemno: 223344; trn_id: 112233; status:delivered
Data Table :
itemno
trn_id
status
223344
112233
delivered
I want to convert input has data table so that it will be easy for me on filter data on data table based on item.
foreach (DataRow row2 in responcedt.Rows)
{
string[] lines = new string[] { row2.Field<string>("ResponseMsg") } ;
foreach (var line in lines)
{
string[] split = line.Split(';');
DataRow row1 = table.NewRow();
row1.SetField(itemno, split[0]);
row1.SetField(trn_id, split[1]);
row1.SetField(status, split[2]);
table.Rows.Add(row1);
}
}
Try following. If reading from a file replace StringReader with StreamReader :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
string pattern = #"(?'key'[^:]+):(?'value'[^;]+);?";
string input =
"itemno: 223344; trn_id: 112233; status:delivered\n" +
"itemno: 223344; trn_id: 112233; status:delivered\n" +
"itemno: 223344; trn_id: 112233; status:delivered\n" +
"itemno: 223344; trn_id: 112233; status:delivered\n";
StringReader reader = new StringReader(input);
string line = "";
int row = 0;
while ((line = reader.ReadLine()) != null)
{
line = line.Trim();
if (line.Length > 0)
{
MatchCollection matches = Regex.Matches(line, pattern);
var keyValues = matches.Cast<Match>().Select(x => new { key = x.Groups["key"].Value, value = x.Groups["value"].Value.Trim() }).ToList();
if (++row == 1)
{
foreach (var keyvalue in keyValues)
{
dt.Columns.Add(keyvalue.key, typeof(string));
}
}
DataRow newRow = dt.Rows.Add();
foreach (var keyvalue in keyValues)
{
newRow[keyvalue.key] = keyvalue.value;
}
}
}
}
}
}
First, turn the desired string into a dictionary, and then navigate the dictionary, map each of its members to a column, and place each created column in a row, and at the end of the row into a datatable.
string lines = "itemno: 223344; trn_id: 112233; status:delivered\n" +
"itemno: 223344; trn_id: 112233; status:delivered\n" +
"itemno: 223344; trn_id: 112233; status:delivered\n";
DataTable dataTable = new DataTable();
int counter = 0;
foreach (var line in lines.Split('\n'))
{
var dict = line.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
.Select(part => part.Split(':'))
.ToDictionary(split => split[0], split => split[1]);
DataRow dataRow = dataTable.NewRow();
foreach (var key in dict.Keys)
{
if(counter == 0)
{
DataColumn column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = key;
column.AutoIncrement = false;
column.Caption = key;
dataRow.Table.Columns.Add(column);
}
dataRow[key] = dict[key];
}
counter++;
dataTable.Rows.Add(dataRow);
}
dataGridView1.DataSource = dataTable;
So I have a csv files and I want to extract its data into a datagridview and then save this to a database. I only want it to save data displayed after "Tango N$10 Voucher Benefit,10" (See the CSV file extract to understand) I am using a windows application C#. Here is what I tried so far.
try
{
var filePath = Path.GetFullPath(openAirtimeFile.FileName);
foreach (var line in File.ReadAllLines(filePath))
{
var thisLine = line;//.Trim();
if (thisLine.StartsWith("Tango", StringComparison.OrdinalIgnoreCase))
{
string[] data = File.ReadAllLines(filePath);
DataTable dt = new DataTable();
string[] col = data[0].Split(',');
foreach (string s in col)
{
dt.Columns.Add(s, typeof(string));
}
for (int i = 0; i < data.Length; i++)
{
string[] row = data[i].Split(',');
dt.Rows.Add(row);
}
dataGridView1.DataSource = dt;
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
}
}
CSV file looks like this:
Please help. How do I display data after "Tango N$10 Voucher Benefit,10"?
You're doing a File.ReadAllLines two times, so your inner if statement is useless. Perhaps try something like this.
disclaimer, this only works assuming Tango will be at the start of your csv file
try
{
var filePath = Path.GetFullPath(openAirtimeFile.FileName);
bool FoundTango = false;
foreach (var line in File.ReadAllLines(filePath))
{
var thisLine = line;//.Trim();
if (thisLine.StartsWith("Tango", StringComparison.OrdinalIgnoreCase))
{
FoundTango = true;
continue; //Tango has been found, skip to next iteration
}
if (FoundTango)
{
DataTable dt = new DataTable();
string[] col = line.Split(',');
foreach (string s in col)
{
dt.Columns.Add(s, typeof(string));
}
for (int i = 0; i < data.Length; i++)
{
string[] row = line.Split(',');
dt.Rows.Add(row);
}
dataGridView1.DataSource = dt;
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
}
}
I am using Epplus library in order to upload data from excel file.The code i am using is perfectly works for excel file which has standard form.ie if first row is column and rest all data corresponds to column.But now a days i am getting regularly , excel files which has different structure and i am not able to read
excel file like as shown below
what i want is on third row i wan only Region and Location Id and its values.Then 7th row is columns and 8th to 15 are its values.Finally 17th row is columns for 18th to 20th .How to load all these datas to seperate datatables
code i used is as shown below
I created an extension method
public static DataSet Exceltotable(this string path)
{
DataSet ds = null;
using (var pck = new OfficeOpenXml.ExcelPackage())
{
try
{
using (var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
pck.Load(stream);
}
ds = new DataSet();
var wss = pck.Workbook.Worksheets;
////////////////////////////////////
//Application app = new Application();
//app.Visible = true;
//app.Workbooks.Add("");
//app.Workbooks.Add(#"c:\MyWork\WorkBook1.xls");
//app.Workbooks.Add(#"c:\MyWork\WorkBook2.xls");
//for (int i = 2; i <= app.Workbooks.Count; i++)
//{
// for (int j = 1; j <= app.Workbooks[i].Worksheets.Count; j++)
// {
// Worksheet ws = app.Workbooks[i].Worksheets[j];
// ws.Copy(app.Workbooks[1].Worksheets[1]);
// }
//}
///////////////////////////////////////////////////
//for(int s=0;s<5;s++)
//{
foreach (var ws in wss)
{
System.Data.DataTable tbl = new System.Data.DataTable();
bool hasHeader = true; // adjust it accordingly( i've mentioned that this is a simple approach)
string ErrorMessage = string.Empty;
foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column])
{
tbl.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column));
}
var startRow = hasHeader ? 2 : 1;
for (var rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++)
{
var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column];
var row = tbl.NewRow();
foreach (var cell in wsRow)
{
//modifed by faras
if (cell.Text != null)
{
row[cell.Start.Column - 1] = cell.Text;
}
}
tbl.Rows.Add(row);
tbl.TableName = ws.Name;
}
DataTable dt = RemoveEmptyRows(tbl);
ds.Tables.Add(dt);
}
}
catch (Exception exp)
{
}
return ds;
}
}
If you're providing the template for users to upload, you can mitigate this some by using named ranges in your spreadsheet. That's a good idea anyway when programmatically working with Excel because it helps when you modify your own spreadsheet, not just when the user does.
You probably know how to name a range, but for the sake of completeness, here's how to name a range.
When you're working with the spreadsheet in code you can get a reference to the range using [yourworkbook].Names["yourNamedRange"]. If it's just a single cell and you need to reference the row or column index you can use .Start.Row or .Start.Column.
I add named ranges for anything - cells containing particular values, columns, header rows, rows where sets of data begin. If I need row or column indexes I assign useful variable names. That protects you from having all sorts of "magic numbers" in your spreadsheet. You (or your users) can move quite a bit around without breaking anything.
If they modify the structure too much then it won't work. You can also use protection on the workbook and worksheet to ensure that they can't accidentally modify the structure - tabs, rows, columns.
This is loosely taken from a test I was working with last weekend when I was learning this. It was just a "hello world" so I wasn't trying to make it all streamlined and perfect. (I was working on populating a spreadsheet, not reading one, so I'm just learning the properties as I go.)
// Open the workbook
using (var package = new ExcelPackage(new FileInfo("PriceQuoteTemplate.xlsx")))
{
// Get the worksheet I'm looking for
var quoteSheet = package.Workbook.Worksheets["Quote"];
//If I wanted to get the text from one named range
var cellText = quoteSheet.Workbook.Names["myNamedRange"].Text
//If I wanted to get the cell's value as some other type
var cellValue = quoteSheet.Workbook.Names["myNamedRange"].GetValue<int>();
//If I had a named range and I wanted to loop through the rows and get
//values from certain columns
var myRange = quoteSheet.Workbook.Names["rangeContainingRows"];
//This is a named range used to mark a column. So instead of using a
//magic number, I'll read from whatever column has this named range.
var someColumn = quoteSheet.Workbook.Names["columnLabel"].Start.Column;
for(var rowNumber = myRange.Start.Row; rowNumber < myRange.Start.Row + myRange.Rows; rowNumber++)
{
var getTheTextForTheRowAndColumn = quoteSheet.Cells(rowNumber, someColumn).Text
}
There might be a more elegant way to go about it. I just started using this myself. But the idea is you tell it to find a certain named range on the spreadsheet, and then you use the row or column number of that range instead of a magic row or column number.
Even though a range might be one cell, one row, or one column, it can potentially be a larger area. That's why I use .Start.Row. In other words, give me the row for the first cell in the range. If a range has more than one row, the .Rows property indicates the number of rows so I know how many there are. That means someone could even insert rows without breaking the code.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
namespace ReadData
{
public partial class ImportExelDataInGridView : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnUpload_Click(object sender, EventArgs e)
{
//Coneection String by default empty
string ConStr = "";
//Extantion of the file upload control saving into ext because
//there are two types of extation .xls and .xlsx of excel
string ext = Path.GetExtension(FileUpload1.FileName).ToLower();
//getting the path of the file
string path = Server.MapPath("~/MyFolder/"+FileUpload1.FileName);
//saving the file inside the MyFolder of the server
FileUpload1.SaveAs(path);
Label1.Text = FileUpload1.FileName + "\'s Data showing into the GridView";
//checking that extantion is .xls or .xlsx
if (ext.Trim() == ".xls")
{
//connection string for that file which extantion is .xls
ConStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=2\"";
}
else if (ext.Trim() == ".xlsx")
{
//connection string for that file which extantion is .xlsx
ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=2\"";
}
//making query
string query = "SELECT * FROM [Sheet1$]";
//Providing connection
OleDbConnection conn = new OleDbConnection(ConStr);
//checking that connection state is closed or not if closed the
//open the connection
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
//create command object
OleDbCommand cmd = new OleDbCommand(query, conn);
// create a data adapter and get the data into dataadapter
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
DataSet ds = new DataSet();
//fill the excel data to data set
da.Fill(ds);
if (ds.Tables != null && ds.Tables.Count > 0)
{
for (int i = 0; i < ds.Tables[0].Columns.Count; i++)
{
if (ds.Tables[0].Columns[0].ToString() == "ID" && ds.Tables[0].Columns[1].ToString() == "name")
{
}
//else if (ds.Tables[0].Rows[0][i].ToString().ToUpper() == "NAME")
//{
//}
//else if (ds.Tables[0].Rows[0][i].ToString().ToUpper() == "EMAIL")
//{
//}
}
}
//set data source of the grid view
gvExcelFile.DataSource = ds.Tables[0];
//binding the gridview
gvExcelFile.DataBind();
//close the connection
conn.Close();
}
}
}
try
{
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
if (!string.IsNullOrEmpty(p.ProcessName))
{
try
{
p.Kill();
}
catch { }
}
}
REF_User oREF_User = new REF_User();
oREF_User = (REF_User)Session["LoggedUser"];
string pdfFilePath = Server.MapPath("~/FileUpload/" + oREF_User.USER_ID + "");
if (Directory.Exists(pdfFilePath))
{
System.IO.DirectoryInfo di = new DirectoryInfo(pdfFilePath);
foreach (FileInfo file in di.GetFiles())
{
file.Delete();
}
Directory.Delete(pdfFilePath);
}
Directory.CreateDirectory(pdfFilePath);
string path = Server.MapPath("~/FileUpload/" + oREF_User.USER_ID + "/");
if (Path.GetExtension(FileUpload1.FileName) == ".xlsx")
{
string fullpath1 = path + Path.GetFileName(FileUpload1.FileName);
if (FileUpload1.FileName != "")
{
FileUpload1.SaveAs(fullpath1);
}
FileStream Stream = new FileStream(fullpath1, FileMode.Open);
IExcelDataReader ExcelReader = ExcelReaderFactory.CreateOpenXmlReader(Stream);
DataSet oDataSet = ExcelReader.AsDataSet();
Stream.Close();
bool result = false;
foreach (System.Data.DataTable oDataTable in oDataSet.Tables)
{
//ToDO code
}
oBL_PlantTransactions.InsertList(oListREF_PlantTransactions, null);
ShowMessage("Successfully saved!", REF_ENUM.MessageType.Success);
}
else
{
ShowMessage("File Format Incorrect", REF_ENUM.MessageType.Error);
}
}
catch (Exception ex)
{
ShowMessage("Please check the details and submit again!", REF_ENUM.MessageType.Error);
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
if (!string.IsNullOrEmpty(p.ProcessName))
{
try
{
p.Kill();
}
catch { }
}
}
}
I found this article to be very helpful.
It lists various libraries you can choose from. One of the libraries I used is EPPlus as shown below.
Nuget: EPPlus Library
Excel Sheet 1 Data
Cell A2 Value :
Cell A2 Color :
Cell B2 Formula :
Cell B2 Value :
Cell B2 Border :
Excel Sheet 2 Data
Cell A2 Formula :
Cell A2 Value :
static void Main(string[] args)
{
using(var package = new ExcelPackage(new FileInfo("Book.xlsx")))
{
var firstSheet = package.Workbook.Worksheets["First Sheet"];
Console.WriteLine("Sheet 1 Data");
Console.WriteLine($"Cell A2 Value : {firstSheet.Cells["A2"].Text}");
Console.WriteLine($"Cell A2 Color : {firstSheet.Cells["A2"].Style.Font.Color.LookupColor()}");
Console.WriteLine($"Cell B2 Formula : {firstSheet.Cells["B2"].Formula}");
Console.WriteLine($"Cell B2 Value : {firstSheet.Cells["B2"].Text}");
Console.WriteLine($"Cell B2 Border : {firstSheet.Cells["B2"].Style.Border.Top.Style}");
Console.WriteLine("");
var secondSheet = package.Workbook.Worksheets["Second Sheet"];
Console.WriteLine($"Sheet 2 Data");
Console.WriteLine($"Cell A2 Formula : {secondSheet.Cells["A2"].Formula}");
Console.WriteLine($"Cell A2 Value : {secondSheet.Cells["A2"].Text}");
}
}
I am trying to parse a CSV and construct a DataTable out of it. Now the tricky part is i would like to assign data types before constructing the data table.
For eg consider the following CSV file
Name,Age,Salary
A,30,1000
B,35,1500
C,40,2000
I would like to have Name stored as string, Age as Int and Salary as decimal in the data table I am constructing. Any suggestions on the best way to do this?
Here's a naive implementation that ignores most error checking, and some good coding practices:
namespace StackOverflowConsole
{
using System;
using System.IO;
using System.Data;
class Program
{
static void Main(string[] args)
{
var path = #"C:\temp\test.csv";
CreateTestFile(path);
var dataTable = new DataTable();
dataTable.Columns.Add("Name", typeof(string));
dataTable.Columns.Add("Age", typeof(int));
dataTable.Columns.Add("Salary", typeof(decimal));
// TODO: add checks, exception handling
using (var reader = new StreamReader(path))
{
// reads all lines into a single string
var lines = reader.ReadToEnd().Split(new char[] { '\n' });
if (lines.Length > 0)
{
// you may wanna skip the first line, if you're using a file header
foreach (string line in lines)
{
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
// split the current line using the separator
var tokens = line.Trim().Split(new char[] { ',' });
// check your assumptions on the CSV contents
// ex: only process lines with the correct number of fields
if (tokens.Length == 3)
{
var person = new Person();
person.Name = tokens[0];
// a better implementation would use TryParse()
person.Age = Int32.Parse(tokens[1]);
person.Salary = Decimal.Parse(tokens[2]);
dataTable.Rows.Add(person.Name, person.Age, person.Salary);
}
}
}
}
}
private static void CreateTestFile(string path)
{
if (File.Exists(path))
{
File.Delete(path);
}
using (var writer = new StreamWriter(path))
{
writer.WriteLine("A,30,1000");
writer.WriteLine("B,35,1500");
writer.WriteLine("C,40,2000");
}
}
}
public class Person
{
public string Name;
public int Age;
public decimal Salary;
}
}
Try this:
Keep CSV file in code directory
string path = Server.MapPath("emp.csv");
string header = "Yes";
string sql = string.Empty;
DataTable dt = null;
string fullpath = Path.GetDirectoryName(path);
string fileName = Path.GetFileName(path);
OleDbConnection connection = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fullpath + ";Extended Properties=\"Text;HDR=" + header + "\"");
OleDbDataAdapter da = new OleDbDataAdapter("select * from [" + fileName + "]", connection);
dt = new DataTable();
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Age", typeof(int));
dt.Columns.Add("Salary", typeof(decimal));
da.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
Please let me know, if there any way to generate CSV files from a DataTable or DataSet? To be specific, without manually iterating through rows of DataTable and concatenating.
Please help
There are several ways to do that.
One of the simplest (IMO) is using FileHelpers Library
FileHelpers.CsvEngine.DataTableToCsv(dataTable, filename);
A relative simple, compact and quite flexible solution could be the following extension method:
public static string ToCsv(this DataTable table, string colSep = "", string rowSep = "\r\n")
{
var format = string.Join(colSep, Enumerable.Range(0, table.Columns.Count)
.Select(i => string.Format("{{{0}}}", i)));
return string.Join(rowSep, table.Rows.OfType<DataRow>()
.Select(i => string.Format(format, i.ItemArray)));
}
Please note that this solution could cause problems with huge amounts of data, in which case you should stream the output. Quoting and formatting would of course make the code more complex.
There is, I hope, also a possible way for doing that:
static void Main(string[] args)
{
DataTable dt = new DataTable("MyTable");
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Name", typeof(string));
DataRow dr1 = dt.NewRow();
dr1["Id"] = 1;
dr1["Name"] = "John Smith";
dt.Rows.Add(dr1);
DataRow dr2 = dt.NewRow();
dr2["Id"] = 2;
dr2["Name"] = "John West";
dt.Rows.Add(dr2);
List<DataRow> list = dt.AsEnumerable().ToList();
var strlist = from dr in list
select dr[0] + ", " + dr[1];
var csv = string.Join(Environment.NewLine,strlist);
Console.WriteLine(csv);
}
//Dataset To Xls
ExportDataSetToCsvFile(DS,#"C:\\");
internal static void ExportDataSetToCsvFile(DataSet _DataSet, string DestinationCsvDirectory)
{
try
{
foreach (DataTable DDT in _DataSet.Tables)
{
String MyFile = #DestinationCsvDirectory + "\\_" + DDT.TableName.ToString() + DateTime.Now.ToString("yyyyMMddhhMMssffff") + ".csv";//+ DateTime.Now.ToString("ddMMyyyyhhMMssffff")
using (var outputFile = File.CreateText(MyFile))
{
String CsvText = string.Empty;
foreach (DataColumn DC in DDT.Columns)
{
if (CsvText != "")
CsvText = CsvText + "," + DC.ColumnName.ToString();
else
CsvText = DC.ColumnName.ToString();
}
outputFile.WriteLine(CsvText.ToString().TrimEnd(','));
CsvText = string.Empty;
foreach (DataRow DDR in DDT.Rows)
{
foreach (DataColumn DCC in DDT.Columns)
{
if (CsvText != "")
CsvText = CsvText + "," + DDR[DCC.ColumnName.ToString()].ToString();
else
CsvText = DDR[DCC.ColumnName.ToString()].ToString();
}
outputFile.WriteLine(CsvText.ToString().TrimEnd(','));
CsvText = string.Empty;
}
System.Threading.Thread.Sleep(1000);
}
}
}
catch (Exception Ex)
{
throw Ex;
}
}
So this is a fairly bizarre solution, but it works faster than most as it makes use of the JSON.net library's serialization. This speeds the solution up significantly.
Steps:
Create array of every column name in the data table, should be
simple
Use JSON.net to convert datatable to a json string
string json = JsonConvert.SerializeObject(dt, Formatting.None);
Begin making use of the Replace function on c# strings and strip the
json string of all json formatting.
json = json.Replace("\"", "").Replace("},{", "\n").Replace(":", "").Replace("[{", "").Replace("}]", "");
Then use the array from step 1 to remove all column names from the
json string. You are left with a csv formatted string.
Consider using the array created in step 1 to add the column names
back in as the first row in csv format.