我有一个数据表,其中包含从1月1日到3月的值,如下所示:
DATE Employer Job1 Job2
1/4/2013 A 1.3 2
1/4/2013 B 2.5 6
1/6/2013 C 3.7 2.4
1/7/2013 D 11
1/7/2013 F 334 0
1/8/2013 A 1.87 1
1/8/2013 B 6.85 2
1/9/2013 C 58 226
1/16/2013 A 9.43 1.45
1/16/2013 B 5.27 0.6
1/122/2013 C 45.4 5
1/23/2013 A 44 4.78
1/29/2013 B 45 40
2/2/2013 C 45 54.12
2/2/2013 D 7 4.4587
2/3/2013 F 265 11.486
更新
DataTable datatable = new DataTable("Employee");
datatable.Columns.Add("Date", typeof(string));
datatable.Columns.Add("Employee", typeof(string));
datatable.Columns.Add("Job1", typeof(double));
datatable.Columns.Add("Job2", typeof(double));
datatable.Rows.Add(new Object[] { "1/4/2013", "A", 1.3, 2 });
datatable.Rows.Add(new Object[] { "1/4/2013", "B", 2.5, 6 });
datatable.Rows.Add(new Object[] { "1/6/2013", "C", 3.7, 2.4 });
datatable.Rows.Add(new Object[] { "1/7/2013", "D", 11, 0.0 });
datatable.Rows.Add(new Object[] { "1/7/2013", "F", 334, 0 });
datatable.Rows.Add(new Object[] { "1/8/2013", "A", 1.87, 1 });
datatable.Rows.Add(new Object[] { "1/8/2013", "B", 6.85, 2 });
datatable.Rows.Add(new Object[] { "1/9/2013", "C", 58, 226 });
datatable.Rows.Add(new Object[] { "1/16/2013", "A", 9.43, 1.45 });
datatable.Rows.Add(new Object[] { "1/16/2013", "B", 5.27, 0.6 });
datatable.Rows.Add(new Object[] { "1/22/2013", "C", 45.4, 5 });
datatable.Rows.Add(new Object[] { "1/23/2013", "A", 44, 4.78 });
datatable.Rows.Add(new Object[] { "1/29/2013", "B", 45, 40 });
datatable.Rows.Add(new Object[] { "2/2/2013", "C", 45, 54.12 });
datatable.Rows.Add(new Object[] { "2/2/2013", "D", 7, 4.4587 });
datatable.Rows.Add(new Object[] { "2/3/2013", "F", "265", 11.486 });
datatable.Rows.Add(new Object[] { "3/3/2013", "A", "25", 28.124 });
我想在星期一到星期日的星期开始的时候总结一周的job1值。这是我到目前为止编写的代码。
DateTime minDate = datatable.AsEnumerable()
.Min(r => DateTime.Parse(r.Field<string>("DATE")));
DateTime startDate = minDate.Date.Date.AddDays(+((6 + minDate.DayOfWeek
- DayOfWeek.Monday) % 7));
DateTime nextDate = startDate.AddDays(6);
DateTime maxDate = datatable.AsEnumerable()
.Max(r => DateTime.Parse(r.Field<string>("DATE")));
while (nextDate < maxDate)
{
var weekEmpGroups = datatable.AsEnumerable()
.Select(r => new
{
Row = r,
Employee = r.Field<String>("Employee"),
Date = DateTime.Parse(r.Field<string>("DATE"))
// week = minDate.Date.Date.AddDays(+((6 + minDate.DayOfWeek
- DayOfWeek.Monday) % 7))
})
.GroupBy(x => x.Employee);
DataTable dtWeeklyResults = new DataTable();
dtWeeklyResults.Columns.Add("Employee", typeof(string));
var dtf = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat;
double weekCount = 0.0;
string expression;
DataRow[] foundRows;
foreach (var empGroup in weekEmpGroups)
{
string employee = empGroup.Key;
var newRow = dtWeeklyResults.Rows.Add();
newRow["Employee"] = employee;
expression = "Employee=" + employee + " AND Date Between " + startDate
+ " And " + nextDate;
foundRows = datatable.Select(expression);
if (foundRows.Length > 0)
{
// add values using linq
}
}
请建议这是否是正确的方法,以及如何每周添加所有值?对于Job1,结果应如下所示:
Employee 1/7-1/13 1/14-1/20 1/21-1/27 1/28-2/3 and so on...
A sum of values for this 7 days
B
C
D
有人可以建议如何通过LINQ实现这一目标吗?
答案 0 :(得分:1)
帮助方法
private static string GetColumnName(int weekNumber)
{
DateTime jan1 = new DateTime(2013, 1, 1);
int daysOffset = DayOfWeek.Monday - jan1.DayOfWeek;
DateTime firstMonday = jan1.AddDays(daysOffset);
var cal = ci.Calendar;
int firstWeek = cal.GetWeekOfYear(firstMonday, ci.DateTimeFormat.CalendarWeekRule, ci.DateTimeFormat.FirstDayOfWeek);
if (firstWeek <= 1)
{
weekNumber -= 1;
}
DateTime result = firstMonday.AddDays((weekNumber-1) * 7);
return string.Format("{0}-{1}", result.ToString("M/d", ci), result.AddDays(6).ToString("M/d", ci));
}
private static int GetWeekOfYear(DateTime value)
{
return ci.Calendar.GetWeekOfYear(value, ci.DateTimeFormat.CalendarWeekRule, ci.DateTimeFormat.FirstDayOfWeek);
}
CultureInfo
实例
static CultureInfo ci = new CultureInfo("en-us");
<强>逻辑强> 的
// load parsed data from DataTable to a list
var data = (from row in dt.AsEnumerable()
select new
{
Date = DateTime.Parse(row.Field<string>("Date"), ci),
Employee = row.Field<string>("Employee"),
Value = row.Field<double>("Job1")
}).ToList();
// find min/max date and week number
var minDateTime = data.Select(i => i.Date).Min();
var maxDateTime = data.Select(i => i.Date).Max();
var minWeekNumber = GetWeekOfYear(minDateTime);
var maxWeekNumber = GetWeekOfYear(maxDateTime);
// prepare result DataTable
var resultDt = new DataTable("Job1");
resultDt.Columns.Add("Employee", typeof(string));
for (int i = minWeekNumber; i <= maxWeekNumber; i++)
resultDt.Columns.Add(i.ToString(), typeof(double));
// prepare grouped data query
var employeeData = from d in data
group d by d.Employee into g
select new
{
Employee = g.Key,
Items = g.GroupBy(x => GetWeekOfYear(x.Date))
.Select(x => new
{
Week = x.Key,
Value = x.Sum(xx => xx.Value)
})
};
// iterate over query results and fill resultsDt
foreach (var e in employeeData)
{
var newRow = resultDt.NewRow();
newRow["Employee"] = e.Employee;
foreach (var d in e.Items)
newRow[d.Week.ToString()] = d.Value;
resultDt.Rows.Add(newRow);
}
// change column names from week numbers to proper start-end dates
foreach(DataColumn col in resultDt.Columns)
{
int weekNumber;
if (int.TryParse(col.ColumnName, out weekNumber))
col.ColumnName = GetColumnName(weekNumber);
}
的结果:强> 的
Job1
Employee 1/7-1/13 1/14-1/20 1/21-1/27 1/28-2/3 2/4-2/10 2/11-2/17 2/18-2/24 2/25-3/3 3/4-3/10 3/11-3/
A 1,3 1,87 9,43 44 2
B 2,5 6,85 5,27 45
C 61,7 45,4 45
D 11 7
F 334 265
答案 1 :(得分:0)
如果任何人有相同的要求,以便每周显示结果,那么这里是代码:
private static DataTable GetWeeklyColumnsAndData(DataTable datatable, string resultFor)
{
DateTime minDate = datatable.AsEnumerable()
.Min(r => DateTime.Parse(r.Field<string>("DATE")));
DateTime maxDate = datatable.AsEnumerable()
.Max(r => DateTime.Parse(r.Field<string>("DATE")));
var distinctValues = datatable.AsEnumerable()
.Select(row => new
{
Employee = row.Field<string>("Employee")
})
.Distinct()
.ToList();
int totalEmployeeCount = System.Linq.Enumerable.Count(distinctValues);
DataTable resultDt = new DataTable();
resultDt.Columns.Add("Employee", typeof(string));
DateTime firstMonday = (minDate.DayOfWeek == DayOfWeek.Monday) ? minDate : GetNextWeekday(minDate, DayOfWeek.Monday);
DateTime startingMonday = firstMonday;
// add columns first
while (firstMonday < maxDate)
{
string weekName = string.Format("{0}-{1}", firstMonday.ToString("M/d", ci), firstMonday.AddDays(6).ToString("M/d", ci));
resultDt.Columns.Add(weekName, typeof(string));
firstMonday = firstMonday.AddDays(7);
}
for (int row = 0; row < totalEmployeeCount; row++)
{
DateTime startDate = startingMonday;
DateTime endDate = startingMonday.AddDays(6);
DataRow newRow = resultDt.NewRow();
string employee = distinctValues[row].Employee.ToString();
// first column for entity
newRow[0] = employee;
for (int col = 1; col < resultDt.Columns.Count; col++)
{
bool isBlank = false;
double total = 0;
string formattedMonday = endDate.ToString("M/d/yyyy");
string expression = String.Format("Employee = '{0}' AND DATE >= #{1}# AND DATE <= #{2}#", employee, startDate.ToString("M/d/yyyy"), formattedMonday);
DataView dv = datatable.DefaultView;
dv.RowFilter = expression;
if (dv.Count > 0)
{
foreach (DataRowView rowView in dv)
{
DataRow r = rowView.Row;
string value = r[resultFor].ToString();
if (value != "")
{
total += Convert.ToDouble(value);
}
else
{
isBlank = true;
}
}
}
else
{
isBlank = true;
}
if (total == 0 && isBlank)
{
newRow[col] = "";
}
else
{
newRow[col] = total;
}
startDate = endDate.AddDays(1);
endDate = startDate.AddDays(6);
}
resultDt.Rows.Add(newRow);
}
return resultDt;
}
public static DateTime GetNextWeekday(DateTime start, DayOfWeek day)
{
// The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
int daysToAdd = ((int)day - (int)start.DayOfWeek + 7) % 7;
return start.AddDays(daysToAdd);
}