Files
ShrlAlgoToolkit/ShrlAlgoToolkit.RevitAddins/DrawSheet/ExportSchedulesCmd.cs
2026-02-22 20:03:42 +08:00

116 lines
4.3 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.IO;
using System.Windows;
using System.Windows.Documents;
using Autodesk.Revit.DB;
using Melskin.Controls;
using MiniExcelLibs;
using Nice3point.Revit.Toolkit.External;
using ShrlAlgoToolkit.RevitAddins.Common.Assists;
using ShrlAlgoToolkit.RevitAddins.RvView;
using ShrlAlgoToolkit;
using ShrlAlgoToolkit.RevitAddins;
namespace ShrlAlgoToolkit.RevitAddins.DrawSheet;
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
public class ExportSchedulesCmd : ExternalCommand
{
public override void Execute()
{
var list = Document.OfCollector().OfClass(typeof(ViewSchedule)).OfCategory(BuiltInCategory.OST_Schedules).Cast<ViewSchedule>().ToList();
if (!list.Any())
{
ErrorMessage = "当前项目不存在明细表";
Result = Result.Failed;
return;
}
var browserWindow = new VistaFolderBrowserDialog();
browserWindow.ShowDialog();
var selectedPath = browserWindow.SelectedPath;
if (selectedPath == null || !Directory.Exists(selectedPath))
{
//var manager = new NotificationMessageManager();
//manager.CreateMessage().Primary("#1751C3").Background("#333").HasBadge("净高").HasMessage("未选择文件夹").Queue();
Result = Result.Cancelled;
return;
}
var path = $"{selectedPath}\\导出的明细表.xlsx";
ExportScheduleToExcel(list, path);
Common.Assists.WinDialogAssist.OpenFolderAndSelectFile(path);
}
public void ExportScheduleToExcel(List<ViewSchedule> list,string path)
{
var allSheetsData = new Dictionary<string, object>();
foreach (var viewSchedule in list)
{
// 过滤掉无法分配类型的明细表(如修订云线明细表等特殊情况)
if (!viewSchedule.CanHaveTypeAssigned()) continue;
var td = viewSchedule.GetTableData();
var tdd = td.GetSectionData(SectionType.Body);
var nColumns = tdd.NumberOfColumns;
var nRows = tdd.NumberOfRows;
// 如果明细表连标题行都没有,直接跳过
if (nRows == 0) continue;
// 1. 获取第 0 行作为 Excel 的标题 (Headers)
var headers = new List<string>();
for (int j = 0; j < nColumns; j++)
{
string headerName = viewSchedule.GetCellText(SectionType.Body, 0, j);
// 容错处理如果列名为空给个默认名如果列名重复加后缀MiniExcel要求Key唯一
if (string.IsNullOrWhiteSpace(headerName)) headerName = $"Column_{j + 1}";
string uniqueName = headerName;
int counter = 1;
while (headers.Contains(uniqueName))
{
uniqueName = $"{headerName}_{counter++}";
}
headers.Add(uniqueName);
}
// 2. 构造数据行(从第 1 行开始循环)
var rowsData = new List<Dictionary<string, object>>();
for (int i = 1; i < nRows; i++)
{
var row = new Dictionary<string, object>();
for (int j = 0; j < nColumns; j++)
{
// 使用上面取到的 headers[j] 作为 Key
row[headers[j]] = viewSchedule.GetCellText(SectionType.Body, i, j);
}
rowsData.Add(row);
}
// 3. 处理 Sheet 名称非法字符 (Excel 不允许 \ / ? * [ ] : )
string safeSheetName = viewSchedule.Name;
char[] invalidChars = { '\\', '/', '?', '*', '[', ']', ':' };
foreach (var c in invalidChars) safeSheetName = safeSheetName.Replace(c, '_');
if (safeSheetName.Length > 31) safeSheetName = safeSheetName.Substring(0, 31);
allSheetsData.Add(safeSheetName, rowsData);
}
try
{
MiniExcel.SaveAs(path, allSheetsData, overwriteFile: true);
}
catch (IOException)
{
// 提示文件被占用
MessageBox.Show("请先关闭已打开的 Excel 文件后再尝试保存。");
}
}
}