DataTable过滤器,包含日期范围

时间:2015-03-15 20:41:07

标签: c# datatable ado.net

我有一个我正在处理的程序的一部分需要过滤掉所有不必要的行,并且只根据从我的表单上的日期时间选择器控件中选择的开始和结束日期保留必要的行。 .csv文件包含以下所有日期作为示例:

  • 3/10/2015
  • 2015年3月9日
  • 2015年3月6日
  • 2015年3月5日
  • 2015年3月4日
  • 2015年3月3日
  • 2015年3月2日
  • 2015年2月27日
  • 2015年2月26日
  • 2015年2月25日
  • 2015年2月24日
  • 2015年2月23日
  • 2015年2月20日

如果我的日期时间选择器已被选中作为2015年2月18日开始,结束日期为2015年3月2日,我希望只能将这些项目包含在我的数据表中。我有一个方法已经反转数据行,但我需要知道如何过滤掉小于或等于结束日期,大于或等于开始日期的值。 我的计划是在一个单独的方法中完成过滤,在该方法中,我传递通过读取.csv文件创建的现有表。

到目前为止我的代码如下:

public DataTable PopulateTable()
{
    DataTable stockTable = new DataTable();
    try
    {
        FileStream stream = new FileStream(BuildFilePath(), FileMode.Open);
        stream.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show("Unable to open filepath");
    }

    StreamReader reader = new StreamReader(BuildFilePath());
    string header = "";
    string line = "";
    char[] delimeter = { ',' };
    string[] headerData;
    string[] rowData;
    //read the header and add the names to the columns of the data table
    header = reader.ReadLine();
    headerData = header.Split(delimeter);
    for (int i = 0; i < 5; ++i)
    {
        if (i == 0)
        {
            stockTable.Columns.Add(new DataColumn(headerData[i], typeof(DateTime)));
        }
        else
            stockTable.Columns.Add(new DataColumn(headerData[i], typeof(decimal)));
    }
    //read each line and populate the data table rows
    while (reader.Peek() > -1)
    {
        line = reader.ReadLine();
        rowData = line.Split(delimeter);
        stockTable.Rows.Add(rowData[0], rowData[1], rowData[2], rowData[3], rowData[4]);
    }
    reader.Close();

    //before the table is returned here call the FilterTable function

    return ReverseRowsInDataTable(stockTable);
}

private DataTable ReverseRowsInDataTable(DataTable table)
{
    DataTable reversedDataTable = table.Clone();
    for (int i = table.Rows.Count - 1; i >= 0; --i)
    {
        reversedDataTable.ImportRow(table.Rows[i]);
    }
    return reversedDataTable;
}

private DataTable FilterTable(DataTable table)
{
    DataTable filteredTable = new DataTable();
    return filteredTable;
}

1 个答案:

答案 0 :(得分:5)

我不明白为什么要反转数据表中的行。从我的角度来看,这不是必要的。

您可以使用Linq查询过滤行,如下所示:

private DataTable FilterTable(DataTable table, DateTime startDate, DateTime endDate)
{
    var filteredRows =
        from row in table.Rows.OfType<DataRow>()
        where (DateTime) row[0] >= startDate
        where (DateTime) row[0] <= endDate
        select row;

    var filteredTable = table.Clone();

    filteredRows.ToList().ForEach(r => filteredTable.ImportRow(r));

    return filteredTable;
} 

要返回具有相同结构的DataTable,您可以使用.Clone()方法并在此新创建的表中添加已过滤的行。

修改

你可以在同样的方式做相反的事情。如果你在填充时在索引1处添加一个额外的int列,并在这里插入rownumber:

for (int i = 0; i < 6; ++i)
{
    if (i == 0)
    {
        stockTable.Columns.Add(new DataColumn(headerData[i], typeof(DateTime)));
    }
    else if (i == 1)
    {
        stockTable.Columns.Add(new DataColumn("RowNbr", typeof(int)));
    }
    else
        stockTable.Columns.Add(new DataColumn(headerData[i-1], typeof(decimal)));
}
//read each line and populate the data table rows
int j = 0;
while (reader.Peek() > -1)
{
    line = reader.ReadLine();
    rowData = line.Split(delimeter);
    stockTable.Rows.Add(rowData[0], j++, rowData[1], rowData[2], rowData[3], rowData[4]);
}

撤消数据非常简单:

private DataTable FilterTable(DataTable table, DateTime startDate, DateTime endDate)
{
    var filteredRows =
        from row in table.Rows.OfType<DataRow>()
        where (DateTime)row[0] >= startDate
        where (DateTime)row[0] <= endDate
        orderby (int)row[1] descending 
        select row;

    var filteredTable = table.Clone();

    filteredRows.ToList().ForEach(r => filteredTable.ImportRow(r));

    return filteredTable;
}