问题描述
我正在将 Excel 工作表导出到数据表 dt。
CultureInfo culture = (CultureInfo)CultureInfo.CurrentCulture.Clone();
culture.DateTimeFormat.ShortDatePattern = "yyyy-MMM-dd";
culture.DateTimeFormat.LongTimePattern = "";
Thread.CurrentThread.CurrentCulture = culture;
我的过滤器字符串如下:
string strFilter = "CONVERT([Creation date],'System.DateTime') <= '2021-02-23' AND CONVERT([Creation date],'System.DateTime') >= '2020-12-01'";
public DataTable filterDataTable(DataTable dt,string filter) {
DataView dv = new DataView(dt);
dv.RowFilter = filter;
DataTable dt2 = dv.ToTable();
return dt2;
}
执行上述操作后,我收到 System.Data.Evaluate.Exception 类型的异常和消息:“找不到列 [OK]。”结果:-2146232032。
在源 Excel 文件中,我要过滤的列名称是“创建日期”,该列在 Excel 中被识别为常规格式。列中的示例值:2020-12-29 14:05:33、2020-07-03 13:05:19。
如何使用日期条件过滤此数据视图?
编辑 - 解决方案
在过滤之前,我创建了一个 DateTime 类型的新列“Creation_date”,并添加了旧列中的解析值。
public DataTable getDtWithDateType(DataTable dt)
{
dt.Columns.Add("Creation_date",typeof(DateTime));
foreach(DaTarow row in dt.Rows)
{
row["Creation_date"] = DateTime.ParseExact(row["Creation date"].ToString(),"yyyy-MM-dd HH:mm:ss",CultureInfo.InvariantCulture);
}
return dt;
}
拥有扩展的 DataTable 后,我就能够实施 Svetoslav Angelov 提出的 Linq 解决方案。
解决方法
这是我使用 Linq 的方式,简单高效
public DataTable FilterDataTable(DataTable dt,DateTime minDate,DateTime maxDate,int columnIndex)
{
DataTable output = dt.Clone();
var filterMenuRows = dt.AsEnumerable().Where(
r => r.Field<DateTime>(columnIndex) >= minDate
&& r.Field<DateTime>(columnIndex) <= maxDate);
if (filterMenuRows != null && filterMenuRows.Any())
{
output = filterMenuRows.CopyToDataTable();
}
return output;
}
如果你想过滤其他类型的数据列,你应该使用 RowFilter 或 Select ,例如
public DataTable FilterDataTable(DataTable dt,string filter,string columnName)
{
DataTable output = dt.Select(columnName +"='" + filter + "'");
return output;
}
假设您在填充 DataTable 时使用迭代:
DataTable dt = new DataTable();
dt.Columns.Add("NAME",typeof(string));
dt.Columns.Add("ADDRESS",typeof(string));
dt.Columns.Add("NOTE",typeof(string));
dt.Columns.Add("BIRTH_DATE",typeof(DateTime));
//excel is not zero based!!
int maxExcelRows = 20001;
int maxExcelColumns = 5;
DataRow nextRow = dt.NewRow();
for (int i = 1; i <= maxExcelRows; i++)
{
for (int j = 1; j <= maxExcelColumns; j++)
{
//new line
if (j == 1)
{
nextRow = dt.NewRow();
}
//write the values
if (xlRange.Cells[i,j] != null && xlRange.Cells[i,j].Value != null)
{
if (j == 5) // your DateTime column here
{
// NOTE: use the exact format of the outer document
nextRow[j - 1] = DateTime.ParseExact(xlRange.Cells[i,j].Value.ToString(),"yy/MM/dd HH:mm:ss",CultureInfo.InvariantCulture); ;
}
else
{
nextRow[j - 1] = xlRange.Cells[i,j].Value.ToString();
}
}
}
dt.Rows.Add(nextRow);
}