获取Excel工作表名至ComboBox后无法读取内容,报Cannot find table -1错误
解决Excel工作表选择时“Cannot find table -1”的报错问题
嘿,我一眼就瞅出问题出在哪了,咱们一步步拆解:
核心错误原因
ComboBox未选中任何项时,
SelectedIndex默认值是-1
你刚把工作表名填充到ComboBox里,既没设置默认选中项,也没等用户手动选择,就直接用comboBox1.SelectedIndex去取DataTable集合里的表——索引-1对应的表根本不存在,自然会抛出“Cannot find table -1”的错误。重复读取Excel文件,低效且没必要
你在按钮点击事件里连续调用了三次ExcelToDataTable(ofd.FileName),每次调用都会重新打开文件、解析整个Excel,这不仅浪费系统资源,还可能因为文件被重复占用触发IO异常。
修正方案
咱们只需要做两个关键调整:
- 只读取一次Excel文件,把结果存起来复用
- 给ComboBox设置默认选中项,或等待用户选择后再加载数据
第一步:修改按钮点击事件,复用DataSet
首先在窗体类里添加一个成员变量存储读取的Excel数据,避免重复读取:
// 窗体类的成员变量,用来缓存当前读取的Excel数据 private DataSet _currentExcelDataSet; // 保持你的Excel读取方法不变 public static DataSet ExcelToDataTable(string fileName) { using (var stream = File.Open(fileName, FileMode.Open, FileAccess.Read)) { using (var reader = ExcelReaderFactory.CreateReader(stream)) { var result = reader.AsDataSet(new ExcelDataSetConfiguration() { UseColumnDataType = true, ConfigureDataTable = (data) => new ExcelDataTableConfiguration() { UseHeaderRow = true } }); return result; } } } private void btnOpen_Click(object sender, EventArgs e) { try { using (OpenFileDialog ofd = new OpenFileDialog() { Filter = "Excel 2003 Worksheet|*.xls|Excel 2007 Worksheet|*.xlsx", ValidateNames = true, Multiselect = false }) { if (ofd.ShowDialog() == DialogResult.OK) { // 只读取一次Excel文件,把结果存入成员变量 _currentExcelDataSet = ExcelToDataTable(ofd.FileName); comboBox1.Items.Clear(); foreach (DataTable dt in _currentExcelDataSet.Tables) { comboBox1.Items.Add(dt.TableName); } // 默认选中第一个工作表(如果Excel里有表的话) if (comboBox1.Items.Count > 0) { comboBox1.SelectedIndex = 0; // 加载第一个工作表的数据到DataGridView dataGridView1.DataSource = _currentExcelDataSet.Tables[0]; } } } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
第二步:添加ComboBox选择变更事件,实现工作表切换
给ComboBox绑定SelectedIndexChanged事件,用户切换选项时自动更新DataGridView的数据:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { // 确保缓存的DataSet存在,且用户已选中有效项 if (_currentExcelDataSet != null && comboBox1.SelectedIndex != -1) { dataGridView1.DataSource = _currentExcelDataSet.Tables[comboBox1.SelectedIndex]; } }
别忘了在窗体构造函数里手动绑定事件(或者在设计器里可视化绑定):
public YourFormName() { InitializeComponent(); comboBox1.SelectedIndexChanged += comboBox1_SelectedIndexChanged; }
这样修改后,既解决了报错问题,又优化了文件读取效率,用户切换工作表的体验也更流畅。
内容的提问来源于stack exchange,提问作者user9178291
相关产品推荐
相关产品推荐

