简体   繁体   English

使用C# Oledb 过滤excel电子表格并返回特定值

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

I have a WPF app of which I would like to pull specific data from based on two variables.我有一个 WPF 应用程序,我想根据两个变量从中提取特定数据。 The data source is the below spreadsheet, there are no specific settings applied it is simply raw data.数据源是下面的电子表格,没有应用特定的设置,它只是原始数据。

在此处输入图片说明 I would like a method of which I could call ie;我想要一种我可以调用的方法,即;

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

With:和:

GetValue(string Product, DateTime Date)

This would return the value 0. I have tried numerous approaches however am unable to produce anything that functions.这将返回值 0。我尝试了多种方法,但无法产生任何功能。 Here is a variation of an attempt of mine I was working on;这是我正在进行的尝试的一种变体;

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;
        }
    }
}

This is a modified version of your original code that will hopefully accomplish what you were looking for:这是原始代码的修改版本,有望实现您的需求:

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;
    }
}

Please note the following:请注意以下事项:

  • The code assumes the data is on a sheet called "Build Schedule"该代码假定数据位于名为“Build Schedule”的工作表上
  • The code does not use the ci CultureInfo variable you used in the ToString call because I did not know where that variable came from该代码不使用您在ToString调用中使用的ci CultureInfo 变量,因为我不知道该变量来自哪里
  • Since the function is of type double , it returns 0, instead of null, if no matching value is found;由于函数是double类型,如果没有找到匹配的值,它返回 0,而不是 null; if you prefer null in these cases, the function can be changed to type double?如果在这些情况下您更喜欢 null,则可以将该函数更改为double? , but the code that calls this function must be aware that a null can be returned ,但是调用这个函数的代码一定要知道可以返回null
  • The code should theoretically work whether the date header cells (eg the "Nov-19" and "Dec-19" cells) contain date values that are merely formatted as "MMM-yy" in Excel or whether they contain actual strings;无论日期标题单元格(例如“Nov-19”和“Dec-19”单元格)是否包含在 Excel 中仅格式化为“MMM-yy”的日期值,或者它们是否包含实际字符串,代码理论上都应该有效; you may want to eliminate either the if or the else block inside the for loop if you only want to handle one case如果您只想处理一种情况,您可能希望消除for循环中的ifelse
  • The code does not take advantage of certain syntax improvements in recent versions of C# (in case you are using an older version)该代码没有利用 C# 最新版本中的某些语法改进(如果您使用的是旧版本)
  • The search for the right column can be optimised, especially if this function will be called many times in consecutive fashion可以优化对右列的搜索,特别是如果此函数将以连续方式多次调用

I tested this code, and it seemed to return the right value every time.我测试了这段代码,它似乎每次都返回正确的值。 I hope it works for you.我希望这个对你有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM