日期范围的DataTable筛选器

3
我正在开发的程序中有一部分需要根据在表单上选择的日期时间选择器控件中选择的开始和结束日期来过滤所有不必要的行,并仅保留必要的行。一个 .csv 文件包含以下所有日期作为示例:
3/10/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/2015,则我希望只有这些项目包含在我的数据表中。我已经有了一个反转数据行的方法,但我需要知道如何过滤小于或等于结束日期且大于或等于开始日期的值。我的计划是在一个单独的方法中进行过滤,在该方法中传递我从读取 .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个回答

6

我不理解为什么要翻转数据表中的行。在我看来,这并不是必要的。

你可以使用以下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列,并在此处插入行号,则可以像这样完成:
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;
} 

我正在反转数据表的行,因为我将使用它来绘制图表,即蜡烛图。 - daftBit
我的代码仍然可以工作。我会先进行筛选,然后再进行反转。否则,您可能会反转许多最终不属于数据表的行。 - Ric .Net
看起来成功了。谢谢Ric! - daftBit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接