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
Related
How can i filter the rows using textBox when rows are added manually
Here is my code:
int n = XML_Grid.Rows.Add();
XML_Grid.ClearSelection();
XML_Grid.Rows[n].Cells[1].Value = FileName;
XML_Grid.Rows[n].Cells[2].Value = Name;
XML_Grid.Rows[n].Cells[3].Value = ID;
XML_Grid.Rows[n].Cells[4].Value = Date;
If not possible to filter how can i add the rows using datatable like i did for the DataGridView in the same way?
Note: This question could be duplicate but i didn't find any solution to my problem
Load your Xml data to DataTable and then set this DataTable to XML_Grid.DataSource.
DataTable dt = new DataTable();
dt.Clear();
dt.Columns.Add("FileName");
dt.Columns.Add("Name");
dt.Columns.Add("ID");
dt.Columns.Add("Date");
XML_Grid.Rows.Clear();
lbl_Path.Text = fbd.SelectedPath;
string[] files = Directory.GetFiles(fbd.SelectedPath, "*.xml");
XmlDocument doc = new XmlDocument();
XmlNodeList nodes = doc.GetElementsByTagName("cfdi:Emisor");
XmlNodeList nodes1 = doc.GetElementsByTagName("cfdi:Comprobante");
foreach (string tot_file in files)
{
doc.Load(tot_file);
string FileName = Path.GetFileNameWithoutExtension(tot_file);
for (int i = 0; i < nodes.Count; i++)
{
string Name = nodes[i].Attributes["Nombre"].Value;
string ID = nodes[i].Attributes["Rfc"].Value;
string Date = nodes1[i].Attributes["Fecha"].Value;
DataRow row = dt.NewRow();
row["FileName"] = FileName;
row["Name"] = Name;
row["ID"] = ID;
row["Date"] = Date;
dt.Rows.Add(row);
}
}
XML_Grid.DataSource = dt;
And in your textbox textchanged event add below like to filter data.
(XML_Grid.DataSource as DataTable).DefaultView.RowFilter = string.Format("FileName LIKE '{0}%'", txt_FileName.Text)
Edit:
If you want to add the rows to your existing columns that you added through add column from datagridview then just set DataPropertyName for each of column of XML_Grid to column name of DataTable like
XML_Grid.Columns[0].DataPropertyName = "FileName";
XML_Grid.Columns[1].DataPropertyName = "Name";
XML_Grid.Columns[2].DataPropertyName = "ID";
XML_Grid.Columns[3].DataPropertyName = "Date";
Where 0,1,2,3 are the index of your column. Verify your column index respective to you existing columns in XML_Grid.
Add above line of code just above to XML_Grid.Rows.Clear();
Alternative to above code is you can set DataPropertyName for each of column from Property Window of datagridview.
Select XML_Grid ==> Open Property Window ==> Select Columns Property ==> Choose your column ==> And set its DataPropertyName from (none) to "FileName".
And same for all of your remaining columns.
I have a application where I save data from a datagridView with 3 columns to the xml file the application has save and load buttions where when save is pressed it saves to the xml file problem is it does not load the changes made in the datagridview... Only loads the headers for it.
DATAGRIDVIEW COLUMNS : (column 1= text, column 2 =checkbox , column 3 = dropdown w) Note: The dropdown has two values... so its obvoiusly 0 and 1
Code for save :
public void Save(DataGridView dgv)
{
DataTable dt = new DataTable();
for (int i = 1; i < dgv.Columns.Count + 1; i++)
{
DataColumn column = new DataColumn(dgv.Columns[i - 1].HeaderText);
dt.Columns.Add(column);
}
int ColumnCount = dgv.Columns.Count;
foreach (DataGridViewRow dr in dgv.Rows)
{
DataRow dataRow = dt.NewRow();
for (int i = 0; i < ColumnCount; i++)
{
dataRow[i] = dr.Cells[i];
}
}
DataSet ds = new DataSet();
ds.Tables.Add(dt);
XmlTextWriter newXml = new XmlTextWriter(#"c:/older/DGVXML.xml", Encoding.UTF8);
ds.WriteXmlSchema(newXml);
}
So far this is all I have for the load:
public void Load(DataGridView dgv)
{
XmlReader xmlFile = XmlReader.Create(#"c:/older/DGVXML.xml", new XmlReaderSettings());
DataSet dataSet = new DataSet();
dataSet.ReadXml(xmlFile,XmlReadMode.ReadSchema);
//LOADS!!! YAY, but only the headers with no data... check save?
dgv.DataSource = dataSet.Tables[0];
xmlFile.Close();
}
Problem 1
You have to call dt.Rows.Add(dataRow) to add row.
http://msdn.microsoft.com/en-us/library/5ycd1034.aspx
Problem 2
DataSet.WriteXmlSchema method doesn't output current data, only structure.
http://msdn.microsoft.com/en-us/library/kas5y1ky(v=vs.110).aspx
Use DataSet.WriteXml method instead.
http://msdn.microsoft.com/en-us/library/ws09ehyc(v=vs.110).aspx
Code being used is as follows.. made changes to it (edited by question asker)
DataTable dt = new DataTable();
for (int i = 1; i < dgv.Columns.Count + 1; i++)
{
DataColumn column = new DataColumn(dgv.Columns[i - 1].HeaderText);
dt.Columns.Add(column);
}
int columnCount = dgv.Columns.Count;
foreach (DataGridViewRow dr in dgv.Rows)
{
DataRow dataRow = dt.NewRow();
for (int i = 0; i < columnCount; i++)
{
//returns checkboxes and dropdowns as string with .value..... nearly got it
dataRow[i] = dr.Cells[i].Value;
}
dt.Rows.Add(dataRow);
}
DataSet ds = new DataSet();
ds.Tables.Add(dt);
XmlTextWriter xmlSave = new XmlTextWriter(#"c:/older/DGVXML.xml", Encoding.UTF8);
ds.WriteXml(xmlSave);
xmlSave.Close();
You first mistake was to choose ListDictionary as a holder for data. Second, to serialize data as array of string.
You could have a small type presenter class to hold your data (or use Tuple).
public class MyParameter
{
public string Name {get; set;}
public bool Enabled {get; set;} // notice type
public SomeType Direction {get; set;} // not sure in type
}
Then you can easily serialize rows as a list or array
var list = dgv.Rows.Select(o => new MyParameter()
{
Name = o.Cells["name"],
Enabled = o.Cells["ENABLED"],
Direction = o.Cells["DIRECTION"]
}).ToList();
And restoring data will looks as simple as
foreach(var parameter in app.Properties.Settings.Default.DeviceSettings)
{
dvg.Rows.Add(parameter.Name, parameter.Enabled, parameter.Direction);
}
Code may not compile (from head), but should give an idea.
I forgot to mention, what I never used Properties to store application settings (simply because they are crap). I rely on the fact, what you was able to store Dictionary in it, then my implementation should works as well.
Much better way to save configuration (configuration is a set of application properties) is to use, to example, XmlSerializer to save data in xml format (which is human-friendly to view/edit). The approach will still be the same to store list of settings: get them as a list, serialize (or if they are just a part of other configuration settings, assign to property and serialize whole configuration).
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'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.