C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C# WinForm读取Excel

C# WinForm读取Excel的三种方法及对比详解

作者:墨瑾轩

本文对比分析了三种方法(Microsoft Interop、EPPlus组件、NPOI)用于读取Excel数据,详细阐述了各自的特点、优势及局限性,并通过代码示例讲解的非常详细,需要的朋友可以参考下

什么是WinForm读取Excel?

想象一下你的程序变成一个“魔法盒子”——点击按钮,它就能“吞掉”Excel文件,再“吐出”整齐的数据!这就是WinForm读取Excel的神奇之处!

核心问题

3种主流方法对比

方法优点缺点
Microsoft Interop功能强大、支持复杂操作需安装Office、性能差
EPPlus无需Office、开源免费仅支持.xlsx格式
NPOI支持.xls/.xlsx、跨平台代码稍复杂

方法1:Microsoft Interop(需安装Office)

1. 准备工作

2. 代码模板

using Excel = Microsoft.Office.Interop.Excel;

public class ExcelReader
{
    public static void ReadExcelFile()
    {
        // 1. 打开文件对话框
        OpenFileDialog openFileDialog = new OpenFileDialog
        {
            Filter = "Excel 文件 (*.xls, *.xlsx)|*.xls;*.xlsx",
            Title = "请选择Excel文件"
        };

        if (openFileDialog.ShowDialog() != DialogResult.OK) return;

        string filePath = openFileDialog.FileName;

        // 2. 创建Excel应用实例
        Excel.Application excelApp = new Excel.Application();
        Excel.Workbook workbook = null;
        Excel.Worksheet worksheet = null;

        try
        {
            // 3. 打开工作簿
            workbook = excelApp.Workbooks.Open(filePath);
            worksheet = workbook.Sheets[1]; // 默认读取第一个工作表

            // 4. 获取已使用范围
            Excel.Range range = worksheet.UsedRange;

            // 5. 遍历单元格
            for (int row = 1; row <= range.Rows.Count; row++)
            {
                for (int col = 1; col <= range.Columns.Count; col++)
                {
                    // 6. 读取单元格值
                    object cellValue = range.Cells[row, col].Value2;
                    Console.Write(cellValue?.ToString() ?? "NULL" + "\t");
                }
                Console.WriteLine();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("读取失败:" + ex.Message);
        }
        finally
        {
            // 7. 释放COM对象(非常重要!)
            if (workbook != null) workbook.Close(false);
            if (excelApp != null) excelApp.Quit();
            ReleaseComObject(worksheet);
            ReleaseComObject(workbook);
            ReleaseComObject(excelApp);
        }
    }

    private static void ReleaseComObject(object obj)
    {
        if (obj != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
    }
}

代码解析

方法2:EPPlus(无需Office)

1. 准备工作

安装NuGet包:

Install-Package EPPlus

2. 代码模板

using OfficeOpenXml;
using System.IO;

public class EpplusReader
{
    public static void ReadExcelFile()
    {
        OpenFileDialog openFileDialog = new OpenFileDialog
        {
            Filter = "Excel 文件 (*.xlsx)|*.xlsx",
            Title = "请选择Excel文件"
        };

        if (openFileDialog.ShowDialog() != DialogResult.OK) return;

        string filePath = openFileDialog.FileName;

        using (var package = new ExcelPackage(new FileInfo(filePath)))
        {
            // 1. 获取第一个工作表
            ExcelWorksheet worksheet = package.Workbook.Worksheets[0];

            int rowCount = worksheet.Dimension.Rows;
            int colCount = worksheet.Dimension.Columns;

            // 2. 遍历单元格
            for (int row = 1; row <= rowCount; row++)
            {
                for (int col = 1; col <= colCount; col++)
                {
                    // 3. 读取单元格值
                    string cellValue = worksheet.Cells[row, col].Text;
                    Console.Write(cellValue + "\t");
                }
                Console.WriteLine();
            }
        }
    }
}

代码解析

方法3:NPOI(兼容.xls/.xlsx)

1. 准备工作

安装NuGet包:

Install-Package NPOI

2. 代码模板

using NPOI.HSSF.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.SS.UserModel;

public class NpoiReader
{
    public static void ReadExcelFile()
    {
        OpenFileDialog openFileDialog = new OpenFileDialog
        {
            Filter = "Excel 文件 (*.xls, *.xlsx)|*.xls;*.xlsx",
            Title = "请选择Excel文件"
        };

        if (openFileDialog.ShowDialog() != DialogResult.OK) return;

        string filePath = openFileDialog.FileName;

        IWorkbook workbook = null;

        using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            // 1. 根据文件扩展名选择加载器
            if (filePath.EndsWith(".xls"))
            {
                workbook = new HSSFWorkbook(file); // .xls格式
            }
            else if (filePath.EndsWith(".xlsx"))
            {
                workbook = new XSSFWorkbook(file); // .xlsx格式
            }
        }

        if (workbook == null) return;

        ISheet sheet = workbook.GetSheetAt(0); // 获取第一个工作表

        // 2. 遍历行
        for (int rowIndex = 0; rowIndex <= sheet.LastRowNum; rowIndex++)
        {
            IRow row = sheet.GetRow(rowIndex);
            if (row == null) continue;

            // 3. 遍历单元格
            for (int colIndex = 0; colIndex < row.LastCellNum; colIndex++)
            {
                ICell cell = row.GetCell(colIndex);
                string cellValue = cell?.ToString() ?? "NULL";
                Console.Write(cellValue + "\t");
            }
            Console.WriteLine();
        }
    }
}

代码解析

常见问题与优化技巧

1. 程序运行后卡死?

场景:Interop方法中未正确关闭Excel进程!
解决方案

// 在finally块中强制退出
if (excelApp != null)
{
    excelApp.Quit();
    ReleaseComObject(excelApp);
}

2. 文件路径错误?

场景:用户选择文件后未检查路径合法性!
解决方案

if (!File.Exists(filePath))
{
    MessageBox.Show("文件不存在!");
    return;
}

3. Excel文件打不开?

场景:文件被其他程序占用!
解决方案

try
{
    workbook = excelApp.Workbooks.Open(filePath);
}
catch (Exception ex)
{
    MessageBox.Show("文件被占用,请关闭Excel后再试!");
}

方法对比总结

方法是否需要Office支持格式性能难度
Interop✅ 必须.xls/.xlsx⚠️ 慢🟡 中
EPPlus❌ 不需要.xlsx✅ 快✅ 简单
NPOI❌ 不需要.xls/.xlsx✅ 快🟡 中

实战场景:Excel数据导入DataGridView

private void ImportToDataGridView(string filePath)
{
    dataGridView1.Rows.Clear();
    dataGridView1.Columns.Clear();

    using (var package = new ExcelPackage(new FileInfo(filePath)))
    {
        var worksheet = package.Workbook.Worksheets[0];
        int colCount = worksheet.Dimension.Columns;

        // 添加列头
        for (int col = 1; col <= colCount; col++)
        {
            dataGridView1.Columns.Add(new DataGridViewTextBoxColumn
            {
                HeaderText = worksheet.Cells[1, col].Text
            });
        }

        // 添加数据行
        for (int row = 2; row <= worksheet.Dimension.Rows; row++)
        {
            var cells = new List<string>();
            for (int col = 1; col <= colCount; col++)
            {
                cells.Add(worksheet.Cells[row, col].Text);
            }
            dataGridView1.Rows.Add(cells.ToArray());
        }
    }
}

代码解析

最佳实践建议

  1. 异步加载
    • 大文件读取时使用async/await,避免界面卡顿。
  2. 错误提示
    • try/catch捕获文件路径错误、格式错误等问题。
  3. 日志记录
    • 记录读取过程中的关键信息,方便调试。
  4. 性能优化
    • 优先选择EPPlus或NPOI,避免Interop的性能瓶颈。
  5. 用户友好
    • 提供“打开文件”、“保存为CSV”等按钮,提升交互体验。

以上就是C# WinForm读取Excel的三种方法及对比详解的详细内容,更多关于C# WinForm读取Excel的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文