使用 C# Oledb 过滤 excel 电子表格和 return 特定值

Use of C# Oledb to filter through an excel spreadsheet and return a specific value

我有一个 WPF 应用程序,我想根据两个变量从中提取特定数据。 数据源是下面的电子表格,没有应用任何特定设置它只是原始数据。

我想要一种我可以调用的方法,即;

GetValue("A", "Dec-19")

有:

GetValue(string Product, DateTime Date)

这将 return 值 0。 我尝试了多种方法,但无法产生任何有用的东西。 这是我正在尝试的一个变体;

public double GetValue(string type, OleDbConnection TargetBuildOleDbConnection, DateTime Selection)
{
    string date = Selection.ToString("MMM-yy", ci);
    string CustomQuery = "SELECT ['" + date + "'] FROM [SHEET1$A1:Z1] WHERE [Product] = '" + type + "'";
    using (DataTable dt = new DataTable())
    {
        using (DataView dv = new DataView(dt))
        {
            using (OleDbCommand comm = new OleDbCommand())
            {
                comm.CommandText = "Select * from [Build Schedule$]";
                comm.Connection = TargetBuildOleDbConnection;
                using (OleDbDataAdapter da = new OleDbDataAdapter())
                {
                    da.SelectCommand = comm;
                    da.Fill(dt);

                }
            }
            dv.RowFilter = "SELECT ['" + date + "'] FROM [SHEET1$A1:Z1]"; //throwing exception
            double target = dt.Rows[0].Field<int>(0);
            return target;
        }
    }
}

这是您原始代码的修改版本,有望实现您所寻找的目标:

public double GetValue(string product, OleDbConnection targetBuildOleDbConnection, DateTime dte)
{
    const double defaultValue = 0; // Value to return if no match is found

    const string prodParamName = "@prod";

    using (OleDbCommand comm = new OleDbCommand())
    {
        comm.Connection = targetBuildOleDbConnection;
        comm.CommandText = string.Format("SELECT * FROM [Build Schedule$] WHERE Product={0}", prodParamName);
        comm.Parameters.Add(prodParamName, OleDbType.VarWChar); // Maybe VarChar is good enough (?)
        comm.Parameters[prodParamName].Value = product;

        using (OleDbDataReader rdr = comm.ExecuteReader())
        {
            if (!rdr.Read()) return defaultValue;

            for (var i = 1; i < rdr.FieldCount; i++)
            {
                var colName = rdr.GetName(i);

                double colNumber;
                if (double.TryParse(colName, out colNumber)) // If the date headers have actual Excel dates
                {
                    DateTime colDate = DateTime.FromOADate(colNumber); // Convert Excel's date number to a C# date
                    if (colDate.Month != dte.Month || colDate.Year != dte.Year) continue;
                }
                else if (colName != dte.ToString("MMM-yy")) // If the date headers are actual Excel strings
                    continue;

                double colValue;
                if (double.TryParse(rdr.GetValue(i).ToString(), out colValue)) return colValue;

                break; // No point in continuing, since we found the right column, but it did not have a valid double
            }
        }

        return  defaultValue;
    }
}

请注意以下事项:

  • 该代码假定数据位于名为 "Build Schedule"
  • 的 sheet 上
  • 该代码不使用您在 ToString 调用中使用的 ci CultureInfo 变量,因为我不知道该变量来自何处
  • 由于函数的类型是double,如果没有找到匹配值,它returns 0,而不是null;如果在这些情况下您更喜欢 null,可以将函数更改为 double? 类型,但调用此函数的代码必须知道 null 可以 returned
  • 无论日期 header 单元格(例如 "Nov-19" 和 "Dec-19" 单元格)是否包含仅在 Excel 或者它们是否包含实际的字符串;如果您只想处理一种情况,您可能想要消除 ifelse 循环中的 for
  • 该代码未利用最新版本的 C# 中的某些语法改进(如果您使用的是旧版本)
  • 可以优化对右列的搜索,特别是如果此函数将以连续方式调用多次

我测试了这段代码,它似乎每次都是 return 正确的值。希望对你有用。