How to Arrange DataRow Sequences in datatable? - c#

I have column in DataTable with RowsOrder postion?
In rowsorder postion data is-
Postion in Column:
1
1a
3
4
6
7
8
9
10
11
2a
11a
12
13a
14
5
2
12b
14c
abc
I want to show Postion
1
1a
2
2a
5
3
4
6
7
8
9
10
11
11a
12
12b
13a
14
14a
14c
.....
..
100
100a
101b
.....
1011a

Use IComparable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Text.RegularExpressions;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("AlphaNumeric", typeof(string));
dt.Rows.Add(new object[] { "1" });
dt.Rows.Add(new object[] { "1a" });
dt.Rows.Add(new object[] { "3" });
dt.Rows.Add(new object[] { "4" });
dt.Rows.Add(new object[] { "6" });
dt.Rows.Add(new object[] { "7" });
dt.Rows.Add(new object[] { "8" });
dt.Rows.Add(new object[] { "9" });
dt.Rows.Add(new object[] { "10" });
dt.Rows.Add(new object[] { "11" });
dt.Rows.Add(new object[] { "2a" });
dt.Rows.Add(new object[] { "11a" });
dt.Rows.Add(new object[] { "12" });
dt.Rows.Add(new object[] { "13a" });
dt.Rows.Add(new object[] { "14" });
dt.Rows.Add(new object[] { "5" });
dt.Rows.Add(new object[] { "2" });
dt.Rows.Add(new object[] { "12b" });
dt.Rows.Add(new object[] { "14c" });
dt.Rows.Add(new object[] { "abc" });
dt.Rows.Add(new object[] { "1011a" });
dt.Rows.Add(new object[] { "101b" });
dt.Rows.Add(new object[] { "100a" });
dt.Rows.Add(new object[] { "100" });
DataTable sorted = dt.AsEnumerable().OrderBy(x => new SortAlphaNumeric(x.Field<string>("AlphaNumeric"))).CopyToDataTable();
}
}
public class SortAlphaNumeric : IComparable<SortAlphaNumeric>
{
public int? number { get;set;}
public string alpha { get;set;}
public SortAlphaNumeric(string alphaNumeric)
{
string pattern = #"(?'number'\d*)(?'alpha'.*)";
Match match = Regex.Match(alphaNumeric, pattern);
string numberStr = match.Groups["number"].Value;
alpha = match.Groups["alpha"].Value;
if (numberStr.Length > 0)
{
number = (int?)int.Parse(numberStr);
}
}
public int CompareTo(SortAlphaNumeric other)
{
if (number == null)
{
if (other.number == null)
{
return alpha.CompareTo(other.alpha);
}
else
{
return 1 ; //other is greater than this
}
}
else
{
if (other.number == null)
{
return -1; //this is greater than other
}
else
{
if (this.number == other.number)
{
return this.alpha.CompareTo(other.alpha);
}
else
{
return ((int)this.number).CompareTo((int)other.number);
}
}
}
}
}
}

Related

Removing Primary Key and Joining Rows in Datatable

I'm trying to sort a DataTable to be able to get the best selling items by order in C#. The DataTable's fields are orderId, productId, size, and amount (amount = how much of it was bought). The current primary key in the table is comprised of orderId, productId, and size. I would like to get the best selling items by sorting the table in a way that would remove orderId, and have productId and size as the new primary key, and amount as the sum of all amount's for orders with this productId and size.
What would be the best way to do this? I'm attaching my current table data for reference. My table data for reference.
If anything is unclear please let me know, this is my first time using Stack Overflow.
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication20
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("orderid", typeof(int));
dt.Columns.Add("productid", typeof(int));
dt.Columns.Add("size", typeof(int));
dt.Columns.Add("amount", typeof(int));
dt.Rows.Add(new object[] { 1, 1, 38, 12 });
dt.Rows.Add(new object[] { 1, 1, 41, 6 });
dt.Rows.Add(new object[] { 1, 2, 36, 8 });
dt.Rows.Add(new object[] { 1, 2, 38, 5 });
dt.Rows.Add(new object[] { 1, 3, 46, 2 });
dt.Rows.Add(new object[] { 4, 3, 40, 7 });
dt.Rows.Add(new object[] { 8, 3, 40, 7 });
dt.Rows.Add(new object[] { 9, 2, 40, 9 });
dt.Rows.Add(new object[] { 12, 2, 37, 5 });
dt.Rows.Add(new object[] { 13, 2, 37, 4 });
dt.Rows.Add(new object[] { 14, 2, 38, 3 });
dt.Rows.Add(new object[] { 15, 3, 41, 4 });
dt.Rows.Add(new object[] { 16, 2, 36, 7 });
dt.Rows.Add(new object[] { 16, 3, 41, 5 });
dt.Rows.Add(new object[] { 17, 2, 38, 4 });
dt.Rows.Add(new object[] { 18, 3, 40, 3 });
dt.Rows.Add(new object[] { 19, 5, 38, 9 });
dt.Rows.Add(new object[] { 20, 2, 36, 2 });
dt.Rows.Add(new object[] { 21, 1, 40, 3 });
dt.Rows.Add(new object[] { 22, 1, 38, 8 });
dt.Rows.Add(new object[] { 23, 1, 40, 9 });
dt.Rows.Add(new object[] { 24, 2, 37, 1 });
dt.Rows.Add(new object[] { 25, 5, 39, 4 });
dt.Rows.Add(new object[] { 2034, 3, 40, 3 });
dt.Rows.Add(new object[] { 2035, 2, 37, 6 });
dt.Rows.Add(new object[] { 2035, 3, 40, 5 });
dt.Rows.Add(new object[] { 2036, 2, 36, 2 });
dt.Rows.Add(new object[] { 2037, 2, 37, 3 });
dt.Rows.Add(new object[] { 2037, 3, 41, 7 });
dt.Rows.Add(new object[] { 2038, 1, 39, 3 });
dt.Rows.Add(new object[] { 2038, 5, 37, 4 });
var results = dt.AsEnumerable()
.GroupBy(x => new { productid = x.Field<int>("productid"), size = x.Field<int>("size") })
.Select(x => new { productid = x.Key.productid, size = x.Key.size, count = x.Count(), total = x.Sum(y => y.Field<int>("amount")) })
.OrderByDescending(x => x.count)
.ToList();
}
}
}

C# SQL Query to return records and related records

I have a table as follows
I have a query that runs each day to find anything that's 5 days old or greater and has a status of "In Progress" and set the status to "Declined".
What I need to be able to do is also set the status to "Declined" for anything with a Linked_ID (child) where the ID (Parent) has been changed.
So in the table I already set ID 1 to "Declined" but I also need to set ID's 2,3,4,8 and 10 to "Declined"
Below is what I have so far, any support would be amazing and really helpful
var Process = from a in db.Table1
where a.Status == "In Progress" && a.Date_Created = DateTime.Now.AddDays(-5)
select a;
foreach (Table1 a in Process)
{
a.Status = "Declined";
}
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Declined declined = new Declined();
declined.Query(DateTime.Now.AddDays(1));
}
}
public class Declined
{
DataTable dt;
public Declined()
{
dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Status", typeof(string));
dt.Columns.Add("Date Created", typeof(DateTime));
dt.Columns.Add("Link_ID", typeof(int));
dt.Rows.Add(new object[] { 1, "In Progress", new DateTime(2020, 9, 25) });
dt.Rows.Add(new object[] { 2, "Completed", new DateTime(2020, 9, 28),1 });
dt.Rows.Add(new object[] { 3, "In Progress", new DateTime(2020, 9, 28),1 });
dt.Rows.Add(new object[] { 4, "In Progress", new DateTime(2020, 9, 28),1 });
dt.Rows.Add(new object[] { 5, "In Progress", new DateTime(2020, 9, 28),2 });
dt.Rows.Add(new object[] { 6, "In Progress", new DateTime(2020, 9, 28),3 });
dt.Rows.Add(new object[] { 7, "In Progress", new DateTime(2020, 9, 28) });
dt.Rows.Add(new object[] { 8, "In Progress", new DateTime(2020, 9, 28),1 });
dt.Rows.Add(new object[] { 9, "In Progress", new DateTime(2020, 9, 28) });
dt.Rows.Add(new object[] { 10, "In Progress", new DateTime(2020, 9, 28),1 });
}
public void Query(DateTime date)
{
List<DataRow> rows = dt.AsEnumerable().Where(x => (x.Field<string>("Status") == "In Progress") && (date.Date.Subtract(x.Field<DateTime>("Date Created")).Days > 5)).ToList();
foreach(DataRow row in rows)
{
if (rows.Count > 0) ChangeChildren_Recursive(row, row.Field<DateTime>("Date Created"));
}
}
public void ChangeChildren_Recursive(DataRow row, DateTime date)
{
int id = row.Field<int>("ID");
DateTime rowDate = row.Field<DateTime>("Date Created").Date;
string status = row.Field<string>("Status");
if((status == "In Progress") && (date != rowDate)) row["Status"] = "Declined";
List<DataRow> children = dt.AsEnumerable().Where(x => (x.Field<int?>("Link_ID") == id) && (x.Field<int?>("Link_ID") != null)).ToList();
foreach (DataRow childRow in children)
{
ChangeChildren_Recursive(childRow, date);
}
}
}
}

Sum Datatable values with same criteria

I have a data table and I need to merge the cells with the same values in the columns IPC and Second Best Issuer and sum the values in the columns Dirty value PC and Par Value LC. All the values are type string.
For example:
I'm a beginner with query and I'm looking for simple way to do this in C# with LINQ.
Thank You
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication11
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("IPC", typeof(int));
dt.Columns.Add("Dirty", typeof(int));
dt.Columns.Add("Second", typeof(string));
dt.Columns.Add("Par", typeof(int));
dt.Rows.Add(new object[] { 1, 5, "BB", 55 });
dt.Rows.Add(new object[] { 1, 4, "B", 30 });
dt.Rows.Add(new object[] { 2, 15, "AAA", 20 });
dt.Rows.Add(new object[] { 1, 10, "BB", 80 });
dt.Rows.Add(new object[] { 2, 20, "AA", 90 });
dt.Rows.Add(new object[] { 2, 30, "AAA", 50 });
dt.Rows.Add(new object[] { 1, 5, "B", 60 });
dt.Rows.Add(new object[] { 2, 15, "AA", 70 });
var groups = dt.AsEnumerable().GroupBy(x => new {ipc = x.Field<int>("IPC"), second = x.Field<string>("Second")}).ToList();
DataTable dtsum = dt.Clone();
foreach(var group in groups)
{
dtsum.Rows.Add(new object[] {group.Key.ipc, group.Sum(y => y.Field<int>("Dirty")), group.Key.second, group.Sum(y => y.Field<int>("Par"))});
}
}
}
}

Compare each row of two identical Datatables for changed values C#

I need to compare two datatables which are having same schema and move the differences into another datatable. Below is my code which is not working fine:
DataTable dt1 = new DataTable("TableChanged");
dt1.Columns.Add("StateID",typeof(int));
dt1.Columns.Add("StateInitial");
dt1.Columns.Add("IsActive");
dt1.Rows.Add(new object[] { 10, "GA", 1 });
dt1.Rows.Add(new object[] { 11, "HI", 0 });
dt1.Rows.Add(new object[] { 12, "ID", 1 });
dt1.Rows.Add(new object[] { 13, "IL", 1 });
dt1.Rows.Add(new object[] { 14, "IN", 0 });
dt1.Rows.Add(new object[] { 15, "IA", 1 });
dt1.Rows.Add(new object[] { 23, "MN", 0 });
DataTable dt2 = new DataTable("TableOriginal");
dt2.Columns.Add("StateID", typeof(int));
dt2.Columns.Add("StateInitial");
dt2.Columns.Add("IsActive");
dt2.Rows.Add(new object[] { 10, "GA", 1 });
dt2.Rows.Add(new object[] { 11, "HI", 1 });
dt2.Rows.Add(new object[] { 12, "ID", 1 });
dt2.Rows.Add(new object[] { 13, "IL", 0 });
dt2.Rows.Add(new object[] { 14, "IN", 1 });
dt2.Rows.Add(new object[] { 15, "IA", 1 });
dt2.Rows.Add(new object[] { 23, "MN", 1 });
var matched = from table1 in dt1.AsEnumerable()
join table2 in dt2.AsEnumerable() on table1.Field<int>("StateID") equals table2.Field<int>("StateID")
//where table1.Field<object>("IsActive") == "0"
where table1.Field<string>("StateInitial") == table2.Field<string>("StateInitial") || table1.Field<object>("IsActive") == table2.Field<object>("IsActive")
select table1;
var missing = from table1 in dt1.AsEnumerable()
where !matched.Contains(table1)
select table1;
After comparison, I want result like:
StateID|StateInitial|IsActive
11 "HI" 0
13 "IL" 1
14 "IN" 0
23 "MN" 0
You can use DataRowComparer.Default, which compares every field of a DataRow, for the LINQ methods Intersect and Except. The latter gives you the missing rows, your desired result:
DataRowComparer<DataRow> fieldComparer = DataRowComparer.Default;
IEnumerable<DataRow> matched = dt1.AsEnumerable().Intersect(dt2.AsEnumerable(), fieldComparer);
IEnumerable<DataRow> missing = dt1.AsEnumerable().Except(dt2.AsEnumerable(), fieldComparer);
If you want to add the missing rows into a third table, you could use:
DataTable result = missing.CopyToDataTable();
But i suggest to use a different way because that throws an exception if there were no missing rows:
DataTable result = dt1.Clone(); // empty, same schema
foreach(DataRow row in missing)
result.ImportRow(row);

How to Query to build a menu using LinQ in C#

I got 3 tables like below which reference the ID column's:
#Table 1
DepID NAME
1 Dep1
2 Dep2
3 Dep3
#Table 2
RoleID Name DepID
11 A1 1
12 A2 2
13 A3 1
14 A4 3
15 A5 3
#Table 3
ID Name RoleID
21 B1 11
23 B2 14
24 B3 11
Output
Menu
Dep1
A1B1B3
A3
Dep2A2
Dep3
A4B2
A5
I have tried using foreach loop, below is example:
StringBuilder objstr = new StringBuilder();
List<Parant> objpmenu = new List<Parant>();
List<Child> objcmenu = new List<Child>();
List<NestedChild> objnmenu = new List<NestedChild>();
objpmenu = GetParantMenu();
objcmenu = GetChildMenu();
objnmenu = GetNestedChildMenu();
objstr.Append("<ul id=\"drop-nav\">");
foreach (MenuParant _pitem in objpmenu)
{
objstr.Append("<li ><a href='" + _pitem.Url + "'><span >" +_pitem.MenuName + "</span></a>");
var childitem = objcmenu.Where(m => m.ParentId == _pitem.Id).ToList();
if (childitem.Count > 0)
{
objstr.Append("<ul>");
foreach (var _citem in childitem)
{
objstr.Append("<li ><a id='asubservice" + _citem.ChildId + "' href='" + _citem.ChildUrl + "'><span>" + _citem.ChildName + "</span></a></li>");
var NestedChildItem = objnmenu.Where(s => s.ChildId == _citem.ChildId).ToList();
if (NestedChildItem.Count > 0)
{
objstr.Append("<ul>");
foreach (var _nitem in NestedChildItem)
{
objstr.Append("<li><a href='" + _nitem.NestedChildUrl + "'>" + _nitem.NestedChildName + "</a></li>");
}
objstr.Append("</ul>");
}
}
objstr.Append("</ul>");
}
objstr.Append("</li>");
}
objstr.Append("</ul>");
divmenu.InnerHtml = objstr.ToString();
Please help me to generate menu with HTML content using Linq.
ThanQ in Advance
Normally where you have a n level hierarchy you would use a recursive method like code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication71
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable("DepID") ;
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("NAME", typeof(string));
dt.Columns.Add("PARENTID", typeof(int));
dt.Rows.Add(new object[] { 1, "Dep1"});
dt.Rows.Add(new object[] { 2, "Dep2"});
dt.Rows.Add(new object[] { 3, "Dep3"});
dt.Rows.Add(new object[] { 11, "A1", 1});
dt.Rows.Add(new object[] { 12, "A2", 2});
dt.Rows.Add(new object[] { 13, "A3", 1});
dt.Rows.Add(new object[] { 14, "A4", 3});
dt.Rows.Add(new object[] { 15, "A5", 3});
dt.Rows.Add(new object[] { 21, "B1", 11});
dt.Rows.Add(new object[] { 23, "B2", 14});
dt.Rows.Add(new object[] { 24, "B3", 11});
Node node = new Node();
node.Load(dt);
}
}
public class Node
{
public static Node root = new Node();
public string name { get; set; }
public int? id { get; set; }
public List<Node> children { get; set; }
public void Load(DataTable dt)
{
LoadRecursive(dt, null, root);
}
public void LoadRecursive(DataTable dt, int? parent, Node node)
{
foreach (DataRow row in dt.AsEnumerable().Where(x => x.Field<int?>("PARENTID") == parent))
{
if (node.children == null) node.children = new List<Node>();
Node newChild = new Node();
node.children.Add(newChild);
newChild.name = row.Field<string>("NAME");
newChild.id = row.Field<int>("ID");
LoadRecursive(dt, newChild.id, newChild);
}
}
}
}
You should get rid of the string concatenation as first thing. We have a couple of frameworks to take care of gory details. One such is called ASP.Net.
Once you have done that, make use of Repeater control to generate markup. Learn about databinding in asp.net and use that to generate your menu instead of manually looping through all the data.
If you need help generating those Repeater controls I talk about, I'll be more than happy to guide you further.

Categories

Resources