I'm trying to export data in multiple files to a single datatable. I was able to add data to the dataset but it doesn't provide the output that I need. I guess it should be an error in my loop and I tried in different ways but failed to get the correct output. Given below the output that I receive:
And this is the output I need:
Please refer the coding that I used, and please help me to find where I'm going wrong. Thanks in advance.
OpenFileDialog thisDialog = new OpenFileDialog();
thisDialog.Multiselect = true;
DataTable dt = new DataTable();
if (thisDialog.ShowDialog() == DialogResult.OK)
{
foreach (string files in thisDialog.FileNames)
{
//each file generates two columns
DataColumn column1 = new DataColumn();
dt.Columns.Add(column1);
DataColumn column2 = new DataColumn();
dt.Columns.Add(column2);
using (System.IO.StreamReader file = new System.IO.StreamReader(files))
{
string line;
while ((line = file.ReadLine()) != null)
{
if (line.Contains("DISKXFER"))
{
string dataLine = line.ToString();
string[] split = dataLine.Split(',');
int result = split.Length;
DataRow row = dt.NewRow();
dt.Rows.Add(split[2], split[3]);
}
}
}
}
dataGridView1.DataSource = dt;
}
You are adding a new row for each DISKXFER line in each file, with only the first two columns populated - dt.rows.add does this.
You should fill in more of the columns in dr, then add dr to the table.
Related
This is the button which I press in order the csv-s to be imported:
private void btnOpen_Click_1(object sender, EventArgs e)
{
using (var fbd = new FolderBrowserDialog())
{
DialogResult result = fbd.ShowDialog();
if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
{
// string[] files = Directory.GetFiles(fbd.SelectedPath);
string[] csvFiles = Directory.GetFiles(#"D:\CSV", "*.csv");
foreach (string filePath1 in csvFiles)
{
BindData(filePath1);
}
}
}
}
This is the method that is called for each csv. The problem is that it makes the datagridview each time the last csv is imported. I want a way that adds all the records not only my last imported csv:
private void BindData(string filePath)
{
DataTable dt = new DataTable();
using (TextFieldParser parser = new TextFieldParser(filePath))
{
// 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[0], typeof(string));
dt.Columns.Add(fields[1], typeof(string));
dt.Columns.Add(fields[6], typeof(float));
dt.Columns.Add(fields[7], typeof(float));
dt.Columns.Add(fields[8], typeof(string));
dt.Columns.Add(fields[9], 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
DataRow row = dt.NewRow();
// put data values; cast if needed - this example uses string type columns
row[0] = line[0];
row[1] = line[1];
row[2] = line[6];
row[3] = line[7];
row[4] = line[8];
row[5] = line[9];
// add the newly created and filled row
dt.Rows.Add(row);
}
}
this.dataGridView1.DataSource = dt;
// asign to DGV
}
Change this line
DataTable dt = new DataTable();
So it says:
DataTable dt = (this.dataGridView1.DataSource as DataTable) ?? new DataTable();
So that you either reuse your existing data source or make a new one if it is not set
I have a DataGridView that contains data which has been successfully imported from a .csv file using the code below. The columns in the DGV can be reordered by the user. I need to export the data to a SQL Server database using the columns' DisplayIndex order rather than the Index order.
private void btn_Upload_Click(object sender, EventArgs e)
{
char colDelimiter = ',';
char rowDelimiter = '\r';
DataTable dataTable = new DataTable();
OpenFileDialog getFile = new OpenFileDialog();
getFile.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*";
getFile.FilterIndex = 1;
if(getFile.ShowDialog() == DialogResult.OK)
{
string fileName = getFile.FileName;
TextReader reader = new StreamReader(getFile.FileName);
string[] columns = reader.ReadLine().Split(colDelimiter);
int x = 0;
foreach(string c in columns)
{
dataTable.Columns.Add(columns[x]);
x += 1;
}
x = 0;
string[] rows = reader.ReadToEnd().Split(rowDelimiter);
foreach (string r in rows)
{
string[] record = r.Split(colDelimiter);
dataTable.Rows.Add(record);
}
this.dataGridView1.DataSource = dataTable;
MessageBox.Show(fileName + " was successfully imported.");
}
Unfortunately this is the best solution I know of: Create a new table based on the dataGridView's displayed table. Then replace the original DataTable with the new one. I'm assuming you have some DataTable called table in this example.
Hope this helps and I wish there was a simpler way, but if you're doing a large Update() command this is the easiest approach I know.
If you're doing something where you manually update each line with a SQL query or something though you can just make sure the update goes based on the DisplayIndex and the DataGridView rather than the DataTable directly.
//Make a new DataTable
DataTable newTable = new DataTable();
//Create Columns based on DataGridView headers
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
newTable.Columns.Add(col.HeaderText);
}
//Add each row of data from DataGridView into new DataTable in the displayed order
foreach (DataGridViewRow row in dataGridView1.Rows)
{
DataRow newRow = newTable.NewRow();
foreach(DataGridViewCell cell in row.Cells)
{
newRow[cell.ColumnIndex] = cell.Value;
}
newTable.Rows.Add(newRow);
}
//Set your original DataTable to the new DataTable with the correct ordering
table = newTable;
Also, as a note, I was looking at how you originally load the .csv...
I have something similar where I'm splitting based on delimiters and I just make sure to include a Schema.ini where my .csv is being loaded from and then use ADO commands to populate the DataTable. This seems to work much faster for me.
See my Schema.ini which splits at commas:
[tempdata.csv]
Format=Delimited(,)
ColNameHeader=True
MaxScanRows=0
Here is the #include command:
using System.Data.OleDb;
Here is the C# code to populate my DataTable using the dataAdapter Fill(), set the binding source to the DataTable, and then set the DataSource for my dataGridView to the binding source:
string connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + workingPath + ";Extended Properties=\"text;HDR=YES;FMT=Delimited(|)\"";
using (OleDbConnection conn = new OleDbConnection(connString))
{
using (OleDbCommand cmd = new OleDbCommand("SELECT * FROM " + workingFilename, conn))
{
conn.Open();
OleDbDataAdapter dAdapter = new OleDbDataAdapter(cmd);
originalTable = new DataTable("");
dAdapter.Fill(originalTable);
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I would like to extract data from a txt file and put it into a DataTable. The content in the txt file is in the following format:
sometext1:sometext2:sometext3 sometext4:sometext5:sometext6
sometext7:sometext8:sometext9 ...
Each line represents a row and every column is separated with ":" character.
I tried doing this:
DataTable tbl = new DataTable();
using (StreamWriter sw = File.CreateText(path))
{
string[] rows = content.Split('\n');
foreach (string s in rows)
{
string[] columns = s.Split(':');
foreach (string t in columns)
{
sw.WriteLine(t);
}
}
}
How can I read this file and add it to DataTable?
This is a simple method to do your job
public DataTable ConvertToDataTable (string filePath, int numberOfColumns)
{
DataTable tbl = new DataTable();
for(int col =0; col < numberOfColumns; col++)
tbl.Columns.Add(new DataColumn("Column" + (col+1).ToString()));
string[] lines = System.IO.File.ReadAllLines(filePath);
foreach(string line in lines)
{
var cols = line.Split(':');
DataRow dr = tbl.NewRow();
for(int cIndex=0; cIndex < 3; cIndex++)
{
dr[cIndex] = cols[cIndex];
}
tbl.Rows.Add(dr);
}
return tbl;
}
Here's an excellent class that will copy CSV data into a datatable using the structure of the data to create the DataTable:
http://www.codeproject.com/Articles/11698/A-Portable-and-Efficient-Generic-Parser-for-Flat-F
This topic has also been discussed here:
How to read a CSV file into a .NET Datatable
However, if you are willing to write the code yourself, there is an example:
Dim csvFileFolder As String = "C:\YourFileFolder"
Dim csvFileName As String = "YourFile.csv"
'Note that the folder is specified in the connection string,
'not the file. That's specified in the SELECT query, later.
Dim connString As String = "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=" _
& csvFileFolder & ";Extended Properties=""Text;HDR=No;FMT=Delimited"""
Dim conn As New Odbc.OdbcConnection(connString)
'Open a data adapter, specifying the file name to load
Dim da As New Odbc.OdbcDataAdapter("SELECT * FROM [" & csvFileName & "]", conn)
'Then fill a data table, which can be bound to a grid
Dim dt As New DataTableda.Fill(dt)
It's in VB.NET, if you can't translate it to C# let me know.
Regards.
Well, you presumably have your data right here:
string[] rows = content.Split('\n');
foreach (string s in rows)
{
string[] columns = s.Split(':');
foreach (string t in columns)
{
// each data element
}
}
If you have a DataTable defined, you can add rows to it with a very similar construct. I don't know the structure of your table, but essentially you can do this:
string[] rows = content.Split('\n');
foreach (string s in rows)
{
string[] columns = s.Split(':');
var dataRow = someDataTable.NewRow();
dataRow["someColumnName"] = columns[0];
dataRow["anotherColumnName"] = columns[1];
dataRow["someOtherColumnName"] = columns[2];
// and so on...
someDataTable.Rows.Add(dataRow);
}
If the DataTable's columns aren't strongly named, you can also add items by index:
dataRow.Item[0] = columns[0];
dataRow.Item[1] = columns[1];
// and so on...
The below will execute the entire process as you outlined.
var table = new DataTable();
var fileContents = File.ReadAllLines("yourFile");
var splitFileContents = (from f in fileContents select f.Split(':')).ToArray();
int maxLength = (from s in splitFileContents select s.Count()).Max();
for (int i = 0; i < maxLength; i++)
{
table.Columns.Add();
}
foreach (var line in splitFileContents)
{
DataRow row = table.NewRow();
row.ItemArray = (object[])line;
table.Rows.Add(row);
}
I would like to populate the first several columns with data from a CSV file
The code I am using:
...
DataTable dataTable = (DataTable)readCsvTable(openFileDialog1.FileName);
if (dataTable != null) dataGridViewQuestions.DataSource = dataTable;
...
private DataTable readCsvTable(string filename)
{
DataTable dtDataSource = new DataTable();
try
{
string[] fileContent = File.ReadAllLines(filename);
if (fileContent.Count() > 0)
{
//Create data table columns
string[] columns = fileContent[0].Split(',');
for (int i = 0; i < columns.Count(); i++)
{
dtDataSource.Columns.Add(columns[i]);
}
//Add row data
for (int i = 1; i < fileContent.Count(); i++)
{
string[] rowData = fileContent[i].Split(',');
dtDataSource.Rows.Add(rowData);
}
}
}
catch (Exception ex) {
...
//error msgbox
...
return null;
}
return dtDataSource;
}
The problem:
When AutoGenerateColumns = true - the code results in additional columns (with the same names as the first several columns already in the DataGridView in case of files exported by the same application) being added to the gridView and filled with the appropriate data.
When AutoGenerateColumns = false - the above code adds the right number of rows to the table, and no new columns are added but the rows are empty.
Already tried:
Calling the columns in the CSV file by the column's HeaderText and the column's control name, making a CSV file with the same number of columns as the DataGridView and making files with fewer columns, no difference.
I've just tried simulating this and it works as expected. Are you getting any exceptions thrown when switching files?
You could try setting the datasource to null before attempting to parse the files so you can see if it gets that far?
dataGridViewQuestions.DataSource = null;
DataTable dataTable = readCsvTable(openFileDialog1.FileName);
if (dataTable != null)
dataGridViewQuestions.DataSource = dataTable;
if the data populating from When "AutoGenerateColumns = true" use it.
in that if the previous columns is your problem then you can create new instance to that datagridview;
...
if (dataTable != null)
{
dataGridViewQuestions = new DataGridView();
dataGridViewQuestions.DataSource = dataTable;
}
...
I have a xls
file. Which have following data.
Now I want to get the values inserted into a datatable dt1. I just want a simple procedure with plain c#. no api/ dll. What i have tried is given below:
string strfilename = "";
DataTable dt = new DataTable();
if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
{
strfilename = openFileDialog1.InitialDirectory + openFileDialog1.FileName;
}
string[] csvRows = System.IO.File.ReadAllLines(strfilename); ;
string[] fields = null;
foreach (string csvRow in csvRows)
{
fields = csvRow.Split(',');
DataRow row = dt.NewRow();
row.ItemArray = fields;
dt.Rows.Add(row);
}
Here my csvRow should find 7 rows. but it get 131 rows. and they are unreadable for me. some kind of symbolic.
You have created a DataTable but you haven't defined any columns in it (AKA Schema).
You need to have at least the same amount of columns as many fields (comma separated) are present in your CSV file
Add this before entering the reading loop
string[] csvRows = System.IO.File.ReadAllLines(strfilename);
for(int x = 0; i < csvRows.Length; x++)
dt.Columns.Add("Col" + x.ToString());
Now your ItemArray has the same number of 'columns' of your csv.
take a look at this example it may help: http://www.codeproject.com/Tips/429712/Convert-CSV-File-to-data-table