c#中三方库操作excel多种方式,对比如下:
综合对比表
特性 | NPOI | Aspose.Cells | COM Interop (Excel.Application) |
---|---|---|---|
授权与成本 | 免费开源 (Apache 2.0) | 商业授权 (约$3,000/开发者) | 免费 (需安装Office) |
依赖项 | 纯.NET库 (无依赖) | 纯.NET库 (无依赖) | 需安装Microsoft Office |
部署环境 | 任意环境 (服务器/客户端) | 任意环境 (服务器/客户端) | 仅客户端 (需安装Office) |
性能 | ⭐⭐⭐⭐ (较快) | ⭐⭐⭐⭐ (优化良好) | ⭐ (非常慢) |
功能完整性 | ⭐⭐⭐ (基础功能完善) | ⭐⭐⭐⭐⭐ (100%功能覆盖) | ⭐⭐⭐⭐⭐ (原生支持) |
内存占用 | 50-100 MB | 100-200 MB | 300-500 MB+ |
稳定性 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐ (常崩溃) |
多线程支持 | ✅ 良好 | ✅ 优秀 | ❌ 极差 |
文档支持 | GitHub Wiki | 专业技术文档+支持 | MSDN文档 |
学习曲线 | 中等 | 中等 | 复杂 |
版本兼容性 | 向后兼容好 | 版本升级需注意 | Office版本强依赖 |
详细分析
1. NPOI (POI for .NET)
优点:
cs
using (var fs = new FileStream("test.xlsx", FileMode.Create)) { IWorkbook workbook = new XSSFWorkbook(); // xlsx格式 ISheet sheet = workbook.CreateSheet("Sheet1"); // 添加数据 IRow row = sheet.CreateRow(0); row.CreateCell(0).SetCellValue("Hello"); row.CreateCell(1).SetCellValue("NPOI"); workbook.Write(fs); }
-
💰 零成本:完全免费,Apache 2.0许可
-
🚀 高性能:内存操作,处理速度快
-
☁️ 无依赖:不依赖Office,适合服务器端使用
-
📦 轻量级:NuGet包仅5-10MB
-
🔄 格式支持:完美支持xls/xlsx格式
缺点:
-
⚠️ 高级功能有限:
-
数据透视表支持不完善
-
复杂图表功能较弱
-
条件格式实现复杂
-
-
📚 文档不足:官方文档较简略,依赖社区示例
-
🧩 API设计:部分接口不够直观
适用场景: 报表导出、数据导入导出、简单格式操作等基础需求
2. Aspose.Cells
优点:
-
🧩 功能全面:
-
100% Excel功能覆盖
-
完美支持数据透视表、高级图表
-
公式计算引擎
-
格式转换(PDF/HTML/CSV等)
-
3. COM Interop (Excel.Application)
优点:
🛡️ 稳定可靠:商业级质量保证
-
📊 高性能处理:优化的大数据量处理
-
🔄 版本兼容:支持从Excel 97到最新格式
-
🔌 原生支持:100% Excel功能兼容
-
🧩 VBA移植:可直接转换VBA代码
-
🎨 所见即所得:实时可视化操作
最终建议
-
优先选择NPOI - 对于大多数场景足够且免费
-
投资Aspose当:
-
需要处理复杂Excel功能
-
要求高稳定性
-
预算允许($3,000+/开发者)
-
-
完全避免COM互操作 - 除非在受控客户端环境且无替代方案
您遇到的"Evaluation Only"问题正是Aspose商业授权的典型表现。若预算有限,迁移到NPOI是明智选择,尽管可能需要调整部分高级功能实现方式。
cs
public void Npoi()
{
try
{
// 步骤1:创建 XSSF 工作簿(对应 .xlsx 格式)
using (IWorkbook workbook = new XSSFWorkbook())
{
// 步骤2:删除默认创建的所有工作表(新建工作簿默认有一个 "Sheet1")
while (workbook.NumberOfSheets > 0)
{
workbook.RemoveSheetAt(0); // 按索引删除工作表(从0开始)
}
// 步骤3:创建名为 "乘法表" 的新工作表
ISheet sheet = workbook.CreateSheet("乘法表");
// 步骤4:设置表头(第一行第一列,合并单元格 A1-I1)
IRow headerRow = sheet.CreateRow(0); // 行索引从0开始(第一行)
ICell headerCell = headerRow.CreateCell(0); // 列索引从0开始(第一列)
headerCell.SetCellValue("九九乘法表");
// 合并单元格(行范围:0-0,列范围:0-8,对应 A1 到 I1)
CellRangeAddress headerMergeRegion = new CellRangeAddress(0, 0, 0, 8);
sheet.AddMergedRegion(headerMergeRegion);
// 步骤5:生成九九乘法表内容(从第二行开始,行索引1)
for (int i = 1; i <= 9; i++) // 外层循环:被乘数(1-9)
{
IRow dataRow = sheet.CreateRow(i); // 创建第 i+1 行(行索引i)
for (int j = 1; j <= i; j++) // 内层循环:乘数(1到被乘数)
{
ICell cell = dataRow.CreateCell(j - 1); // 列索引 = j-1(从0开始)
cell.SetCellValue($"{j}*{i}={i * j}"); // 格式示例:"2*3=6"
}
}
// 步骤6:设置列宽(可选,根据内容自适应宽度)
for (int col = 0; col < 9; col++)
{
sheet.AutoSizeColumn(col); // 自动调整列宽以适应内容
}
// 调用格式设置函数(核心封装功能)
SetSheetFormat(sheet);
// 步骤7:获取桌面路径并保存文件
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string savePath = Path.Combine(desktopPath, "九九乘法表.xlsx");
using (FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write))
{
workbook.Write(fs); // 将工作簿写入文件流
}
Z.ed.WriteMessage($"Excel 文件已成功保存到:{savePath}");
}
}
catch (Exception ex)
{
Z.ed.WriteMessage($"操作失败,错误信息:{ex.Message}");
}
}
/// <summary>
/// 封装:设置工作表格式(字体加粗、边框、对齐、自动列宽)
/// </summary>
/// <param name="sheet">需要设置格式的工作表</param>
static void SetSheetFormat(ISheet sheet)
{
IWorkbook workbook = sheet.Workbook; // 获取工作簿引用(用于创建样式)
#region 样式定义
// 表头字体样式(加粗)
IFont headerFont = workbook.CreateFont();
headerFont.FontHeightInPoints = 12; // 字体大小
headerFont.Boldweight = (short)FontBoldWeight.Bold; // 加粗
// 内容单元格样式(边框+居中对齐)
ICellStyle contentStyle = workbook.CreateCellStyle();
contentStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; // 水平居中
contentStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center; // 垂直居中
// 设置黑色细边框(上下左右)
contentStyle.BorderTop = BorderStyle.Thin;
contentStyle.BorderBottom = BorderStyle.Thin;
contentStyle.BorderLeft = BorderStyle.Thin;
contentStyle.BorderRight = BorderStyle.Thin;
contentStyle.TopBorderColor = IndexedColors.Black.Index;
contentStyle.BottomBorderColor = IndexedColors.Black.Index;
contentStyle.LeftBorderColor = IndexedColors.Black.Index;
contentStyle.RightBorderColor = IndexedColors.Black.Index;
// 表头单元格样式(合并后单独设置)
ICellStyle headerStyle = workbook.CreateCellStyle();
headerStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
headerStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;
headerStyle.SetFont(headerFont); // 应用加粗字体
#endregion
#region 处理表头格式
// 表头行(第0行)
IRow headerRow = sheet.GetRow(0);
if (headerRow != null)
{
// 合并后的表头单元格(A1)
ICell headerCell = headerRow.GetCell(0);
if (headerCell != null)
{
headerCell.CellStyle = headerStyle; // 应用表头样式
}
}
#endregion
#region 获取表格最大行和列
int maxRow = sheet.LastRowNum; // 最后一行索引(从0开始)
int maxCol = 0;
// 遍历所有行获取最大列数
for (int rowNum = 0; rowNum <= maxRow; rowNum++)
{
IRow row = sheet.GetRow(rowNum);
if (row != null && row.LastCellNum > maxCol)
{
maxCol = row.LastCellNum; // 记录当前行的最大列数
}
}
#endregion
#region 应用内容格式(所有单元格)
for (int rowNum = 0; rowNum <= maxRow; rowNum++)
{
IRow row = sheet.GetRow(rowNum) ?? sheet.CreateRow(rowNum); // 确保行存在
for (int colNum = 0; colNum < maxCol; colNum++)
{
ICell cell = row.GetCell(colNum) ?? row.CreateCell(colNum); // 确保单元格存在
cell.CellStyle = contentStyle; // 应用内容样式(边框+对齐)
}
}
#endregion
#region 自动调整列宽
for (int colNum = 0; colNum < maxCol; colNum++)
{
sheet.AutoSizeColumn(colNum); // 自动调整列宽
// 适当增加列宽(避免内容过紧)
sheet.SetColumnWidth(colNum, sheet.GetColumnWidth(colNum) + 1000);
}
#endregion
}
/// <summary>
/// 生成九九乘法表数据到指定工作表
/// </summary>
/// <param name="sheet">目标工作表</param>
唯一文件名:
cs
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string dateTimeStr = DateTime.Now.ToString("yyyyMMdd_HHmmss");
string savePath = Path.Combine(desktopPath, $"九九乘法表_{dateTimeStr}.xlsx");