ID Name Value
......................
1 aa 123
2 bb 123
3 cd 123
Wanted to remove column "value" which has all the row values equal to 123 from Dataset using linq
If you want to delet the whole column if all values are the same use Enumerable.All, for example in:
foreach(DataTable dt in ds.Tables)
{
if(dt.Rows.Count > 0 && dt.Columns.Contains("Value") && dt.Columns["Value"].DataType == typeof(int))
{
int firstValue = dt.Rows[0].Field<int>("Value");
if(dt.AsEnumerable().Skip(1).All(r => r.Field<int>("Value") == firstValue))
{
dt.Columns.Remove("Value");
}
}
}
Update: "wanted to find and delete the column were all the values are same in that column."
Then you just have to generalize above code:
foreach (DataTable dt in ds.Tables)
{
List<DataColumn> columnsToDelete = new List<DataColumn>();
foreach (DataColumn col in dt.Columns)
{
object first = dt.Rows[0][col];
if (dt.AsEnumerable().Skip(1).All(r => r[col].Equals(first)))
{
columnsToDelete.Add(col);
}
}
foreach (DataColumn colToRemove in columnsToDelete)
dt.Columns.Remove(colToRemove);
}
Here return in list of datarow
ds.Tables["tableName"].AsEnumerable().Where(g => g.Field<Int32>("Value") != 123).ToList<DataRow>();
Worked with the solution given by SLaks https://stackoverflow.com/a/1766950/848286
foreach (var column in ds.Tables[0].Columns.Cast<DataColumn>().ToArray())
{
if (ds.Tables[0].AsEnumerable().All(dr => dr.IsNull(column)))
{
ds.Tables[0].Columns.Remove(column);
}
}
Related
I have a datatable as below
StudentID Marks
AAA NULL
AAA 100
BBB 200
I have to remove the row from datatable by checking studentID in a condition that
If there are same studentID then remove row with NULL value and display only student id with value.
If both marks are NULL of that student then show only one row.
Resulted Datatable should be
StudentID Marks
AAA 100
BBB 200
I have tried to remove duplicate rows from above table using below function
public DataTable RemoveDuplicateRows(DataTable dTable, string colName)
{
Hashtable hTable = new Hashtable();
ArrayList duplicateList = new ArrayList();
//Add list of all the unique item value to hashtable, which stores combination of key, value pair.
//And add duplicate item value in arraylist.
foreach (DataRow drow in dTable.Rows)
{
if (hTable.Contains(drow[colName])&& drow["Marks"]==null)
{
duplicateList.Add(drow);
}
else
{
hTable.Add(drow[colName], string.Empty);
}
}
//Removing a list of duplicate items from datatable.
foreach (DataRow dRow in duplicateList)
dTable.Rows.Remove(dRow);
//Datatable which contains unique records will be return as output.
return dTable;
}
DataTable datatabble = new DataTable();
datatabble.Columns.Add("studentid", typeof(string));
datatabble.Columns.Add("marks", typeof(int));
datatabble.Rows.Add("AAA");
datatabble.Rows.Add("AAA",100);
datatabble.Rows.Add("BBB",200);
var duplicates = datatabble.AsEnumerable().GroupBy(r => r[0]).Where(gr => gr.Count() > 1)
.Select(dupl => dupl.Key).ToList();
var result = datatabble.AsEnumerable().Where(x =>
(
(duplicates.Contains(x[0]) && !string.IsNullOrEmpty(x[1].ToString()))
|| !duplicates.Contains(x[0])
)
).ToList();
Output: You can see output with 2 row count with filtered null value.
I have two datatables:
1.dtEmployee:
|agent_id|agent_name|sum|
2.dtReport:
|sale_date|agent_id|sum |
------------------------
For each record in dtReport I need to find agent_id in dtEmployee and add the value of dtReport["sum"] to dtEmployee["sum"]:
foreach (DataRow r in dtReport)
{
DataRow empRow = dtEmployee.find(dtReport["agent_id"]);
empRow["sum"] += r["sum"];
}
Is there a way that would allow me to accomplish this?
Something like this works:
private void AddValue(string agent_id, decimal sum)
{
DataRow[] row= dtEmployee.Select("agent_id= '"+agent_id+"'");
//since only one record with this agent_id, we take first record of array -> row[0]
decimal dSum= Convert.ToDecimal(row[0][column]);
dSum+= sum;
row[0]["sum"] = dSum;
}
and insert this function into loop:
foreach (DataRow r in dtReport)
{
AddValue(r["agent_id"], r["sum"]);
}
This can be achieved in many ways.
Option 1 :
foreach(DataRow row in dtEmployee.Rows)
{
var update = dtReport.AsEnumerable().FirstOrDefault(r => r.Field<string>("agent_id") == row.Field<string>("agent_id"));
if(update !=null)
row.SetField<float>("sum", update.Field<float>("sum"));
}
Option 2
Another option would be creating new table by joining DataTables
var results = from t1 in dtEmployee.AsEnumerable()
join t2 in dtReport.AsEnumerable()
on t1.Field<int>("agent_id") equals t2.Field<int>("agent_id")
select new { t1, t2 };
// Now we can construct new DataTable
DataTable result = new DataTable() ;
result.Columns.Add("agent_id", typeof(System.Int32));
result.Columns.Add("Name", typeof(System.String));
result.Columns.Add("sum", typeof(float));
foreach(var dr in results )
{
DataRow newRow = results.NewRow();
newRow["agent_id"] = dr.t1.Field<int>("agent_id");
newRow["agent_name"] = dr.t1.Field<string>("agent_name");
newRow["sum"] = dr.t2.Field<float>("sum");
// When all columns have been filled in then add the row to the table
results.Rows.Add(newRow);
}
Working sample
Hope this helps !
You could try something like this. Given that your agent_id and sum are integer.
foreach (DataRow r in dtReport.Rows)
{
dtEmployee.Select(string.Format("agent_id = {0}", r["agent_id"])).ToList<DataRow>().ForEach(
v => { v["sum"] = (v.IsNull("sum") ? 0 : v.Field<int>("sum")) + (r.IsNull("sum") ? 0 : r.Field<int>("sum")); });
}
Or equivalent code
foreach (DataRow r in dtReport.Rows)
{
DataRow[] empRow = dtEmployee.Select("agent_id = " + r["agent_id"]);
for (int i = 0; i < empRow.Length; i++)
{
empRow[i]["sum"] = (empRow[i].IsNull("sum") ? 0 : (int)empRow[i]["sum"]) + (r.IsNull("sum") ? 0 : (int)r["sum"]);
}
}
I have a DataTable dt where I have a string column Salenumber.
I need to remove the row where the Salenumber is between 1 - 5999 and move that row to DataTable dt2.
Something like this, but foreach wont work when you want to remove rows.
DataTable dt2 = new DataTable();
dt2 = CreateNewDataTable.NewDataTable();
foreach (DataRow row in dt.Rows)
{
double RowDoubleValue;
if (Double.TryParse(row["Salenumber"].ToString(), out RowDoubleValue) && RowDoubleValue >= 1.0 && RowDoubleValue <= 5999.0)
{
dt2.ImportRow(row); //Copy
dt.Rows.Remove(row); //Remove
}
}
One way to circumvent the problem that you cant modify a collection during enumeration in a foreach is to use another collection where you store the items that you want to modify, so like:
List<DataRow> rowsToRemove = new List<DataRow>();
foreach (DataRow row in dt.Rows)
{
double RowDoubleValue;
if (Double.TryParse(row["Salenumber"].ToString(), out RowDoubleValue) && RowDoubleValue >= 1.0 && RowDoubleValue <= 5999.0)
{
rowsToRemove.Add(row);
}
}
foreach(DataRow row in rowsToRemove)
{
dt2.ImportRow(row); //Copy
dt.Rows.Remove(row); //Remove
}
Another more readable and shorter way is LINQ:
var rowsToImport = from row in dt.AsEnumerable()
let salesNumDouble = row.Field<string>("Salenumber").TryGetDouble()
where salesNumDouble.HasValue
&& salesNumDouble.Value >= 1.0 && salesNumDouble.Value <= 5999.0
select row;
DataTable dt2 = rowsToImport.CopyToDataTable();
I've used this extension to try-parse a string to double?:
public static Double? TryGetDouble(this string item, IFormatProvider formatProvider = null)
{
if (formatProvider == null) formatProvider = NumberFormatInfo.CurrentInfo;
Double d = 0d;
bool success = Double.TryParse(item, NumberStyles.Any, formatProvider, out d);
if (success)
return d;
else
return null;
}
You shouldn't modify collection in foreach process, you can use DataTable.Select for simple solution
DataTable dt;
DataTable dt2;
var rows = dt.Select("Salenumber >=1 and Salenumber<5999");
foreach (var row in rows)
{
dt.Rows.Remove(row);
}
dt2.Rows.Add(rows);
I have DataTable which I add Columns and Rows from database. Problem is I have one cell which has multiples record like province can be multiples in database. So I need to create multiple records in one cell of province. My code is
foreach (var item in attributes)
{
table.Columns.Add(item.name);
//column add
}
foreach (var item in forms)
{
string FormId = Convert.ToString(item);
var row = table.NewRow();
row["Form Id"] = FormId;
foreach (var itemdata in attributes)
{
var value = attributesData.FirstOrDefault(t => t.attributeName == itemdata.name && t.strFormId == FormId);
if (value != null && String.IsNullOrWhiteSpace(value.strFormId) == false )
{
row[itemdata.name] = value.strValue;
//row add
}
}
table.Rows.Add(row);
}
gvView.DataSource = table;
I bind this with my GridView. How to break one cell with mutliples records please help.
How can I get a sum for all the columns in a datatable? Say I had the following table. How can I calculate the "total" row? It should be easy to add total row to a datatable.
Columns hits uniques sigups, etc...
Rows
1 12 1 23
2 1 0 5
3 6 2 9
total 19 3 37
Update
I ended up with this. It was the only thing I could get to work.
For Each col As DataColumn In TotalsTable.Columns
If col.DataType.Name = "DateTime" Then
count = count + 1
Continue For
End If
Dim colTotal As Double = 0
Dim value As Double
For Each row As DataRow In TotalsTable.Rows
If Double.TryParse(row(col), value) Then
colTotal += Double.Parse(row(col))
End If
Next
totalRow(count) = colTotal
count = count + 1
Next
There is also a way to do this without loops using the DataTable.Compute Method. The following example comes from that page. You can see that the code used is pretty simple.:
private void ComputeBySalesSalesID(DataSet dataSet)
{
// Presumes a DataTable named "Orders" that has a column named "Total."
DataTable table;
table = dataSet.Tables["Orders"];
// Declare an object variable.
object sumObject;
sumObject = table.Compute("Sum(Total)", "EmpID = 5");
}
I must add that if you do not need to filter the results, you can always pass an empty string:
sumObject = table.Compute("Sum(Total)", "")
Try this:
DataTable dt = new DataTable();
int sum = 0;
foreach (DataRow dr in dt.Rows)
{
foreach (DataColumn dc in dt.Columns)
{
sum += (int)dr[dc];
}
}
I doubt that this is what you want but your question is a little bit vague
Dim totalCount As Int32 = DataTable1.Columns.Count * DataTable1.Rows.Count
If all your columns are numeric-columns you might want this:
You could use DataTable.Compute to Sum all values in the column.
Dim totalCount As Double
For Each col As DataColumn In DataTable1.Columns
totalCount += Double.Parse(DataTable1.Compute(String.Format("SUM({0})", col.ColumnName), Nothing).ToString)
Next
After you've edited your question and added more informations, this should work:
Dim totalRow = DataTable1.NewRow
For Each col As DataColumn In DataTable1.Columns
totalRow(col.ColumnName) = Double.Parse(DataTable1.Compute("SUM(" & col.ColumnName & ")", Nothing).ToString)
Next
DataTable1.Rows.Add(totalRow)
You can loop through the DataColumn and DataRow collections in your DataTable:
// Sum rows.
foreach (DataRow row in dt.Rows) {
int rowTotal = 0;
foreach (DataColumn col in row.Table.Columns) {
Console.WriteLine(row[col]);
rowTotal += Int32.Parse(row[col].ToString());
}
Console.WriteLine("row total: {0}", rowTotal);
}
// Sum columns.
foreach (DataColumn col in dt.Columns) {
int colTotal = 0;
foreach (DataRow row in col.Table.Rows) {
Console.WriteLine(row[col]);
colTotal += Int32.Parse(row[col].ToString());
}
Console.WriteLine("column total: {0}", colTotal);
}
Beware: The code above does not do any sort of checking before casting an object to an int.
EDIT: add a DataRow displaying the column sums
Try this to create a new row to display your column sums:
DataRow totalsRow = dt.NewRow();
foreach (DataColumn col in dt.Columns) {
int colTotal = 0;
foreach (DataRow row in col.Table.Rows) {
colTotal += Int32.Parse(row[col].ToString());
}
totalsRow[col.ColumnName] = colTotal;
}
dt.Rows.Add(totalsRow);
This approach is fine if the data type of any of your DataTable's DataRows are non-numeric or if you want to inspect the value of each cell as you sum. Otherwise I believe #Tim's response using DataTable.Compute is a better.
It's a pity to use .NET and not use collections and lambda to save your time and code lines
This is an example of how this works:
Transform yourDataTable to Enumerable, filter it if you want , according a "FILTER_ROWS_FIELD" column, and if you want, group your data by a "A_GROUP_BY_FIELD".
Then get the count, the sum, or whatever you wish.
If you want a count and a sum without grouby don't group the data
var groupedData = from b in yourDataTable.AsEnumerable().Where(r=>r.Field<int>("FILTER_ROWS_FIELD").Equals(9999))
group b by b.Field<string>("A_GROUP_BY_FIELD") into g
select new
{
tag = g.Key,
count = g.Count(),
sum = g.Sum(c => c.Field<double>("rvMoney"))
};
for (int i=0;i<=dtB.Columns.Count-1;i++)
{
array(0, i) = dtB.Compute("SUM([" & dtB.Columns(i).ColumnName & "])", "")
}