使用 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 或者它们是否包含实际的字符串;如果您只想处理一种情况,您可能想要消除
if
或 else
循环中的 for
块
- 该代码未利用最新版本的 C# 中的某些语法改进(如果您使用的是旧版本)
- 可以优化对右列的搜索,特别是如果此函数将以连续方式调用多次
我测试了这段代码,它似乎每次都是 return 正确的值。希望对你有用。
我有一个 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 或者它们是否包含实际的字符串;如果您只想处理一种情况,您可能想要消除
if
或else
循环中的for
块 - 该代码未利用最新版本的 C# 中的某些语法改进(如果您使用的是旧版本)
- 可以优化对右列的搜索,特别是如果此函数将以连续方式调用多次
我测试了这段代码,它似乎每次都是 return 正确的值。希望对你有用。