I have a DataTable called dt which is filled with values from excel.
On line 6 (row) i have my header information
Code i have now
string connString = #"Provider=Microsoft.ACE.OLEDB.16.0;Data Source=C:\Users\thoje\Desktop\stack\forslag.xlsx;" +
#"Extended Properties=""Excel 12.0;HDR=No;""";
DataTable dt = new DataTable();
string sql = #"SELECT * from [Ark1$]";
using (OleDbConnection conn = new OleDbConnection(connString))
{
conn.Open();
using (OleDbCommand cmd = new OleDbCommand(sql, conn))
{
using (OleDbDataReader rdr = cmd.ExecuteReader())
{
dt.Load(rdr);
}
}
}
DataTable dt2 = dt.Clone();
//foreach (DataRow dr in dt.Rows)
//{
for (int i = 5; i <= dt.Rows.Count-1; i++)
{
if (i == 6)
{
DataRow dr = dt2.NewRow();
dr.ItemArray = dt.Rows[i].ItemArray;
dt2.Rows.Add(dr);
}
else if(i >=8)
{
DataRow dr = dt2.NewRow();
dr.ItemArray = dt.Rows[i].ItemArray;
dt2.Rows.Add(dr);
}
}
What i need is:
I want all my data on row 6 to become headers in a new DataTable
All data after line 7 i need to append to this new Datatable with the new headers.
What my code shows:
My code now shows how to do it on a DataTable which is cloned, so therefore i have the wrong headernames.
You don't need to iterate through all rows if you only need 1 of them.
DataTable dtSource = new DataTable();
DataTable dtTarget = new DataTable();
// Get row at index == 6 (7th line as this is a 0-based-index)
var headerRow = dtSource.Rows[6];
// Iterate through all values
foreach(var value in headerRow.ItemArray)
{
// For each value create a column
// and add it to your new dataTable
DataColumn dc = new DataColumn(value.ToString());
dc.Caption = value.ToString();
dtTarget.Columns.Add(dc);
}
using a linq approach might be good:
a pseudo way:
//linq query to select row
var query = from myRow in
myDataTable.AsEnumerable() where myRow.Field<int>("RowNo") == 6
select myRow;
// Create a table from the query DataTable newTable =
query.CopyToDataTable<DataRow>();
Your question is pretty confusing to read, and keeps talking about rows where I'd expect columns etc, but I'll make the following assumptions:
You have an excel file with 5 blank rows and then a row of headers, and then data rows
You've successfully imported this data into a Datatable called dt
You want to end up with a datatable that has the values in row 6 as the column names, and the blank rows removed
Code:
for(int i = 5; i >= 0; i--){
if(i == 5)
{
for(int j = 0; j < dt.Columns.Count; j++)
dt.Columns[j].ColumnName = dt.Rows[i][j].ToString();
}
dt.Rows.RemoveAt(i);
}
You don't need to clone the datatable. Watch out for strings that make for poor column names (containing chars like '[' ) making your life miserable further down the line ..
Related
I'm trying to sort the data in a DataTable which is in a Dataset.
By Using the below code it is working
DataTable dt = (this._dataSet).Tables["Customers"];
dt.DefaultView.Sort = "Surname";
dt.TableName = "Customers";
DataTable defaultviewtable = dt.DefaultView.ToTable();
(this._dataSet).Tables.Remove("Customers");
(this._dataSet).Tables.Add(defaultviewtable);
By using the above code sorting is working, but because of the other table relationships it's not removing the table (from the line 5 in code) and throwing an error "Relationships should be removed first" which is not at all my case. If I remove the relationships I will loose the data from other table.
I tried by Using "DataviewManager" for sorting but it is not sorting ?
Can any one suggest how to append the sorted data to DataSet from DataViewManager ?
Note : My Dataset has 4 tables.
This is the code :
var dataViewSetting = new DataViewManager(this._dataSet).DataViewSettings["Customers"];
if (dataViewSetting != null)
{
dataViewSetting.ApplyDefaultSort = true;
dataViewSetting.Sort = "Surname";
}
DataTable dt = (this._dataSet).Tables["Customers"];
dt.DefaultView.Sort = "Surname";
dt.TableName = "Customers";
DataTable defaultviewtable = dt.DefaultView.ToTable();
// Remove all rows from the table
for(int i = dt.Rows.Count-1; i >= 0; i--)
{
dt.Rows[i].Delete();
}
// Add rows back using the sorted view
for(int i = 0; i < defaultviewtable.Rows.Count; i++)
{
dt.Rows.Add(defaultviewtable.Rows[i].ItemArray);
}
I'm getting the data of my Datatable into a List but i need to get only the items of a matching date how can i do a Linq statement of my datatable to filter the data on the provided date?
My table Structure is taken from a stored procedure
This is my Code:
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand("JoinedRecords", conn);
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
DataTable myTable = new DataTable();
myTable.Load(cmd.ExecuteReader());
conn.Close();
for (var rowIndex = 0; rowIndex < myTable.Rows.Count; rowIndex++)
{
var row = myTable.Rows[rowIndex];
var rowValues = new List<string>();
foreach (DataColumn column in myTable.Columns)//Where column.Date.Day == 3
{
rowValues.Add(row[column].ToString());
}
var jsonRow = JsonConvert.SerializeObject(rowValues);
// Write current row
reader.Write(jsonRow);
// Add separating comma
if (rowIndex != myTable.Rows.Count - 1)
reader.WriteLine(",");
}
How can i do this?
There a data in my datatable that has datetime format
Can you try:
var myTable = new DataTable();
var rowValues = myTable.AsEnumerable().Where(r => r.Field<string>("Date") == "3").ToList();
And use a .Select() before the .ToList() to get what you want?
Hard to provide more with an example of the data you have.
var rowValues = new List<String>();
var value = from r in rowValues
where column.Date.Day == 3
select r;
Question edited
I have a datatablethat repeatedly fill by user selection (but the headers of datatable don't change) , using this code I add it's data to a datagridview but the problem is the header of datatable (at
least 50 header that I don't want to add them manually) do not add as well.
public static void GetSelectedFeed(Form2 frm2)
{
if (frm2.FeedSelectListBox.SelectedIndex != -1)
{
string StrCon = System.Configuration.ConfigurationManager.ConnectionStrings["FeedLibraryConnectionString"].ConnectionString;
OleDbConnection Connection = new OleDbConnection(StrCon);
OleDbDataAdapter DataA = new OleDbDataAdapter("Select * from FeedLibrary where ID =" + frm2.FeedSelectListBox.SelectedValue, Connection);
DataTable DTable = new DataTable();
DataA.Fill(DTable);
frm2.SelectedFeeddataGridView.ColumnCount = DTable.Columns.Count;
foreach (DataRow DR in DTable.Rows)
{
frm2.SelectedFeeddataGridView.Rows.Add(DR.ItemArray);
}
frm2.SelectedFeeddataGridView.ColumnHeadersVisible = true;
frm2.SelectedFeeddataGridView.Columns[0].Visible = true;
frm2.SelectedFeeddataGridView.Columns[1].Frozen = true;
frm2.SelectedFeeddataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
}
}
How could I programatically add headers of DataTable to dataGridView ?
this is how the headers of datatable should add to a datagridview
for (int k = 0; k < DTable.Columns.Count; k++)
{
frm2.SelectedFeeddataGridView.Columns.Add(DTable.Columns[k].ColumnName, DTable.Columns[k].Caption);
}
Up until now, I had a utility class that contained a function called "getTable", which took a string query and returned a datatable. Now I'm trying to get these queries to be returned via excel. Simply copying the contents of the datatable to excel works fine - however there's no header row on the spreadsheet to explain what each column is.
Below is my attempt:
public static DataTable getTable(String sql, bool includeHeaderRow)
{
DataTable table = new DataTable();
using (SqlDataAdapter adpt = new SqlDataAdapter(sql, getConn()))
{
adpt.Fill(table);
if (includeHeaderRow)
{
DataRow headerRow = table.NewRow();
for (int i = 0; i < table.Columns.Count; i++)
{
headerRow[i] = table.Columns[i].ColumnName;
}
table.Rows.InsertAt(headerRow, 0);
}
}
return table;
}
The above almost works, but an exception is thrown when I try and write a column name (obviously a string) into a non-string column of the datatable.
Any ideas for an easy way to achieve this?
Of course the code may give error, because as you told you are assigning none compatible datatypes into one column with specific datatype, columns at Datatable accepts specific datatypes now if you try to change the column datatype to object by creating a copy of table(cloning it) I think the problem will fix:
public static DataTable getTable(String sql, bool includeHeaderRow)
{
DataTable table = new DataTable();
using (SqlDataAdapter adpt = new SqlDataAdapter(sql, getConn()))
{
adpt.Fill(table);
if (includeHeaderRow)
{
DataTable dt = table.Clone();
for (int i = 0; i < table.Columns.Count; i++)
{
dt.Columns[i].DataType = typeof(Object);
}
foreach (DataRow row in table.Rows)
{
dt.ImportRow(row);
}
DataRow headerRow = dt.NewRow();
for (int i = 0; i < table.Columns.Count; i++)
{
headerRow[i] = table.Columns[i].ColumnName;
}
dt.Rows.InsertAt(headerRow, 0);
}
}
return dt;
}
So I had 3 sqlite tables named abc, t2, and t3. I wanted to merge all three of them into one datagrid. By this I mean, first abc comes, then below it should be t2, then below that t3.
This was my original code for showing only table abc in the datagrid view:
string sql = " SELECT * FROM abc";
SQLiteDataAdapter da;
DataTable dt;
sqlite_cmd.CommandText = sql;
//Create New Datatable to fill with data
dt = new DataTable();
//Create DataAdapter to fill data in DataTable via Adapter
da = new SQLiteDataAdapter(sql, sqlite_conn);
da.Fill(dt);
// Lets populate the datagrid
dataGridView1.DataSource = dt;
dataGridView1.Refresh();
The code below is what a user suggested I should use to merge all 3 tables into 1 datagrid view. Given my lack of programming knowledge, I didn't know how to synchronize his answer with my code above. The error I was getting from his code is that the name 'abc', 't2', and 't3' don't exist in the current context.(most likely because they dont have any sqlite statements a
The goal here is to merge 3 tables into 1 data grid view. The error above is preventing me from doing so. An answer in full code would be appreciated.
DataTable allDTs = abc;
int rowCount = allDTs.Rows.Count - 1;
foreach (DataRow row in t2.Rows)
{
rowCount = rowCount + 1;
allDTs.Rows.Add();
int colCount = -1;
foreach (DataColumn col in t2.Columns)
{
colCount = colCount + 1;
if (colCount > allDTs.Columns.Count - 1) allDTs.Columns.Add(col.ColumnName);
allDTs.Rows[rowCount][colCount] = row[col];
}
}
rowCount = allDTs.Rows.Count - 1;
foreach (DataRow row in t3.Rows)
{
rowCount = rowCount + 1;
allDTs.Rows.Add();
int colCount = -1;
foreach (DataColumn col in t3.Columns)
{
colCount = colCount + 1;
if (colCount > allDTs.Columns.Count - 1) allDTs.Columns.Add(col.ColumnName);
allDTs.Rows[rowCount][colCount] = row[col];
}
}
dataGridView1.DataSource = allDTs;