C# 使用OleDbAdaptor和查询参数打开Excel工作表

C# 使用OleDbAdaptor和查询参数打开Excel工作表,c#,sql,excel,oledb,C#,Sql,Excel,Oledb,这是我以前打开excel工作表的方法: public static System.Data.DataTable GetEntireSheet(string fileName, string sheetName) { string connectionString = GetConnectionString(fileName); System.Data.DataTable excelTable = new System.Data.DataTable(); excel

这是我以前打开excel工作表的方法:

public static System.Data.DataTable GetEntireSheet(string fileName,
    string sheetName)
{
    string connectionString = GetConnectionString(fileName);
    System.Data.DataTable excelTable = new System.Data.DataTable();
    excelTable.Locale = CultureInfo.InvariantCulture;

    using (OleDbConnection connection =
        new OleDbConnection(connectionString))
    {
        using (OleDbDataAdapter adaptor = new OleDbDataAdapter(
            string.Format(CultureInfo.InvariantCulture,
                "Select * from [{0}$]", sheetName),
            connection))
        {
            adaptor.Fill(excelTable);
        }
    }

    return excelTable;
}
这工作正常,但也会生成代码分析警告:

CA2100传递给的查询字符串 中的“OleDbDataAdapter.OleDbDataAdapter(字符串,OleDbConnection)” “ExcelWrapper.GetEntireSheet(字符串,字符串)”可以包含 以下变量的string.Format(CultureInfo.InvariantCulture, “从[{0}$]”中选择*,sheetName)”。如果这些变量中的任何一个可以 来自用户输入,考虑使用存储过程或 参数化SQL查询,而不是使用字符串生成查询 连接

sheetname不是来自用户输入,因此我可以抑制警告,但抑制警告是我尽量避免的做法

我已尝试使用以下内容更新该方法:

string query = "SELECT * FROM [?]";
string parameter = string.Format(
    CultureInfo.InvariantCulture, "{0}$", sheetName);
using (OleDbCommand command =
    new OleDbCommand(query, connection))
{
    command.Parameters.Add("?", OleDbType.BSTR).Value =
        parameter;

    using (OleDbDataAdapter adaptor =
        new OleDbDataAdapter(command))
    {
        adaptor.Fill(excelTable);
    }
}
但是,它看起来可疑,并且它还生成一个OLEDBE异常:

Microsoft Access数据库引擎找不到对象“?”。 确保对象存在,并拼写其名称和路径 正确命名。如果“?”不是本地对象,请检查网络 连接或联系服务器管理员


使用查询参数调用此函数的正确方法是什么?

不能使用参数表示表名(工作表名)。仅当要传递INSERT、UPDATE和in WHERE子句的值时,才使用参数

然而,正如所指出的,通过代码分析工具,您可以使用一个白色的表名列表,用户可以在其中进行选择,而无需键入任何内容

从OLEDB连接中使用,并使用DropDownStyle的DropDownList填充组合

using(OleDbConnection excel_con = new OleDbConnection(connectionString))
using(OleDbCommand cmd = new OleDbCommand())
{
    excel_con.Open();
    DataTable result = excel_con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
    var names = result.AsEnumerable().Select(x => x.Field<string>("TABLE_NAME").TrimEnd('$')).ToList();
    comboBoxTables.DataSource = names;
}
使用(OleDbConnection excel\u con=新的OleDbConnection(connectionString))
使用(OleDbCommand cmd=new OleDbCommand())
{
excel_con.Open();
DataTable结果=excel\u con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,null);
var NAME=result.AsEnumerable().Select(x=>x.Field(“TABLE_NAME”).TrimEnd(“$”).ToList();
comboBoxTables.DataSource=名称;
}

现在,您的代码可以使用comboBoxTables中的SelectedItem并使用字符串连接方法,而不会出现Sql注入问题。

使用下面给出的代码,即用户显式提供程序声明

public System.Data.DataTable ReadExcel(string fileName, string fileExt, strig SheetName)
    {
        string conn = string.Empty;
        System.Data.DataTable dtexcel = new System.Data.DataTable();
        if (fileExt.CompareTo(".xls") == 0)
            conn = @"provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fileName + ";Extended Properties='Excel 8.0;HRD=Yes;IMEX=1';"; //for below excel 2007  
        else
            conn = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties='Excel 12.0;HDR=YES';"; //for above excel 2007  
        using (OleDbConnection con = new OleDbConnection(conn))
        {
            try
            {
     String Query = String.Format("select * from [{0}]",SheetName);         
       // [sheet1] = [YouerSheetNameinExcelFile]
                //OleDbDataAdapter oleAdpt = new OleDbDataAdapter("select * from [sheet1]", con); //here we read data from sheet1  
                OleDbDataAdapter oleAdpt = new OleDbDataAdapter(Query, con); //here we read data from sheet1 and from specific cell range.   
                oleAdpt.Fill(dtexcel); //fill excel data into dataTable  
            }
            catch (Exception ex) { MessageBox.Show(ex.Message); }
        }
        return dtexcel;
    }

参数不能用于表示代码分析工具建议避免用户输入的表名。可以使用GetSchema方法检索表名(即工作表名),然后将所有内容放在组合框中,用户只能选择有效的名称。谢谢,但是工作表名来自另一个类,因此不能硬编码。此外,这并没有解决问题的查询参数方面。在这一点上,用户没有关于工作表名称的选择(可能在将来),但我知道您来自哪里,关于“白名单”。我将很快对此进行调查。那么,这是一种例外情况,在这种情况下,您可以抑制警告。代码分析工具不知道您的字符串是否安全。因此,除非您的工具制造商为产品添加更多智能,否则您将被迫抑制或忽略警告。