EPPLUS——CAD c#读写EXCEL的第三方库
EPPLUS(可支持NET35)
在 CAD 的 C# 二次开发中,使用 EPPLUS 库处理 Excel 文件具有以下显著优点,尤其在兼容性、便捷性和性能等方面契合 CAD 项目的需求:
1. 跨.NET 版本兼容性强,适配 CAD 多环境部署
- 多框架支持:EPPLUS 从早期的.NET 3.5 到最新的.NET 4.8 均能稳定运行,而 CAD 二次开发中常面临不同 AutoCAD 版本(如 2014-2024)对应不同.NET 框架的情况(例如老版本 CAD 可能基于.NET 3.5,新版本基于.NET 4.5+)。这种兼容性避免了因框架不匹配导致的开发适配问题,无需为不同 CAD 版本单独调整代码。
- 部署轻量:无需额外安装.NET 扩展包,只需引用 EPPLUS.dll 即可集成,适合 CAD 插件的轻量化部署(CAD 插件通常要求安装包简洁,避免依赖冲突)。
2. 无需安装 Office,解决 CAD 环境依赖痛点
- 无 COM 组件依赖:传统 Excel 操作库(如 Microsoft.Office.Interop.Excel)依赖本地 Office 安装,而 CAD 服务器或用户环境可能未安装 Office,或存在版本冲突(如 CAD 后台服务场景)。EPPLUS 基于纯.NET 代码,通过 EPPlus 命名空间直接操作 Excel 文件(.xlsx 格式),完全脱离 Office 环境,避免因 COM 组件引发的权限、稳定性问题(如 CAD 进程中 COM 组件崩溃)。
- 跨平台潜力:虽然 CAD 主要运行在 Windows,但 EPPLUS 支持.NET Core(需适配版本),若未来涉及 CAD 跨平台开发(如 Linux 环境的轻量化 CAD 工具),可无缝迁移。
3. 高效处理 CAD 数据,适配工程场景需求
- 大数据量导出:CAD 图纸常包含大量构件、属性数据(如管线参数、构件坐标),EPPLUS 采用流式处理(Streaming 模式),可高效生成包含数万行数据的 Excel 文件,内存占用低,避免 CAD 进程因内存溢出卡顿。例如,导出建筑模型的所有构件属性时,性能优势明显。
- 格式与图表定制:支持自定义 Excel 格式(如单元格样式、行列冻结、条件格式)、生成工程报表常用的图表(如工程量柱状图、构件分布饼图),便于将 CAD 数据可视化。例如,可将图纸中的钢筋分布数据直接生成 Excel 图表,辅助施工交底。
- 批量导入支持:支持从 Excel 导入参数到 CAD 模型(如通过 Excel 表格批量创建构件),EPPLUS 的解析效率高,可处理包含复杂公式或合并单元格的工程表格,减少手动录入误差。
4. 开发便捷性与社区支持
- API 简洁易用:EPPLUS 的 API 设计贴近 Excel 操作逻辑(如 Workbook→Worksheet→Cell 层级操作),C# 开发者可快速上手,无需深入学习复杂模型。例如,读取 CAD 选中构件的属性并写入 Excel,代码量少且逻辑清晰。
- 开源与商业灵活选择:免费版(LGPL 协议)适合个人或开源项目,商业版(EPPlus Professional)提供更完善的技术支持和企业授权,满足 CAD 项目的商业发布需求(如设计院插件需合规授权)。
- 错误处理友好:支持 Excel 文件异常解析(如损坏文件)和内存管理,减少 CAD 插件因 Excel 操作导致的崩溃风险,提升用户体验。
5. 与 CAD 对象模型无缝集成
- 数据映射便捷:可直接将 CAD 对象(如 Entity、BlockReference)的属性(如坐标、图层、自定义参数)映射到 Excel 单元格,无需复杂转换。例如,遍历图纸中所有门窗构件,将其尺寸、材质等属性导出到 Excel 表格。
- 事务性操作支持:配合 CAD 的事务机制(如 Transaction),可在 Excel 操作中结合 CAD 的撤销 / 重做功能,确保数据一致性(如导入 Excel 参数失败时,CAD 操作可回滚)。
总结
在 CAD C# 二次开发中,EPPLUS 凭借跨框架兼容性、无 Office 依赖、高效数据处理能力,成为工程数据报表生成、批量参数导入导出的理想选择。尤其在需要适配不同 CAD 版本、避免环境依赖、处理大量工程数据的场景下,其优势更为突出,可显著提升插件的稳定性和开发效率。
public class EPPlus{// 主方法:导出数据库到Excel[CommandMethod("Epp")]public void 读取数据库ToExcel_EPPlus(){// ====================== 步骤1:配置数据库连接 ======================string connectionString ="Data Source=rm-wz9a";// 生成Excel路径(桌面+时间戳命名)string fileName = string.Format("{0:yyyyMMddHHmmss}.xlsx", DateTime.Now);string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);string filePath = Path.Combine(desktopPath, fileName);using (ExcelPackage package = new ExcelPackage()){try{// ====================== 步骤4:为每个表创建Sheet并写入数据 ======================foreach (string tableName in tableNames){try{// 创建工作表(表名作为Sheet名,限制31字符)string sheetName = tableName.Length > 31 ? tableName.Substring(0, 31) : tableName;ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(sheetName);// 读取表结构和数据(通过自定义类TableData)TableData tableData = ReadTableData(connection, tableName);//if (tableData.Headers.Count == 0 || tableData.Data.Count == 0)//{// Z.ed.WriteMessage($"表 {tableName} 无数据或结构,跳过");// continue;//}// ====================== 步骤5:写入表头(带样式) ======================for (int col = 0; col < tableData.Headers.Count; col++){worksheet.Cells[1, col + 1].Value = tableData.Headers[col];// 表头样式:加粗、浅蓝背景、自动换行(EPPlus 4.x 样式设置)worksheet.Cells[1, col + 1].Style.Font.Bold = true;worksheet.Cells[1, col + 1].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;worksheet.Cells[1, col + 1].Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightBlue);worksheet.Cells[1, col + 1].Style.WrapText = true;}// 步骤6:写入表数据并设置格式for (int row = 0; row < tableData.Data.Count; row++){for (int col = 0; col < tableData.Data[row].Length; col++){object cellValue = tableData.Data[row][col];worksheet.Cells[row + 2, col + 1].Value = cellValue;// 根据字段类型设置 Excel 格式Type columnType = tableData.ColumnTypes[col];if (columnType == typeof(DateTime)){// 日期时间格式(Excel 自定义格式)worksheet.Cells[row + 2, col + 1].Style.Numberformat.Format = "yyyy-mm-dd hh:mm:ss";}else if (columnType == typeof(decimal) || columnType == typeof(double)){// 数值格式(保留2位小数)worksheet.Cells[row + 2, col + 1].Style.Numberformat.Format = "#,##0.00";}// 可扩展其他类型(如整数、布尔值等)}}// 定义表格范围(表头+数据行):第1行到最后一行数据,第1列到最后一列int lastRow = tableData.Data.Count + 1; // 数据行从第2行开始,最后一行是数据行数+1(表头占1行)int lastCol = tableData.Headers.Count;var tableRange = worksheet.Cells[1, 1, lastRow, lastCol];// 设置外边框(上下左右)tableRange.Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;tableRange.Style.Border.Top.Color.SetColor(System.Drawing.Color.Black);tableRange.Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;tableRange.Style.Border.Bottom.Color.SetColor(System.Drawing.Color.Black);tableRange.Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;tableRange.Style.Border.Left.Color.SetColor(System.Drawing.Color.Black);tableRange.Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;tableRange.Style.Border.Right.Color.SetColor(System.Drawing.Color.Black);// ====================== 设置内部横线(单元格之间的横线) // 范围:第1行到倒数第1行(最后一行的下边框是外框,无需重复设置)var horizontalRange = worksheet.Cells[1, 1, lastRow - 1, lastCol];horizontalRange.Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;horizontalRange.Style.Border.Bottom.Color.SetColor(System.Drawing.Color.Black);// ====================== 设置内部竖线(单元格之间的竖线) ======================// 范围:第1列到倒数第1列(最后一列的右边框是外框,无需重复设置)var verticalRange = worksheet.Cells[1, 1, lastRow, lastCol - 1];verticalRange.Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;verticalRange.Style.Border.Right.Color.SetColor(System.Drawing.Color.Black);// 自动调整列宽worksheet.Cells[1, 1, tableData.Data.Count + 1, tableData.Headers.Count].AutoFitColumns();}catch (Exception ex){Z.ed.WriteMessage($"处理表 {tableName} 失败: {ex.Message}");}}}// ====================== 步骤7:保存Excel文件 ======================FileInfo fileInfo = new FileInfo(filePath);package.SaveAs(fileInfo);Z.ed.WriteMessage($"Excel文件已保存至: {filePath}");// 自动打开文件(可选)System.Diagnostics.Process.Start("explorer.exe", filePath);}catch (Exception ex){Z.ed.WriteMessage($"系统错误: {ex.Message}");}}}public class TableData{public List<string> Headers { get; set; } // 表头(列名+类型)public List<Type> ColumnTypes { get; set; } // 新增:字段类型(如 typeof(DateTime))public List<object[]> Data { get; set; } // 表数据}}