You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#实现Excel文件选择与逐单元格读取(含上下按钮)及代码问题修复

解决Excel逐行读取卡顿、显示最后一条记录及进程残留问题

我来帮你梳理下当前代码的问题,然后给出完整的修复方案:

问题根源分析

  • 只显示最后一个单元格值:
    你的btnNext_Click方法里每次都把iRow重置为2,而且getExcelData里用了for循环从传入的rowNo一直遍历到最后一行,最后textEnterData.Text会被最后一行的值覆盖,自然看不到中间的记录。
  • 程序卡顿+多Excel.exe进程:
    每次点击Next按钮,你都会重新创建Excel.Application实例、打开Workbook,但从来没有关闭和释放这些资源。这不仅会导致重复打开文件卡顿,还会让Excel进程一直留在后台,越积越多。

修复方案

我们需要做这几个关键调整:

  1. 将Excel相关对象(xlApp, xlWorkBook, xlWorkSheet)提升为类级成员,只初始化一次,避免重复创建。
  2. 维护一个全局的当前行计数器(比如_currentRow),记录当前读取的行号,不要每次都重置。
  3. 移除getExcelData里的for循环,直接读取当前行的单元格值。
  4. 添加“上一个单元格”按钮的逻辑,处理行号递减的边界(不能小于数据起始行,比如2)。
  5. 确保在不再使用Excel时,正确关闭并释放所有资源,杀掉后台进程。

修正后的完整代码

using Excel = Microsoft.Office.Interop.Excel;
using System;
using System.Windows.Forms;

namespace YourNamespace
{
    public partial class YourForm : Form
    {
        // 类级变量,只初始化一次
        public static string ExcelName = "";
        string imagepath;
        Excel.Application xlApp;
        Excel.Workbook xlWorkBook;
        Excel.Worksheet xlWorkSheet;
        int _currentRow = 2; // 当前读取的行号,默认从第2行开始(假设第1行是表头)
        int _totalRows; // 记录Excel的总行数

        public YourForm()
        {
            InitializeComponent();
        }

        private void btnExcel_Click(object sender, EventArgs e)
        {
            getExcel();
        }

        private void getExcel()
        {
            try
            {
                OpenFileDialog folder = new OpenFileDialog();
                folder.Title = "Select Excel file";
                folder.FileName = "";
                folder.Filter = "Excel File|*.xlsx;*.xls";
                if (folder.ShowDialog() == DialogResult.OK)
                {
                    ExcelName = folder.FileName;
                    if (!string.IsNullOrEmpty(ExcelName.Trim()))
                    {
                        textBoxExcel.Text = ExcelName;
                        // 初始化Excel对象,只做一次
                        InitializeExcel();
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        // 初始化Excel对象,获取总行数
        private void InitializeExcel()
        {
            try
            {
                xlApp = new Excel.Application();
                xlWorkBook = xlApp.Workbooks.Open(ExcelName);
                xlWorkSheet = xlWorkBook.Worksheets["Sheet1"];
                Excel.Range xlRange = xlWorkSheet.UsedRange;
                _totalRows = xlRange.Rows.Count;
                // 显示第一行数据(第2行)
                UpdateCurrentRowData();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                ReleaseExcelResources();
            }
        }

        // 更新当前行的数据到文本框
        private void UpdateCurrentRowData()
        {
            if (xlWorkSheet == null) return;

            // 处理单元格值为空的情况
            var cellValue = xlWorkSheet.Cells[_currentRow, 2].Value;
            textEnterData.Text = cellValue == null ? "" : cellValue.ToString();
            textBoxGo.Text = _currentRow.ToString();
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            // 检查是否还有下一行
            if (_currentRow < _totalRows)
            {
                _currentRow++;
                UpdateCurrentRowData();
            }
            else
            {
                MessageBox.Show("已经是最后一条记录了!");
            }
        }

        // 添加上一个按钮的点击事件
        private void btnPrevious_Click(object sender, EventArgs e)
        {
            // 检查是否已经是第一行数据
            if (_currentRow > 2)
            {
                _currentRow--;
                UpdateCurrentRowData();
            }
            else
            {
                MessageBox.Show("已经是第一条记录了!");
            }
        }

        private void btnImage_Click(object sender, EventArgs e)
        {
            readImgaePath();
        }

        private void label5_Click(object sender, EventArgs e)
        {
        }

        private void readImgaePath()
        {
            FolderBrowserDialog imagepathDir = new FolderBrowserDialog();
            if (imagepathDir.ShowDialog() == DialogResult.OK)
            {
                imagepath = imagepathDir.SelectedPath;
                textBoxIamge.Text = imagepath;
            }
        }

        // 释放Excel资源,避免进程残留
        private void ReleaseExcelResources()
        {
            if (xlWorkBook != null)
            {
                xlWorkBook.Close(false);
                System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkBook);
                xlWorkBook = null;
            }

            if (xlApp != null)
            {
                xlApp.Quit();
                System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
                xlApp = null;
            }
        }

        // 窗体关闭时释放资源
        protected override void OnFormClosed(FormClosedEventArgs e)
        {
            base.OnFormClosed(e);
            ReleaseExcelResources();
        }
    }
}

额外注意事项

  • 确保你已经引用了Microsoft.Office.Interop.Excel程序集。
  • 如果你的Excel文件表头不是第1行,可以调整_currentRow的初始值和btnPrevious_Click里的边界判断。
  • 处理单元格值的时候,根据实际数据类型做适当转换,避免ToString()报错。

内容的提问来源于stack exchange,提问作者chandan sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:02:50