using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using EPPlus.Core.Extensions; using OfficeOpenXml; using OfficeOpenXml.Style; namespace Szmedi.RvKits.ModelManager { public static class ReportGenerator { public static string Generate(List results) { if (results == null || results.Count == 0) return "未发现构件差异。"; StringBuilder sb = new StringBuilder(); sb.AppendLine("=== Revit 版本对比报告 ==="); // 1. 新增 var added = results.Where(r => r.Status == DiffType.Added).ToList(); if (added.Any()) { sb.AppendLine($"\n【新增构件】: {added.Count}"); foreach (var item in added) { sb.Append($" [+] ID:{item.ElementId} | {item.CategoryName}: {item.Name}"); // 如果 LocationChange 不为空,说明计算出了坐标 if (item.LocationChange != null && !string.IsNullOrEmpty(item.LocationChange.NewValue)) { sb.Append($" @ {item.LocationChange.NewValue}"); } sb.AppendLine(); } } // 2. 修改 var modified = results.Where(r => r.Status == DiffType.Modified).ToList(); if (modified.Any()) { sb.AppendLine($"\n【修改构件】: {modified.Count}"); foreach (var item in modified) { sb.AppendLine($" [*] ID:{item.ElementId} | {item.CategoryName}: {item.Name}"); // 显示位置移动 if (item.LocationChange != null) { sb.AppendLine($" [位置移动]"); sb.AppendLine($" 原: {item.LocationChange.OldValue}"); sb.AppendLine($" 新: {item.LocationChange.NewValue}"); } // 显示参数变化 foreach (var p in item.ParamChanges) { sb.AppendLine($" > {p.ParamName}: \"{p.OldValue}\" -> \"{p.NewValue}\""); } sb.AppendLine(); } } // 3. 删除 var deleted = results.Where(r => r.Status == DiffType.Deleted).ToList(); if (deleted.Any()) { sb.AppendLine($"\n【删除构件】: {deleted.Count}"); foreach (var item in deleted) { sb.AppendLine($" [-] ID:{item.ElementId} | {item.CategoryName}: {item.Name}"); } } return sb.ToString(); } public static void ToExcel(string excelPath, List infos) { FileInfo fi = new(excelPath); ExcelPackage package = infos.ToWorksheet("构件数量变动对比表") .WithConfiguration(cfg => cfg.WithColumnConfiguration(c => c.AutoFit())) .ToExcelPackage(); package.SaveAs(fi); } public static void Export(List data, string filePath) { var file = new FileInfo(filePath); if (file.Exists) { try { file.Delete(); } catch { throw new Exception("无法覆盖文件,请确保Excel已关闭。"); } } using (var package = new ExcelPackage(file)) { var ws = package.Workbook.Worksheets.Add("构件对比表"); // --- 1. 设置表头 (模仿图片样式) --- // 设置列宽 ws.Column(1).Width = 6; // 序号 ws.Column(2).Width = 10; // 变更类型 // 变更后 (3-7) ws.Column(3).Width = 10; // ID ws.Column(4).Width = 15; // 类型 ws.Column(5).Width = 25; // 设计属性 ws.Column(6).Width = 12; // 出量 ws.Column(7).Width = 12; // 坐标 // 变更前 (8-12) ws.Column(8).Width = 10; ws.Column(9).Width = 15; ws.Column(10).Width = 25; ws.Column(11).Width = 12; ws.Column(12).Width = 12; // 第一行:合并的大标题 ws.Cells[1, 1].Value = "序号"; ws.Cells[1, 1, 2, 1].Merge = true; ws.Cells[1, 2].Value = "变更\n类型"; ws.Cells[1, 2, 2, 2].Merge = true; ws.Cells[1, 3].Value = "变更后构件"; ws.Cells[1, 3, 1, 7].Merge = true; ws.Cells[1, 8].Value = "变更前构件"; ws.Cells[1, 8, 1, 12].Merge = true; // 第二行:子标题 string[] headers = { "图元ID", "类型", "设计属性", "出量属性", "坐标" }; for (int i = 0; i < 5; i++) { ws.Cells[2, 3 + i].Value = headers[i]; ws.Cells[2, 8 + i].Value = headers[i]; } // 表头样式 using (var range = ws.Cells[1, 1, 2, 12]) { range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; range.Style.VerticalAlignment = ExcelVerticalAlignment.Center; range.Style.Font.Bold = true; range.Style.Fill.PatternType = ExcelFillStyle.Solid; range.Style.Fill.BackgroundColor.SetColor(Color.LightGray); range.Style.Border.Top.Style = ExcelBorderStyle.Thin; range.Style.Border.Bottom.Style = ExcelBorderStyle.Thin; range.Style.Border.Left.Style = ExcelBorderStyle.Thin; range.Style.Border.Right.Style = ExcelBorderStyle.Thin; range.Style.WrapText = true; // 允许表头换行 } // --- 2. 填充数据 --- int rowIdx = 3; foreach (var item in data) { // 序号 & 类型 ws.Cells[rowIdx, 1].Value = item.Index; ws.Cells[rowIdx, 2].Value = item.ChangeType; // 设置变更类型颜色 var typeCell = ws.Cells[rowIdx, 2]; if (item.ChangeType.Contains("新增")) typeCell.Style.Font.Color.SetColor(Color.Green); else if (item.ChangeType.Contains("删除")) typeCell.Style.Font.Color.SetColor(Color.Red); else typeCell.Style.Font.Color.SetColor(Color.Blue); // --- 变更后数据 (After) --- if (item.After.IsEmpty) { // 如果为空,合并5列显示“无” ws.Cells[rowIdx, 3].Value = "无"; ws.Cells[rowIdx, 3, rowIdx, 7].Merge = true; } else { FillData(ws, rowIdx, 3, item.After); } // --- 变更前数据 (Before) --- if (item.Before.IsEmpty) { // 如果为空,合并5列显示“无” ws.Cells[rowIdx, 8].Value = "无"; ws.Cells[rowIdx, 8, rowIdx, 12].Merge = true; } else { FillData(ws, rowIdx, 8, item.Before); } rowIdx++; } // --- 3. 全局样式调整 --- if (data.Count > 0) { var dataRange = ws.Cells[3, 1, rowIdx - 1, 12]; // 边框 dataRange.Style.Border.Top.Style = ExcelBorderStyle.Thin; dataRange.Style.Border.Bottom.Style = ExcelBorderStyle.Thin; dataRange.Style.Border.Left.Style = ExcelBorderStyle.Thin; dataRange.Style.Border.Right.Style = ExcelBorderStyle.Thin; // 对齐 dataRange.Style.VerticalAlignment = ExcelVerticalAlignment.Center; dataRange.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; // 特殊列左对齐 (属性列) ws.Cells[3, 5, rowIdx - 1, 5].Style.HorizontalAlignment = ExcelHorizontalAlignment.Left; // After Props ws.Cells[3, 10, rowIdx - 1, 10].Style.HorizontalAlignment = ExcelHorizontalAlignment.Left; // Before Props ws.Cells[3, 7, rowIdx - 1, 7].Style.HorizontalAlignment = ExcelHorizontalAlignment.Left; // After Coords ws.Cells[3, 12, rowIdx - 1, 12].Style.HorizontalAlignment = ExcelHorizontalAlignment.Left; // Before Coords // 开启自动换行 (关键,否则 \n 不生效) dataRange.Style.WrapText = true; } package.Save(); } } private static void FillData(ExcelWorksheet ws, int row, int col, ComponentState s) { ws.Cells[row, col].Value = s.ElementId; ws.Cells[row, col + 1].Value = s.TypeName; ws.Cells[row, col + 2].Value = s.DesignProps; ws.Cells[row, col + 3].Value = s.QuantityProps; ws.Cells[row, col + 4].Value = s.Coordinates; } } }