【问题标题】:C# DataFilter cannot find column System.Data.Evaluate.ExceptionC# DataFilter 找不到列 System.Data.Evaluate.Exception
【发布时间】:2021-05-26 15:34:07
【问题描述】:

我正在将 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 解决方案。

【问题讨论】:

  • 我正在研究由以前的员工创建的解决方案。另外,据我所知 CopyToDataTable() 方法存在一些问题。

标签: c# excel datatable dataview


【解决方案1】:

这就是我使用 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);
            }

【讨论】:

  • 不建议使用字符串作为 DateTime ... 我强烈建议您在从 excel 导入时将数据解析为 DateTime,这样您就不会遇到任何问题。
  • 工作表上的格式无关紧要...只要将其作为 DataTable 导入 C# 内存,无论格式如何(它是对象类型),过滤的代码都应该起作用。我的猜测是你没有点击正确的列索引或者你在 DataTable 中的列不是 DateTime 类型。尝试使用一些断点进行调试,如果您可以指定一些数据,例如 3-4 行,我可以尝试检查它。
  • 使用 System.Globalization; DateTime d = DateTime.ParseExact("12/02/21 10:56:09", "yy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture);
  • 我将尝试在上面的答案中解释整个过程
  • 当您使用您的方法时,只需在末尾添加另一个 DateTime 列并迭代所有行以使用正确的对象类型填充它。正如我的第一条评论是.. 不建议将字符串用作 DateTime
猜你喜欢
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 2018-09-13
  • 2022-01-03
  • 2019-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多