当前位置: 首页 > news >正文

C# 操作 Excel

C# 中操作 Excel 有许多强大的库可供选择,它们各有特点,适合不同的场景。下面我用一个表格汇总这些常见库及其特点,并辅以说明和代码示例

库名称 类型 优点 缺点 适用场景 NuGet 安装命令
ClosedXML 开源 API 直观易用,无需 Excel 环境,性能较好 旧版 .xls 格式支持有限 快速创建、读取、修改 .xlsx 文件,报表导出 Install-Package ClosedXML
EPPlus 开源 功能丰富,性能优秀,支持图表、数据验证、条件格式等 v6+ 版本商用需授权 (非商业用途免费,LGPL 协议下 v5 及以下版本可免费商用) 复杂的 Excel 操作和数据导出 Install-Package EPPlus
NPOI 开源 无需 Office COM 组件,同时支持 .xls 和 .xlsx API 相对底层,使用稍复杂 需要处理 旧版 .xls 格式 Install-Package NPOI
Microsoft.Office.Interop.Excel 官方 COM 功能最全面,能实现 Excel 几乎所有功能 严重依赖本地安装的 Excel,性能开销大,稳定性相对较低,不适合服务器端 客户端应用且需要与 Excel 深度交互 通过 Visual Studio 的 COM 引用添加
ExcelDataReader 开源 专注于数据读取,速度快,内存占用低 主要用于读取,写入功能很弱 快速读取大量 Excel 数据到 DataSet/DataTable Install-Package ExcelDataReader
Spire.XLS 商业 功能强大,支持转换(如转 PDF),无需 Excel 环境 免费版有功能和水印限制,商用需购买授权 需要高级功能(如转换)且预算允许的项目 Install-Package FreeSpire.XLS (免费版)

如何选择 Excel 操作库

  • 优先考虑开源方案:大多数情况下,ClosedXML (易用性优先) 或 EPPlus v5 (功能丰富且可免费商用) 或 NPOI (需处理旧版 .xls) 是不错的选择。
  • 专注高性能读取:选择 ExcelDataReader
  • 需要与 Excel 进程深度交互:仅在客户端环境且必需时使用 Microsoft.Office.Interop.Excel
  • 有预算且需要强大功能:考虑 Spire.XLS 等商业库。

使用示例:ClosedXML 和 ExcelDataReader

下面我们重点看一下 ClosedXML (因其易用性) 和 ExcelDataReader (因其读取专业性) 的封装示例。

ClosedXML 封装示例 (写入与读取)

ClosedXML 提供了非常直观的 API 来操作 Excel。

using ClosedXML.Excel;
using System.Data;public class ClosedXmlExcelHelper : IDisposable
{private XLWorkbook _workbook;private IXLWorksheet _worksheet;/// <summary>/// 打开或创建一个 Excel 文件/// </summary>/// <param name="filePath">文件路径</param>public void OpenOrCreate(string filePath){if (File.Exists(filePath)){_workbook = new XLWorkbook(filePath);}else{_workbook = new XLWorkbook();}}/// <summary>/// 选择或创建一个工作表/// </summary>/// <param name="sheetName">工作表名称</param>public void SelectOrCreateWorksheet(string sheetName = "Sheet1"){if (_workbook.Worksheets.TryGetWorksheet(sheetName, out var ws)){_worksheet = ws;}else{_worksheet = _workbook.Worksheets.Add(sheetName);}}/// <summary>/// 写入单个单元格数据/// </summary>public void SetCellValue(int row, int column, object value){_worksheet.Cell(row, column).Value = value;}/// <summary>/// 写入一行数据/// </summary>public void WriteRow(int startRow, int startColumn, params object[] values){for (int i = 0; i < values.Length; i++){SetCellValue(startRow, startColumn + i, values[i]);}}/// <summary>/// 写入 DataTable 到工作表/// </summary>public void WriteDataFromTable(DataTable dataTable, bool includeHeader = true, int startRow = 1){if (includeHeader){for (int i = 0; i < dataTable.Columns.Count; i++){SetCellValue(startRow, i + 1, dataTable.Columns[i].ColumnName);}startRow++;}for (int rowIdx = 0; rowIdx < dataTable.Rows.Count; rowIdx++){for (int colIdx = 0; colIdx < dataTable.Columns.Count; colIdx++){SetCellValue(startRow + rowIdx, colIdx + 1, dataTable.Rows[rowIdx][colIdx]);}}}/// <summary>/// 将指定范围读取到 DataTable/// </summary>public DataTable ReadRangeToDataTable(int startRow, int startColumn, int numRows, int numColumns, bool firstRowIsHeader = false){var dataTable = new DataTable();var range = _worksheet.Range(startRow, startColumn, startRow + numRows - 1, startColumn + numColumns - 1);if (firstRowIsHeader){var headerRow = range.FirstRow();foreach (var cell in headerRow.Cells()){dataTable.Columns.Add(cell.Value.ToString());}startRow++;numRows--;}else{for (int i = 1; i <= numColumns; i++){dataTable.Columns.Add($"Column{i}");}}var dataRange = firstRowIsHeader ? range.Range(2, 1, numRows, numColumns) : range;foreach (var row in dataRange.Rows()){DataRow dataRow = dataTable.NewRow();for (int i = 1; i <= numColumns; i++){dataRow[i - 1] = row.Cell(i).Value;}dataTable.Rows.Add(dataRow);}return dataTable;}/// <summary>/// 保存文件/// </summary>public void Save(string filePath = null){_workbook.SaveAs(filePath);}public void Dispose(){_workbook?.Dispose();}
}

使用 ClosedXMLHelper:

// 使用示例
using (var excelHelper = new ClosedXmlExcelHelper())
{// 创建新文件并写入excelHelper.OpenOrCreate("test.xlsx");excelHelper.SelectOrCreateWorksheet("Data");excelHelper.SetCellValue(1, 1, "Hello");excelHelper.SetCellValue(1, 2, "World");excelHelper.WriteRow(2, 1, new object[] { 1, "Alice", 25 });excelHelper.WriteRow(3, 1, new object[] { 2, "Bob", 30 });// 保存excelHelper.Save("test.xlsx");
}// 读取示例
using (var excelHelper = new ClosedXmlExcelHelper())
{excelHelper.OpenOrCreate("test.xlsx");excelHelper.SelectOrCreateWorksheet("Data");DataTable dt = excelHelper.ReadRangeToDataTable(1, 1, 3, 3, true);// 处理 dt...
}

ExcelDataReader 封装示例 (专注于读取)

ExcelDataReader 非常适合快速将 Excel 数据读取到 DataSet 或 DataTable 中。

using ExcelDataReader;
using System.Data;
using System.Text;public class ExcelReaderHelper
{/// <summary>/// 读取 Excel 文件到 DataSet/// </summary>public DataSet ReadExcelToDataSet(string filePath, bool useHeaderRow = false){Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); // 重要:支持旧编码using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))using (var reader = ExcelReaderFactory.CreateReader(stream)){var configuration = new ExcelDataSetConfiguration(){ConfigureDataTable = (_) => new ExcelDataTableConfiguration(){UseHeaderRow = useHeaderRow // 指示第一行是否作为列名}};return reader.AsDataSet(configuration);}}/// <summary>/// 读取指定工作表到 DataTable/// </summary>public DataTable ReadSheetToDataTable(string filePath, string sheetName = null, bool useHeaderRow = false){DataSet ds = ReadExcelToDataSet(filePath, useHeaderRow);if (sheetName != null){return ds.Tables[sheetName];}else{return ds.Tables[0]; // 返回第一个表}}/// <summary>/// 获取所有工作表名称/// </summary>public List<string> GetSheetNames(string filePath){Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))using (var reader = ExcelReaderFactory.CreateReader(stream)){var result = reader.AsDataSet();return result.Tables.Cast<DataTable>().Select(t => t.TableName).ToList();}}
}

使用 ExcelReaderHelper:

// 使用示例
var excelReader = new ExcelReaderHelper();
try
{// 读取第一个工作表,且第一行是标题DataTable dt = excelReader.ReadSheetToDataTable("data.xlsx", null, true);foreach (DataRow row in dt.Rows){// 处理每一行数据Console.WriteLine($"{row["Name"]}, {row["Age"]}");}// 获取所有工作表名List<string> sheetNames = excelReader.GetSheetNames("data.xlsx");
}
catch (Exception ex)
{Console.WriteLine($"读取失败: {ex.Message}");
}

推荐项目 C# EXCEL完整封装 www.youwenfan.com/contentcnl/112314.html

处理异常和性能

  • 异常处理:务必使用 try-catch 块包裹 Excel 操作代码,妥善处理 IOExceptionUnauthorizedAccessException 等可能出现的异常。
  • 性能:处理大量数据时,注意:
    • 释放资源:使用 using 语句或手动调用 Dispose() 确保释放文件句柄和 COM 对象(如果使用 Interop)。
    • 分批处理:避免一次性将海量数据加载到内存,可以考虑分页读取。
    • 减少交互:使用 Interop 时,尽量减少与 Excel 进程的来回调用。
http://www.jsqmd.com/news/37681/

相关文章:

  • 恒利泰射频器件:国产穿心电容、高Q电容、馈通滤波器
  • 智能字幕校准系统实战(二):6级匹配算法从精确到模糊的全链路解析
  • P11802 【MX-X9-T6】『GROI-R3』Graph
  • 基于MATLAB实现支持向量机(SVM)分类
  • 2025年一代天骄青少年训练营最新推荐:一代天骄寒假班/一代天骄课程/一代天骄成长课程/一代天骄暑假班,专注青少年成长训练,树立个性化教育新标准
  • LLM大模型原理与实践 学习笔记 - yi
  • 为什么要使用immer库?
  • 183天基于资源的约束委派
  • 2025年11月酒店加盟品牌推荐:主流选择对比与高性价比解决方案
  • 疯了还是天才?(下):揭秘ObjectSense的0“AI护城河”——微语言
  • 【完结】AI 编程必备 - 零基础 系统化学Python
  • iOS申请备案号时需要提供Bundle ID、公钥和证书SHA-1指纹
  • 2025最新美国留学机构推荐:资质认证机构清单+ 个性化规划
  • C# DXF文件解析与交互式显示含缩放/拖拽
  • TensorRT - 命令行程序 - 详解
  • Hostinger+Wordpress虚拟主机踩坑:零代码建站体验+绝对不要用支付宝付款!!
  • 2025年PVC酸洗槽实力厂家权威推荐榜单:四氟电加热器/PDF酸洗槽/储罐式换热器源头厂家精选
  • 2025年11月连锁酒店推荐:主流品牌对比高性价比选择指南
  • 20251111Tuesday 代码修改备忘(为视频坐席 转坐席 以及 坐席发起呼叫 是否包含视频 而做的修改)
  • 绩效管理过程中常见的陷阱
  • 2025年11月连锁酒店排行榜推荐:主流品牌对比与高性价比选择指南
  • 全网最容易被忽视但超能打的 6 款工具,不收藏会后悔!
  • 2025年11月沈阳酒店推荐:口碑评价列表实用避坑指南
  • P4784 [BalticOI 2016] 城市 (Day2) 小结
  • 合并
  • Spring-ai 框架源码分析
  • 2025年11月沈阳酒店推荐:口碑评价列表与实用避坑指南
  • 2025年11月geo服务商推荐:知名机构排行榜口碑评价对比指南
  • 2025年11月geo优化服务商推荐:知名机构排行榜与口碑评价对比指南
  • 2025年11月GEO优化推荐:知名机构排行榜口碑评价对比指南