I'm having hard times exporting DB table in CSV file using LINQ. I've tried few things from related topics, but it was all way too long and I need a simpliest solution. There has to be something.
With this code is problem, that file is created, but empty. When I tried to debug, query is fine, there's everything I want to export. What am I doing wrong?
private void Save_Click(object sender, RoutedEventArgs e)
{
StreamWriter sw = new StreamWriter("test.csv");
DataDataContext db = new DataDataContext();
var query = from x in db.Zbozis
orderby x.Id
select x;
foreach (var something in query)
{
sw.WriteLine(something.ToString());
}
}
Edit: Ok, I tried all your suggestions, sadly with same result (CSV was created, but in it was 10x Lekarna.Zbozi (Name of project/db + name of table)).
So I used a method, that I've found (why reinventing a wheel, huh).
public string ConvertToCSV(IQueryable query, string replacementDelimiter)
{
// Create the csv by looping through each row and then each field in each row
// seperating the columns by commas
// String builder for our header row
StringBuilder header = new StringBuilder();
// Get the properties (aka columns) to set in the header row
PropertyInfo[] rowPropertyInfos = null;
rowPropertyInfos = query.ElementType.GetProperties();
// Setup header row
foreach (PropertyInfo info in rowPropertyInfos)
{
if (info.CanRead)
{
header.Append(info.Name + ",");
}
}
// New row
header.Append("\r\n");
// String builder for our data rows
StringBuilder data = new StringBuilder();
// Setup data rows
foreach (var myObject in query)
{
// Loop through fields in each row seperating each by commas and replacing
// any commas in each field name with replacement delimiter
foreach (PropertyInfo info in rowPropertyInfos)
{
if (info.CanRead)
{
// Get the fields value and then replace any commas with the replacement delimeter
string tmp = Convert.ToString(info.GetValue(myObject, null));
if (!String.IsNullOrEmpty(tmp))
{
tmp.Replace(",", replacementDelimiter);
}
data.Append(tmp + ",");
}
}
// New row
data.Append("\r\n");
}
// Check the data results... if they are empty then return an empty string
// otherwise append the data to the header
string result = data.ToString();
if (string.IsNullOrEmpty(result) == false)
{
header.Append(result);
return header.ToString();
}
else
{
return string.Empty;
}
}
So I have a modified version of previous code:
StreamWriter sw = new StreamWriter("pokus.csv");
ExportToCSV ex = new ExportToCSV();
var query = from x in db.Zbozis
orderby x.Id
select x;
string s = ex.ConvertToCSV(query,"; ");
sw.WriteLine(s);
sw.Flush();
Everything is fine, except it export every line in one column and does not separate it. See here -> http://i.stack.imgur.com/XSNK0.jpg
Question is obvious then, how to divide it into columns like I have in my DB?
Thanks
You are not closing the file. Either use "using"
using(StreamWriter sw = new StreamWriter("test.csv"))
{
..............
}
or simply try this
File.WriteAllLines("test.csv",query);
Related
I'm trying to get a csv file into a data table but there are some things in the csv file that I am trying to omit from being entered into the data table, so I wrote it to a list first.
The csv files that i will using the software for have different sections in it for which I then split the whole list into the separate lists for those sections.
After all that was achieved, i needed to skip some lines in each list and wrote the final form i was happy with to lists respective to previous set of lists.
Now I hit a wall, I need to write each of the lists to a respective data grid.
public partial class Form1 : Form
{
String filePath = "";
//list set 1 = list box
List<String> lines = new List<String>();
List<String> accountList = new List<String>();
List<String> statementList = new List<String>();
List<String> summaryList = new List<String>();
List<String> transactionList = new List<String>();
//list set 2 = dgv
List<String> accountList2 = new List<String>();
List<String> statementList2 = new List<String>();
List<String> summaryList2 = new List<String>();
List<String> transactionList2 = new List<String>();
public Form1()
{
InitializeComponent();
}
private void btn_find_Click(object sender, EventArgs e)
{
try
{
using (OpenFileDialog fileDialog = new OpenFileDialog()
{ Filter = "CSV|* .csv", ValidateNames = true, Multiselect = false })
if (fileDialog.ShowDialog() == DialogResult.OK)
{
String fileName = fileDialog.FileName;
filePath = fileName;
}
try
{
if (File.Exists(filePath))
{
lines = File.ReadAllLines(filePath).ToList();
foreach (String line in lines)
{
String addLine = line.Replace("'", "");
String addLine2 = addLine.Replace("\"", "");
String str = line.Substring(0, 1);
int num = int.Parse(str);
if (addLine2.Length > 1)
{
String addLine3 = addLine2.Substring(2);
switch (num)
{
case 2:
accountList.Add(addLine3);
break;
case 3:
statementList.Add(addLine3);
break;
case 4:
summaryList.Add(addLine3);
break;
case 5:
transactionList.Add(addLine3);
break;
}
}
}
}
else
{
MessageBox.Show("Invalid file chosen, choose an appropriate CSV file and try again.");
}
transactionLB.DataSource = transactionList;
//var liness = transactionList;
//foreach (string line in liness.Skip(2))
// transactionList2.Add(line);
//Console.WriteLine(transactionList2);
//var source = new BindingSource();
//source.DataSource = transactionList2;
//trans_dgv.DataSource = source;
accountLB.DataSource = accountList;
summaryLB.DataSource = summaryList;
statementLB.DataSource = statementList;
}
catch (Exception)
{
MessageBox.Show("Cannot load CSV file, Ensure that a valid CSV file is selected and try again.");
}
}
catch (Exception)
{
MessageBox.Show("Cannot open File Explorer, Something is wrong :(");
}
}
}
EDIT 1:
the table has the following columns for the transaction lists (each of the lists have different columns) :
'Number' , 'Date' , 'Description1' , 'Description2' , 'Description3' , 'Amount' , 'Balance' , 'Accrued Charges'
an example of data in the lines of the transaction list:
9, 02 Sep, Petrol Card Purchase, Shell Kempton Park, 968143*7188 30 Aug, -714.45, -10661.88, 5.5
some liness do contain null values.
If I understand correctly, it seems like you're wanting to get the value of the strings in your string list to appear in your DataGridViews. This can be a little tricky because the DataGridView needs to know which property to display and strings only have the Length property (which probably isn't what you're looking for). There are a lot of ways to go about getting the data you want into the DataGridView. For example you could use DataTables and choose which column you want displayed in the DataGridView. If you want to stick with using string lists, I think you could get this to work by modifying your DataSource line to look something like this:
transactionLB.DataSource = transactionList.Select(x => new { Value = x} ).ToList();
I hope this helps! Let me know if I've misunderstood your question. Thanks!
I'm trying to import a CSV file to my C# site and save it in the database. While doing research I learned about CSV parsing, I've tried to implement this but I've ran into some trouble. Here is a portion of my code so far:
string fileext = Path.GetExtension(fupcsv.PostedFile.FileName);
if (fileext == ".csv")
{
string csvPath = Server.MapPath("~/CSVFiles/") + Path.GetFileName(fupcsv.PostedFile.FileName);
fupcsv.SaveAs(csvPath);
// Add Columns to Datatable to bind data
DataTable dtCSV = new DataTable();
dtCSV.Columns.AddRange(new DataColumn[2] { new DataColumn("ModuleId", typeof(int)), new DataColumn("CourseId", typeof(int))});
// Read all the lines of the text file and close it.
string[] csvData = File.ReadAllLines(csvPath);
// iterate over each row and Split it to New line.
foreach (string row in csvData)
{
// Check for is null or empty row record
if (!string.IsNullOrEmpty(row))
{
using (TextFieldParser parser = new TextFieldParser(csvPath))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
while (!parser.EndOfData)
{
//Process row
string[] fields = parser.ReadFields();
int i = 1;
foreach (char cell in row)
{
dtCSV.NewRow()[i] = cell;
i++;
}
}
}
}
}
}
I keep getting the error "There is no row at position -1" at " dtCSV.Rows[dtCSV.Rows.Count - 1][i] = cell;"
Any help would be greatly appreciated, thanks
You are trying to index rows that you have not created. Instead of
dtCSV.Rows[dtCSV.Rows.Count - 1][i] = cell;
use
dtCSV.NewRow()[i] = cell;
I also suggest you start indexing i from 0 and not from 1.
All right so it turns out there were a bunch of errors with your code, so I made some edits.
string fileext = Path.GetExtension(fupcsv.PostedFile.FileName);
if (fileext == ".csv")
{
string csvPath = Server.MapPath("~/CSVFiles/") + Path.GetFileName(fupcsv.PostedFile.FileName);
fupcsv.SaveAs(csvPath);
DataTable dtCSV = new DataTable();
dtCSV.Columns.AddRange(new DataColumn[2] { new DataColumn("ModuleId", typeof(int)), new DataColumn("CourseId", typeof(int))});
var csvData = File.ReadAllLines(csvPath);
bool headersSkipped = false;
foreach (string line in csvData)
{
if (!headersSkipped)
{
headersSkipped = true;
continue;
}
// Check for is null or empty row record
if (!string.IsNullOrEmpty(line))
{
//Process row
int i = 0;
var row = dtCSV.NewRow();
foreach (var cell in line.Split(','))
{
row[i] = Int32.Parse(cell);
i++;
}
dtCSV.Rows.Add(row);
dtCSV.AcceptChanges();
}
}
}
I ditched the TextFieldParser solution solely because I'm not familiar with it, but if you want to stick with it, it shouldn't be hard to reintegrate it.
Here are some of the things you got wrong:
Not calling NewRow() to create a new row or adding it to the table with AddRow(row)
Iterating through the characters in row instead of the fields you parsed
Not parsing the value of cell - it's value type is string and you are trying to add to an int column
Some other things worth noting (just to improve your code's performance and readability :))
Consider using var when declaring new variables, it takes a lot of the stress away from having to worry about exactly what type of variable you are creating
As others in the comments said, use ReadAllLines() it parses your text file into lines neatly, making it easier to iterate through.
Most of the times when working with arrays or lists, you need to index from 0, not from 1
You have to use AcceptChanges() to commit all the changes you've made
I have a csv file that I need to read in the first line and save it to a List. Only problem is there are commas in some of the text and it is splitting in the middle of a field when I need it not to. Unfortunately I cannot change the data inside so whats there needs to stay. I currently also write the data to csv so I was thinking maybe instead of using a comma I can use a different character. Does anyone know if this is possible? I have been researching but am not coming up with a proper answer. Here is my code below:
using System;
using System.CodeDom;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace TestJSON
{
class Program
{
static void Main()
{
var data = JsonConvert.DeserializeObject<dynamic>(File.ReadAllText(
#"C:\Users\nphillips\workspace\2016R23\UITestAutomation\SeedDataGenerator\src\staticresources\seeddata.resource"));
string fileName = "";
var bundles = data.RecordSetBundles;
foreach (var bundle in bundles)
{
var records = bundle.Records;
foreach (var record in records)
{
var test = record.attributes;
foreach (var testagain in test)
{
// Getting the object Name Ex. Location, Item, etc.
var jprop = testagain as JProperty;
if (jprop != null)
{
fileName = jprop.First.ToString().Split('_')[2]+ ".csv";
}
break;
}
string header = "";
string value = "";
foreach (var child in record)
{
var theChild = child as JProperty;
if (theChild != null && !theChild.Name.Equals("attributes"))
{
header += child.Name + ",";
value += child.Value.ToString() + ",";
}
}
value += "+" + Environment.NewLine;
if (!File.Exists(fileName))
{
header += "+" + Environment.NewLine;
File.WriteAllText(fileName, header);
}
else
{
// Need to read in here
var readCSV = new StreamReader(fileName);
var splits = readCSV.ReadLine();
}
File.AppendAllText(fileName, value);
}
}
}
}
}
You need to know how the file is delimited. I would guess that this file is tab delimited, so split on that instead.
Assuming your line is called myCSVLine... I.E
string seperator = "\t";
string[] splitLine = myCSVLine.Split(seperator.ToCharArray());
splitLine would now have all of your strings, including ones with commas
Hi I'm using csvHelper to read in a csv files with a variable number of columns. The first row always contains a header row. The number of columns is unknown at first, sometimes there are three columns and sometimes there are 30+. The number of rows can be large.
I can read in the csv file, but how do I address each column of data. I need to do some basic stats on the data (e.g. min, max, stddev), then write them out in a non csv format.
Here is my code so far...
try{
using (var fileReader = File.OpenText(inFile))
using (var csvResult = new CsvHelper.CsvReader(fileReader))
{
// read the header line
csvResult.Read();
// read the whole file
dynamic recs = csvResult.GetRecords<dynamic>().ToList();
/* now how do I get a whole column ???
* recs.getColumn ???
* recs.getColumn['hadername'] ???
*/
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
Thanks
I don't think the library is capable of doing so directly. You have to read your column from individual fields and add them to a List, but the process is usually fast because readers do job fast. For example if your desired column is of type string, the code would be like so:
List<string> myStringColumn= new List<string>();
using (var fileReader = File.OpenText(inFile))
using (var csvResult = new CsvHelper.CsvReader(fileReader))
{
while (csvResult.Read())
{
string stringField=csvResult.GetField<string>("Header Name");
myStringColumn.Add(stringField);
}
}
using (System.IO.StreamReader file = new System.IO.StreamReader(Server.MapPath(filepath)))
{
//Csv reader reads the stream
CsvReader csvread = new CsvReader(file);
while (csvread.Read())
{
int count = csvread.FieldHeaders.Count();
if (count == 55)
{
DataRow dr = myExcelTable.NewRow();
if (csvread.GetField<string>("FirstName") != null)
{
dr["FirstName"] = csvread.GetField<string>("FirstName"); ;
}
else
{
dr["FirstName"] = "";
}
if (csvread.GetField<string>("LastName") != null)
{
dr["LastName"] = csvread.GetField<string>("LastName"); ;
}
else
{
dr["LastName"] = "";
}
}
else
{
lblMessage.Visible = true;
lblMessage.Text = "Columns are not in specified format.";
lblMessage.ForeColor = System.Drawing.Color.Red;
return;
}
}
}
I'm trying to develop an application which will take the data from a datagrid and based on a drop down menu choice return a csv file with only the selected client . My code is shown below , This links to a previous question I posted howeever I am still getting no values back and I really need to sort this out so I'm wondering if anyone can either see were i'm going wrong or else provide alternatives
//Master inventory export
private void ExportClass_Click(object sender, EventArgs e)
{
StringBuilder str = new StringBuilder();
objSqlCommands2 = new SqlCommands("MasterInventory", "ClientName");
string strString = str.ToString();
string Filepath = txtSaveShareClass.Text.ToString();
str.Append("ISIN ,FundName,Status,Share CCY,Benchmark,NAV Freq,CLASSCODE,SIMULATION,HEDGED,FUNDCCY");
StringManipulation sm = new StringManipulation();
foreach (DataRow dr in this.CalcDataSet.MasterInventory)
{
foreach (object field in dr.ItemArray)
{
str.Append(field.ToString() + ",");
}
str.Replace(",", "\n", str.Length - 1, 1);
}
try
{
System.IO.File.WriteAllText(Filepath, str.ToString());
}
catch (Exception ex)
{
MessageBox.Show("Write Error :" + ex.Message);
}
List<string[]> lsClientList = objStringManipulation.parseCSV(Filepath,cmbClientList .Text.ToCharArray());
foreach (string[] laClient in lsClientList)
{
sm.parseCSV2(Filepath, cmbClientList.Text.ToCharArray());
List<string[]> newFoo = lsClientList.Where(x => x.Contains(cmbClientList.Text)).ToList();
List<string[]> Results = sm.parseCSV2(Filepath, cmbClientList.Text.ToCharArray()).Where(x => x.Contains(cmbClientList.Text)).ToList();
//Refreshs the Client table on display from the
System.IO.File.WriteAllText(Filepath, Results.ToString());
}
this.TableAdapter.Fill(this.CalcDataSet.MasterInventory);
dataGridView2.Update();
}
If all of your variables are filling properly and your Results list contains the data that you expect, then the problem is with your WriteAllText call. You have:
System.IO.File.WriteAllText(Filepath, Results.ToString());
That is not going to produce the output that you seem to expect. It will likely just give you the class name.
Results is a List<string[]>. If you want to output that as a CSV, then you have to enumerate it:
using (var outfile = new StreamWriter(Filepath))
{
foreach (var line in Results)
{
StringBuilder sb = new StringBuilder();
foreach (var field in line)
{
sb.Append(field + ",");
}
sb.Length = sb.Length -1;
outfile.WriteLine(sb.ToString());
}
}