我正在使用 .Net 4.0 读取 Excel 文件,使用 OleDbDataAdapter
时遇到了类似的问题。即在 MS Excel 中读取 "PartID" 列中的混合数据类型,其中 PartID 值可以是数字(例如 561)或文本(例如 HL4354),即使该 Excel 列已经格式化为 "Text"。
据我所知,ADO.NET 根据列中大多数值的数据类型来选择数据类型(如果平局则选择数字数据类型)。也就是说,如果样本集中大多数 PartID 都是数字,则 ADO.NET 将声明该列为数字。因此,ADO.Net 将尝试将每个单元格转换为数字,并且无法导入这些 "text" PartID 的 "text" 值。
我的解决方法是将 OleDbConnection
连接字符串设置为使用 Extended Properties=IMEX=1;HDR=NO
来指示这是一个导入过程,而且表中不包括标头。Excel 文件有一个标题行,因此在这种情况下告诉 ado.net 不要使用它。然后在代码中稍后删除数据集中的标题行,就可以得到该列的混合数据类型。
string sql = "SELECT F1, F2, F3, F4, F5 FROM [sheet1$] WHERE F1 IS NOT NULL";
OleDbConnection connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + PrmPathExcelFile + @";Extended Properties=""Excel 8.0;IMEX=1;HDR=NO;TypeGuessRows=0;ImportMixedTypes=Text""");
OleDbCommand cmd = new OleDbCommand(sql, connection);
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
DataSet ds = new DataSet();
ds.Tables.Add("xlsImport", "Excel");
da.Fill(ds, "xlsImport");
DataRow rowDel = ds.Tables["xlsImport"].Rows[0];
ds.Tables["xlsImport"].Rows.Remove(rowDel);
ds.Tables["xlsImport"].Columns[0].ColumnName = "LocationID";
ds.Tables["xlsImport"].Columns[1].ColumnName = "PartID";
ds.Tables["xlsImport"].Columns[2].ColumnName = "Qty";
ds.Tables["xlsImport"].Columns[3].ColumnName = "UserNotes";
ds.Tables["xlsImport"].Columns[4].ColumnName = "UserID";
connection.Close();
// 现在你可以使用 LINQ 来搜索字段
var data = ds.Tables["xlsImport"].AsEnumerable();
var query = data.Where(x => x.Field<string>("LocationID") == "COOKCOUNTY").Select(x =>
new Contact
{
LocationID= x.Field<string>("LocationID"),
PartID = x.Field<string>("PartID"),
Quantity = x.Field<string>("Qty"),
Notes = x.Field<string>("UserNotes"),
UserID = x.Field<string>("UserID")
});
Extended Properties=\"Excel 8.0;IMEX=1;\";
解决了这个问题。 - BornToCode