I have a datatable and I'm trying to select some of the rows from the datatable.
It works well for PracticeIDs 1 & 37, but for some reason, when it gets to the last row of the data(ID 7), it doesn't pull up the record from the datatable.
Any ideas?
//create datatable
DataTable dt = new DataTable();
dt.Columns.Add("PracticeID");
dt.Columns.Add("AuthorID");
//add data(in real code, this is pulled from the database)
dt.Rows.Add(1, 87);
dt.Rows.Add(37, 202);
dt.Rows.Add(1, 268);
dt.Rows.Add(7, 262);
//get distinct practiceids into datatable
DataView dv = new DataView(dt);
DataTable dtDistinctIDs = dv.ToTable(true, "PracticeID");
//for each practice, get a list of the authors
foreach (DataRow practiceRow in dtDistinctIDs.Rows)
{
DataRow[] dra = dt.Select("PracticeID = " + practiceRow["PracticeID"].ToString());
}
This was hard to spot, as this behaviour seems counterintuitive. The problem you are experimenting is derived of the columns not having a datatype. I now can't explain it exactly, but try to change your code to the following and it would work as expected:
DataTable dt = new DataTable();
dt.Columns.Add("PracticeID",typeof(int)); //THIS IS THE IMPORTANT BIT
dt.Columns.Add("AuthorID");
//add data(in real code, this is pulled from the database)
dt.Rows.Add(1, 87);
dt.Rows.Add(37, 202);
dt.Rows.Add(1, 268);
dt.Rows.Add(7, 262);
//get distinct practiceids into datatable
DataView dv = new DataView(dt);
DataTable dtDistinctIDs = dv.ToTable(true, "PracticeID");
//for each practice, get a list of the authors
foreach (DataRow practiceRow in dtDistinctIDs.Rows)
{
DataRow[] dra = dt.Select("PracticeID = " + (int)practiceRow["PracticeID"]);
}
EDIT:
In fact I was wrong and it was simpler. The real problem was with your Select not having ' surrounding the field, as by default the DataColumn is string. So, using your original code, just changing the following should work:
DataRow[] dra = dt.Select("PracticeID = '" + practiceRow["PracticeID"].ToString() + "'");
Related
I have correct source DataTable "sourceDataTable" and I call method to split it into several and store the result into DataSet "ds":
DataSet ds = MyClass.SplitDataTables(sourceDataTable);
Here is the method MyClass.SplitDataTables():
public static DataSet SplitDataTables(DataTable sourceDataTable)
{
using (DataSet dsOut = new DataSet())
{
DataTable dt1 = new DataTable;
DataTable dt2 = new DataTable;
DataTable dt3 = new DataTable;
dt1 = sourceDataTable.Clone();
dt2 = sourceDataTable.Clone();
dt3 = sourceDataTable.Clone();
foreach (DataRow row in sourceDataTable.Rows)
{
//column is for example "City" and some row has "Boston" in it, so I put this row into dt1
if (row["ColumnName"].ToString() == "something")
{
dt1.ImportRow(row);
}
else if (...)
{ } //for other DataTables dt2, dt3, etc...
else .......... ;
}
//here I put resulting DataTables into one DataSet which is returned
string[] cols= { "dt1", "dt2", "dt3" };
foreach (string col in cols)
{
dsOut.Tables.Add(col);
}
return dsOut;
}
}
So with this returned DataSet I display new Windows each with one DataTable
foreach (DataTable dtt in ds.Tables)
{
string msg = dtt.TableName;
Window2 win2 = new Window2(dtt, msg);
win2.Show();
}
All I get shown is Windows with placeholder for "empty DataGrid"
Windows code is correct, as it works whith "unsplit DataTable".
I assume code in splitting DataTables is all wrong as it does not output DataSet with filled DataTables. I will greatly appreciate any help on this issue. Thank you!
You don't need a for loop here
Replace below code
string[] cols= { "dt1", "dt2", "dt3" };
foreach (string col in cols)
{
dsOut.Tables.Add(col);
}
With this
dsOut.Tables.Add(dt1);
dsOut.Tables.Add(dt2);
dsOut.Tables.Add(dt3);
Thanks to #Krishna I got this solved. So if you ever encounter similar problem here are 2 things to note:
string[] cols = { "dt1", "dt2", "dt3", ... };
foreach (string col in cols)
{
dsOut.Tables.Add(col);
}
This cycle does not have access to objects of DataTables with same name and writes only empty DataTables into DataSet collection (regardless of same name!).
If you create new DataTable and you will be making it a clone of another DataTable, dont bother yet with setting its name.
DataTable dt1 = new DataTable();
Make new DataTable of same format as source DataTable:
dt1 = sourceDataTable.Clone();
dt2 = sourceDataTable.Clone();
//etc...
Now you have to set unique DataTable names to each DataTable cloned from source DataTable:
dt1.TableName = "Name1";
dt2.TableName = "Name2";
//and so on
Now all works as intended.
Here is my code, I am trying to display multiplication of Rate * Supply column values and assigning it to the Amount column in data grid view :
try
{
Query = "Select id,Code,Description,Rate,Cust_Id,Supply,Empty,Amount,Received from Items ";
adap = new SQLiteDataAdapter(Query, GlobalVars.conn);
ds = new DataSet();
adap.Fill(ds, "Items");
dtgVOuchers.DataSource = ds.Tables[0];
ds.Tables[0].Columns["Amount"].DefaultValue = (ds.Tables[0].Columns["Rate"].DefaultValue) * (ds.Tables[0].Columns["Supply"].DefaultValue); //error
//dtgVOuchers.Rows.Clear();
ds.Tables[0].Clear();
dtgVOuchers.Refresh();
}
Does anyone know how I can accomplish this functionality in data grid view ? . .Please help me to correct this code. Thanks
just use the query
Select id,Code,Description,Rate,Cust_Id,Supply,Empty,isnull(Rate,0)*isnull(Supply,0) as [Amount],Received from Items
DataTable myDataTable = new DataTable();
DataColumn quantityColumn = new DataColumn("Quantity");
DataColumn rateColumn = new DataColumn("Rate");
DataColumn priceColumn = new DataColumn ("Price");
quantityColumn.DataType = typeof(int);
rateColumn.DataType = typeof(int);
myDataTable.Columns.Add(quantityColumn);
myDataTable.Columns.Add(rateColumn);
myDataTable.Columns.Add(priceColumn);
//Set the Expression here
priceColumn.Expression = "Quantity * Rate";
foreach (DataGridViewRow row in dtgVOuchers.Rows)
{
row.Cells[dtgVOuchers.Columns["Amount"].Index].Value = (Convert.ToDouble(row.Cells[dtgVOuchers.Columns["Rate"].Index].Value) * Convert.ToDouble(row.Cells[dtgVOuchers.Columns["Supply"].Index].Value));
}
Use the below code..run a loop to update the Amount column in all rows
Note : Though this method is not preferred as it effects performance.So do this calculation in the sql query.I dont understand the reason behind not doing the munltiplication in SQL query..
foreach (DataRow row in ds.Tables[0].Rows)
{
row["Amount"]= Convert.ToDecimal(row["Rate"])* Convert.ToDecimal(row["Supply"]);
ds.Tables[0].AcceptChanges();
}
dtgVOuchers.DataSource = ds.Tables[0];
dtgVOuchers.Refresh();
We have two columns in a DataTable, like so:
COL1 COL2
Abc 5
Def 8
Ghi 3
We're trying to sort this datatable based on COL2 in decreasing order.
COL1 COL2
ghi 8
abc 4
def 3
jkl 1
We tried this:
ft.DefaultView.Sort = "COL2 desc";
ft = ft.DefaultView.ToTable(true);
but, without using a DataView, we want to sort the DataTable itself, not the DataView.
I'm afraid you can't easily do an in-place sort of a DataTable like it sounds like you want to do.
What you can do is create a new DataTable from a DataView that you create from your original DataTable. Apply whatever sorts and/or filters you want on the DataView and then create a new DataTable from the DataView using the DataView.ToTable method:
DataView dv = ft.DefaultView;
dv.Sort = "occr desc";
DataTable sortedDT = dv.ToTable();
This will help you...
DataTable dt = new DataTable();
dt.DefaultView.Sort = "Column_name desc";
dt = dt.DefaultView.ToTable();
Its Simple Use .Select function.
DataRow[] foundRows=table.Select("Date = '1/31/1979' or OrderID = 2", "CompanyName ASC");
DataTable dt = foundRows.CopyToDataTable();
And it's done......Happy Coding
Maybe the following can help:
DataRow[] dataRows = table.Select().OrderBy(u => u["EmailId"]).ToArray();
Here, you can use other Lambda expression queries too.
Or, if you can use a DataGridView, you could just call Sort(column, direction):
namespace Sorter
{
using System;
using System.ComponentModel;
using System.Windows.Forms;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.Rows.Add("Abc", 5);
this.dataGridView1.Rows.Add("Def", 8);
this.dataGridView1.Rows.Add("Ghi", 3);
this.dataGridView1.Sort(this.dataGridView1.Columns[1],
ListSortDirection.Ascending);
}
}
}
Which would give you the desired result:
Did you try using the Select(filterExpression, sortOrder) method on DataTable? See here for an example. Note this method will not sort the data table in place, if that is what you are looking for, but it will return a sorted array of rows without using a data view.
table.DefaultView.Sort = "[occr] DESC";
Use LINQ - The beauty of C#
DataTable newDataTable = baseTable.AsEnumerable()
.OrderBy(r=> r.Field<int>("ColumnName"))
.CopyToDataTable();
There is 2 way for sort data
1) sorting just data and fill into grid:
DataGridView datagridview1 = new DataGridView(); // for show data
DataTable dt1 = new DataTable(); // have data
DataTable dt2 = new DataTable(); // temp data table
DataRow[] dra = dt1.Select("", "ID DESC");
if (dra.Length > 0)
dt2 = dra.CopyToDataTable();
datagridview1.DataSource = dt2;
2) sort default view that is like of sort with grid column header:
DataGridView datagridview1 = new DataGridView(); // for show data
DataTable dt1 = new DataTable(); // have data
dt1.DefaultView.Sort = "ID DESC";
datagridview1.DataSource = dt1;
It turns out there is a special case where this can be achieved. The trick is when building the DataTable, collect all the rows in a list, sort them, then add them. This case just came up here.
//Hope This will help you..
DataTable table = new DataTable();
//DataRow[] rowArray = dataTable.Select();
table = dataTable.Clone();
for (int i = dataTable.Rows.Count - 1; i >= 0; i--)
{
table.ImportRow(dataTable.Rows[i]);
}
return table;
TL;DR
use tableObject.Select(queryExpression, sortOrderExpression) to select data in sorted manner
Complete example
Complete working example - can be tested in a console application:
using System;
using System.Data;
namespace A
{
class Program
{
static void Main(string[] args)
{
DataTable table = new DataTable("Orders");
table.Columns.Add("OrderID", typeof(Int32));
table.Columns.Add("OrderQuantity", typeof(Int32));
table.Columns.Add("CompanyName", typeof(string));
table.Columns.Add("Date", typeof(DateTime));
DataRow newRow = table.NewRow();
newRow["OrderID"] = 1;
newRow["OrderQuantity"] = 3;
newRow["CompanyName"] = "NewCompanyName";
newRow["Date"] = "1979, 1, 31";
// Add the row to the rows collection.
table.Rows.Add(newRow);
DataRow newRow2 = table.NewRow();
newRow2["OrderID"] = 2;
newRow2["OrderQuantity"] = 2;
newRow2["CompanyName"] = "NewCompanyName1";
table.Rows.Add(newRow2);
DataRow newRow3 = table.NewRow();
newRow3["OrderID"] = 3;
newRow3["OrderQuantity"] = 2;
newRow3["CompanyName"] = "NewCompanyName2";
table.Rows.Add(newRow3);
DataRow[] foundRows;
Console.WriteLine("Original table's CompanyNames");
Console.WriteLine("************************************");
foundRows = table.Select();
// Print column 0 of each returned row.
for (int i = 0; i < foundRows.Length; i++)
Console.WriteLine(foundRows[i][2]);
// Presuming the DataTable has a column named Date.
string expression = "Date = '1/31/1979' or OrderID = 2";
// string expression = "OrderQuantity = 2 and OrderID = 2";
// Sort descending by column named CompanyName.
string sortOrder = "CompanyName ASC";
Console.WriteLine("\nCompanyNames data for Date = '1/31/1979' or OrderID = 2, sorted CompanyName ASC");
Console.WriteLine("************************************");
// Use the Select method to find all rows matching the filter.
foundRows = table.Select(expression, sortOrder);
// Print column 0 of each returned row.
for (int i = 0; i < foundRows.Length; i++)
Console.WriteLine(foundRows[i][2]);
Console.ReadKey();
}
}
}
Output
try this:
DataTable DT = new DataTable();
DataTable sortedDT = DT;
sortedDT.Clear();
foreach (DataRow row in DT.Select("", "DiffTotal desc"))
{
sortedDT.NewRow();
sortedDT.Rows.Add(row);
}
DT = sortedDT;
Yes the above answers describing the corect way to sort datatable
DataView dv = ft.DefaultView;
dv.Sort = "occr desc";
DataTable sortedDT = dv.ToTable();
But in addition to this, to select particular row in it you can use LINQ and try following
var Temp = MyDataSet.Tables[0].AsEnumerable().Take(1).CopyToDataTable();
I want to convert dataview rowfilter value to datatable. I have a dataset with value. Now i was filter the value using dataview. Now i want to convert dataview filter values to datatable.please help me to copy it........
My partial code is here:
DataSet5TableAdapters.sp_getallempleaveTableAdapter TA = new DataSet5TableAdapters.sp_getallempleaveTableAdapter();
DataSet5.sp_getallempleaveDataTable DS = TA.GetData();
if (DS.Rows.Count > 0)
{
DataView datavw = new DataView();
datavw = DS.DefaultView;
datavw.RowFilter = "fldempid='" + txtempid.Text + "' and fldempname='" + txtempname.Text + "'";
if (datavw.Count > 0)
{
DT = datavw.Table; // i want to copy dataview row filter value to datatable
}
}
please help me...
You can use
if (datavw.Count > 0)
{
DT = datavw.ToTable(); // This will copy dataview's RowFilterd values to datatable
}
You can use DateView.ToTable() for converting the filtered dataview in to a datatable.
DataTable DTb = new DataTable();
DTb = SortView.ToTable();
The answer does not work for my situation because I have columns with expressions. DataView.ToTable() will only copy the values, not the expressions.
First I tried this:
//clone the source table
DataTable filtered = dt.Clone();
//fill the clone with the filtered rows
foreach (DataRowView drv in dt.DefaultView)
{
filtered.Rows.Add(drv.Row.ItemArray);
}
dt = filtered;
but that solution was very slow, even for just 1000 rows.
The solution that worked for me is:
//create a DataTable from the filtered DataView
DataTable filtered = dt.DefaultView.ToTable();
//loop through the columns of the source table and copy the expression to the new table
foreach (DataColumn dc in dt.Columns)
{
if (dc.Expression != "")
{
filtered.Columns[dc.ColumnName].Expression = dc.Expression;
}
}
dt = filtered;
The below code is for Row filter from Dataview and the result converted in DataTable
itemCondView.RowFilter = "DeliveryNumber = '1001'";
dataSet = new DataSet();
dataSet.Tables.Add(itemCondView.ToTable());
my datatable;
dtData
ID | ID2
--------
1 | 2
1 | 3
dtData.Select("ID = 1"); one more rows;
i want row "ID = 1 And ID2 = 3" how to make ?
Do you mean like this?:
dtData.Select("ID=1 AND ID2=3");
Okay, here is how I do such things...
GridFieldDAO dao = new GridFieldDAO();
//Load My DataTable
DataTable dt = dao.getDT();
//Get My rows based off selection criteria
DataRow[] drs = dt.Select("(detailID = 1) AND (detailTypeID = 2)");
//make a new "results" datatable via clone to keep structure
DataTable dt2 = dt.Clone();
//Import the Rows
foreach (DataRow d in drs)
{
dt2.ImportRow(d);
}
//Bind to my new DataTable and it will only show rows based off selection
//criteria
myGrid.DataSource = dt2;
myGrid.DataBind();
Notice in my Select() I put the criteria in Parens between AND and OR
Hope this helps!
Mike V
Better use this :
GridFieldDAO dao = new GridFieldDAO();
//Load My DataTable
DataTable dt = dao.getDT();
//Get My rows based off selection criteria and copy them directly to datatable
DataTable dt2 = dt.Select("(detailID = 1) AND (detailTypeID = 2)").CopyToDataTable();
DataTable dt2 = dt.Select("ID = 1").CopyToDataTable;
make sure dt has rows in it
Here you can copy your contents to another DataTable by using CopyToDataTable method of Linq while selecting the specific rows by filtering.
DataTable dt2 = dt.Select("state = 'FL' ").CopyToDataTable;
Great example and very helpful. Wanted to add one thing - if you need to select on a string use something like:
DataTable dt2 = dt.Select("state = 'FL' ");