Files
SzmediTools/Szmedi.RvKits/ModelManager/ReportGenerator.cs
2025-12-23 21:37:02 +08:00

239 lines
9.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<ElementDiffInfo> 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<ElementDiffInfo> 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<ReportRow> 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;
}
}
}