用OleDbAdaptor打开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在“ExcelWrapper.GetEntireSheet(string,string)”中传递给“OleDbDataAdapter.OleDbDataAdapter(string,OleDbConnection)”的查询string可能包含以下variables:string.Format(CultureInfo.InvariantCulture,“SELECT * FROM [{0} $ ]“,sheetName)'。 如果这些variables中的任何一个可能来自用户input,请考虑使用存储过程或参数化的SQL查询,而不是使用string连接构build查询。

sheetname不是来自用户input,所以我可以压制警告,但是抑制警告是我尽量避免的做法。

我试着用下面的方法更新方法:

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

它看起来很可疑,但它也会生成一个OleDbException:

Microsoft Access数据库引擎找不到对象“?”。 确保对象存在,并且正确拼写其名称和path名称。 如果'?' 不是本地对象,请检查您的networking连接或联系服务器pipe理员。

用查询参数调用这个方法的正确方法是什么?

您不能使用参数来表示表名称(工作表名称)。 只有当您想要为INSERT,UPDATE和WHERE子句传递VALUES时才使用参数。

但是,正如所指出的那样,通过您的代码分析工具,您可以使用一个白名单的表名,用户可以从中进行select,而无需input任何内容。

您使用OleDbConnection中的GetOleDbSchemaTable ,并使用DropDownList的DropDownStyle填充组合

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

现在,您的代码可以使用comboBoxTables中的SelectedItem,并使用string连接方法,而不会出现Sql Injection问题。

使用下面给出的代码,用户显式提供者声明。

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