ASP.NET C#上传xlsx文件报找不到Sheet1$对象错误排查
问题现象
上传Excel文件时操作失败,抛出如下错误:
The Microsoft Office Access database engine could not find the object 'Sheet1$'.
该错误由业务代码中da.Fill(dt);行触发,完整业务代码如下:
private void UploadDataForAnyVendor(string strUser) { try { if (fluUploadBtn.HasFile) { string ConStr = ""; string ext = Path.GetExtension(fluUploadBtn.FileName).ToLower(); if (ext == ".xls" || ext == ".xlsx") { string path = Server.MapPath("~/UploadIPFEEData/"); //string strFolderName = "INDUS\\"; string strAnyFolder = "ANYFOLDER\\"; string strDeleteFile = Server.MapPath("~/ANYFOLDER/") + Path.GetFileName(fluUploadBtn.PostedFile.FileName); string newPath = Path.Combine(path, strAnyFolder.ToString()); DirectoryInfo objDirectory = new DirectoryInfo(newPath); string day = DateTime.Now.ToString("ss_mm_hh_dd_MM_yyyy"); if (!objDirectory.Exists) { System.IO.Directory.CreateDirectory(newPath); newPath = newPath + fluUploadBtn.FileName; } newPath = newPath + fluUploadBtn.FileName; if ((System.IO.File.Exists(fluUploadBtn.FileName))) { System.IO.File.Delete(fluUploadBtn.FileName); } if (ext.Trim() == ".xls") { ConStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + newPath + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=2\""; } else if (ext.Trim() == ".xlsx") { ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + newPath + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=2\""; } OleDbConnection mycon = new OleDbConnection(ConStr); if (mycon.State == ConnectionState.Closed) { mycon.Open(); } OleDbCommand cmd = new OleDbCommand("Select * from [Sheet1$]", mycon); OleDbDataAdapter da = new OleDbDataAdapter(); da.SelectCommand = cmd; DataSet ds = new DataSet(); DataTable dt = new DataTable(); da.Fill(dt); //loadfile(newPath, ext); string strAssignedStates = string.Empty; strAssignedStates = Convert.ToString(ViewState["States"]); string strOne = strStates; string[] strStateArray = new string[] { "" }; strStateArray = strOne.Split(','); string errMsg = string.Empty; int j = 1; string key = "StateNotFoundAlert" + j.ToString(); for (int i = 0; i < strStateArray.Length; i++) { if (dt.Rows[0]["CIRCLE"].ToString() == strStateArray[i].Trim().ToString()) { if (dt.Rows.Count > 0) { errMsg = "1"; dt.TableName = "RecodSet"; string xml = ConvertDatatableToXML(dt); mycon.Close(); ScriptManager.RegisterStartupScript(this, this.GetType(), key, "alert('File uploaded successfully.!!');", true); } else { string noData = "No data to upload."; ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "script", noData, false); } } else { errMsg = "0"; } } if (errMsg == "0" && errMsg != "1") { ScriptManager.RegisterStartupScript(this, this.GetType(), key, "alert('User is not authorised to upload data for state mentioned in excel report ');", true); } } else { string key = "Invalid vendor"; ScriptManager.RegisterStartupScript(this, this.GetType(), key, "alert('Invalid file extension !!!');", true); } } } catch (Exception) { throw; } }
错误原因
- 工作表名硬编码:代码固定写死查询
[Sheet1$]工作表,只要用户上传的Excel默认工作表被重命名、或者文件内不存在名为Sheet1的工作表,OLEDB引擎找不到对应对象就会抛出该错误。 - 文件保存逻辑缺失:代码全程没有调用
fluUploadBtn.SaveAs(newPath)将用户上传的文件实际存储到服务器指定路径,且路径拼接逻辑存在bug——当目标存储文件夹已存在时,if分支内不会给newPath赋值,分支外又重复拼接一次文件名,会导致最终生成的存储路径错乱,连接字符串指向的路径下不存在有效Excel文件,引擎读取时自然找不到目标工作表。 - 校验逻辑顺序错误:代码在判断
dt.Rows.Count > 0之前就直接访问dt.Rows[0]["CIRCLE"],即使工作表存在,只要表格为空就会触发索引越界异常。
修正方向
- 补全文件存储逻辑:修正路径拼接代码,统一在目录判断逻辑外做一次文件名拼接,拼接完成后第一时间调用
fluUploadBtn.SaveAs(newPath)将上传文件持久化到服务器,确认文件存在且大小正常后再做后续连接读取操作。路径修正示例:
// 修正路径拼接逻辑,去掉if分支内的newPath赋值 if (!objDirectory.Exists) { System.IO.Directory.CreateDirectory(newPath); } // 统一拼接一次最终文件路径 newPath = Path.Combine(newPath, fluUploadBtn.FileName); // 保存上传的文件 fluUploadBtn.SaveAs(newPath);
- 取消工作表名硬编码:OLEDB连接打开后,先读取当前Excel文件的所有工作表元数据,取有效工作表名拼接查询语句,避免工作表名不匹配问题,示例代码:
mycon.Open(); // 获取文件内所有表结构信息 DataTable sheetSchema = mycon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }); // 取第一个有效工作表名,返回值自带$后缀,无需额外拼接 string targetSheetName = sheetSchema.Rows[0]["TABLE_NAME"].ToString(); // 如果业务强制要求固定工作表模板,可在此处校验名称,不符合直接返回提示 OleDbCommand cmd = new OleDbCommand($"Select * from [{targetSheetName}]", mycon);
- 调整校验逻辑顺序:读取表格行内容前先判断
dt.Rows.Count > 0,避免空表触发索引越界;读取完成后及时关闭数据库连接,释放文件占用。 - 增加异常捕获分支:针对文件损坏、格式不匹配、权限不足等场景给出明确的用户提示,不要直接抛出系统原生错误。
内容的提问来源于stack exchange,提问作者Nadeem
相关产品推荐
相关产品推荐

