The given data can be transformed into the required format using
LINQ
query as shown below:
DataTable shiftData = new DataTable("ShiftData");
shiftData.Columns.Add("Id",typeof(int),null);
shiftData.Columns.Add("EmpId",typeof(string),null);
shiftData.Columns.Add("Month",typeof(string),null);
shiftData.Columns.Add("Date",typeof(DateTime),null);
shiftData.Columns.Add("Shift",typeof(int),null);
shiftData.Rows.Add(1,"001","Month01",new DateTime(2012,1,1),1);
shiftData.Rows.Add(2,"001","Month01",new DateTime(2012,1,2),2);
shiftData.Rows.Add(3,"001","Month01",new DateTime(2012,1,3),3);
shiftData.Rows.Add(4,"001","Month01",new DateTime(2012,1,3),1);
shiftData.Rows.Add(5,"001","Month01",new DateTime(2012,1,4),2);
shiftData.Rows.Add(6,"001","Month01",new DateTime(2012,1,5),3);
shiftData.Rows.Add(7,"002","Month01",new DateTime(2012,1,1),1);
shiftData.Rows.Add(8,"002","Month01",new DateTime(2012,1,2),2);
shiftData.Rows.Add(9,"002","Month01",new DateTime(2012,1,3),3);
shiftData.Rows.Add(10,"001","Month02",new DateTime(2012,2,3),1);
shiftData.Rows.Add(11,"001","Month02",new DateTime(2012,2,4),2);
shiftData.Rows.Add(12,"001","Month02",new DateTime(2012,2,5),3);
DataTable empShifts = new DataTable("EmpShifts");
empShifts.Columns.Add("EmpId",typeof(string),null);
empShifts.Columns.Add("Month",typeof(string),null);
for(int i=1; i<= 31; i++)
for(int j=1; j <=3; j++)
empShifts.Columns.Add(i.ToString()+"-" + j.ToString(),typeof(string),null);
shiftData.AsEnumerable().GroupBy (dr => dr.Field<string>("EmpId")).Select (er => {
er.GroupBy (dr2 => dr2.Field<string>("Month")).Select (mr => {
DataRow row = empShifts.NewRow();
row["EmpId"]=er.Key;
row["Month"]=mr.Key;
mr.Select (ms =>
row[ms.Field<datetime>("Date").Day + "-" + ms.Field<int>("Shift").ToString()]="x").Count ();
empShifts.Rows.Add(row);
return mr;
}).Count ();
return er;
}).Count ();
The
LINQ
has deferred execution model, which means the query will be executed only when it is iterated or a scalar method like
Count
is called on it. Hence, in the above code to force immediate execution of the query
Count
extension method is used.
The
DataTable
generated above can be bound to the
DataGridView
.
The
DataGridView
does not have an in built feature to display
Header
in two rows as required. However, as explained here
http://www.murrayhilltech.com/articles/articles.aspx?key=8[
^] the
DataGridView
headers can be custom drawn.