2025-09-16 16:06:41 +08:00
|
|
|
|
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
using System.Windows;
|
|
|
|
|
|
|
|
|
|
|
|
using Autodesk.Revit.DB;
|
|
|
|
|
|
using Autodesk.Revit.UI;
|
|
|
|
|
|
|
|
|
|
|
|
using EPPlus.Core.Extensions;
|
|
|
|
|
|
using EPPlus.Core.Extensions.Attributes;
|
|
|
|
|
|
|
|
|
|
|
|
using Microsoft.Win32;
|
|
|
|
|
|
|
|
|
|
|
|
using Nice3point.Revit.Toolkit.External.Handlers;
|
|
|
|
|
|
|
|
|
|
|
|
using OfficeOpenXml;
|
|
|
|
|
|
|
|
|
|
|
|
using Szmedi.RvKits.Assists;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Szmedi.RvKits.InfoManager;
|
|
|
|
|
|
|
|
|
|
|
|
public partial class WriteParametersViewModel : ObservableObject
|
|
|
|
|
|
{
|
|
|
|
|
|
public WriteParametersViewModel(UIDocument uIDocument)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.uiDocument = uIDocument;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private readonly ActionEventHandler handler = new();
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private bool isSelectedItems;
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private bool isOverride;
|
|
|
|
|
|
|
|
|
|
|
|
//record class ParameterEditModel(string Name, object Value);
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
[NotifyCanExecuteChangedFor(nameof(ExportExcelCommand))]
|
|
|
|
|
|
[NotifyCanExecuteChangedFor(nameof(WriteParamsCommand))]
|
|
|
|
|
|
private List<ParameterEditModel> items;
|
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
|
private string excelPath;
|
|
|
|
|
|
private readonly UIDocument uiDocument;
|
|
|
|
|
|
private bool HasItems => Items?.Any() == true;
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void GetParams()
|
|
|
|
|
|
{
|
|
|
|
|
|
Items = null;
|
|
|
|
|
|
List<ParameterEditModel> models = [];
|
|
|
|
|
|
var doc = uiDocument.Document;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var reference = uiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, "请选择提取参数的元素");
|
|
|
|
|
|
var elem = doc.GetElement(reference);
|
|
|
|
|
|
if (elem == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
foreach (Parameter param in elem.Parameters)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (param.IsReadOnly || param.StorageType == StorageType.ElementId || (param.HasValue || !string.IsNullOrEmpty(param.AsString())))
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
models.Add(new ParameterEditModel { Name = param.Definition.Name });
|
|
|
|
|
|
}
|
|
|
|
|
|
Items = [.. models.OrderBy(m => m.Name)];
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Autodesk.Revit.Exceptions.OperationCanceledException) { }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void OpenExcel()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ExcelPath.StartsWith("\""))
|
|
|
|
|
|
{
|
|
|
|
|
|
ExcelPath = ExcelPath.TrimStart('\"');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (ExcelPath.EndsWith("\""))
|
|
|
|
|
|
{
|
|
|
|
|
|
ExcelPath = ExcelPath.TrimEnd('\"');
|
|
|
|
|
|
}
|
|
|
|
|
|
if (File.Exists(ExcelPath))
|
|
|
|
|
|
{
|
|
|
|
|
|
FileInfo file = new(ExcelPath);
|
|
|
|
|
|
if (file.Extension != ".xlsx")
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("请选择xlsx格式的Excel文件");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ReadExcel(ExcelPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("文件路径有误");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand(CanExecute = nameof(HasItems))]
|
|
|
|
|
|
private void ExportExcel()
|
|
|
|
|
|
{
|
|
|
|
|
|
SaveFileDialog dialog =
|
|
|
|
|
|
new()
|
|
|
|
|
|
{
|
|
|
|
|
|
Filter = WinDialogAssists.CreateFilter("Excel文件", "xlsx"),
|
|
|
|
|
|
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
|
|
|
|
|
|
};
|
|
|
|
|
|
if (dialog.ShowDialog() != true)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var excel = dialog.FileName;
|
|
|
|
|
|
FileInfo fi = new(excel);
|
|
|
|
|
|
var package = Items
|
|
|
|
|
|
.ToWorksheet("参数表")
|
|
|
|
|
|
.WithConfiguration(cfg => cfg.WithColumnConfiguration(c => c.AutoFit()))
|
|
|
|
|
|
.ToExcelPackage();
|
|
|
|
|
|
|
|
|
|
|
|
package.SaveAs(fi);
|
|
|
|
|
|
|
|
|
|
|
|
var result = MessageBox.Show("是否打开Excel表?", "提示", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
|
|
|
|
|
if (result == MessageBoxResult.Yes)
|
|
|
|
|
|
{
|
|
|
|
|
|
Process.Start(excel);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand(CanExecute = nameof(HasItems))]
|
|
|
|
|
|
private void WriteParams()
|
|
|
|
|
|
{
|
|
|
|
|
|
var doc = uiDocument.Document;
|
|
|
|
|
|
var elements = IsSelectedItems
|
|
|
|
|
|
? uiDocument.Selection.GetElementIds().Select(id => doc.GetElement(id)).ToList()
|
|
|
|
|
|
: [.. doc.OfAllModelCollector()];
|
|
|
|
|
|
if (elements == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("没有找到模型元素", "错误");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
StringBuilder sb = new();
|
|
|
|
|
|
handler.Raise(_ =>
|
|
|
|
|
|
{
|
|
|
|
|
|
using (TransactionGroup transG = new(doc, "填写属性值"))
|
|
|
|
|
|
{
|
|
|
|
|
|
transG.Start();
|
|
|
|
|
|
foreach (var elem in elements)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (elem.IsValidObject)
|
|
|
|
|
|
{
|
|
|
|
|
|
using Transaction trans = new(doc, "填写属性值");
|
|
|
|
|
|
//FailureHandlingOptions options = trans.GetFailureHandlingOptions();
|
|
|
|
|
|
//FailuresPreProcessor failuresProcessor = new();
|
|
|
|
|
|
//options.SetFailuresPreprocessor(failuresProcessor);
|
|
|
|
|
|
//trans.SetFailureHandlingOptions(options);
|
|
|
|
|
|
trans.Start();
|
|
|
|
|
|
Regex regex = new(@"^[A-Z]{2}-\d00-");
|
|
|
|
|
|
foreach (Parameter parameter in elem.Parameters)
|
|
|
|
|
|
{
|
|
|
|
|
|
//if (parameter.Definition.Name == "ID-100-编号")
|
|
|
|
|
|
//{
|
|
|
|
|
|
// continue;
|
|
|
|
|
|
//}
|
|
|
|
|
|
//不为空时,跳过设置“/”或“0”即跳过已有值的情况
|
|
|
|
|
|
if (!(string.IsNullOrEmpty(parameter.AsString()) && string.IsNullOrEmpty(parameter.AsValueString())))
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
//只针对轨道交通参数设置0或/
|
|
|
|
|
|
if (regex.IsMatch(parameter.Definition.Name) && !parameter.IsReadOnly)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (parameter.StorageType is StorageType.Integer or StorageType.Double)
|
|
|
|
|
|
{
|
|
|
|
|
|
parameter.Set(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (parameter.StorageType == StorageType.String)
|
|
|
|
|
|
{
|
|
|
|
|
|
parameter.Set("/");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
doc.Regenerate();
|
|
|
|
|
|
//要修改的参数值,去掉参数值为空的参数
|
|
|
|
|
|
//foreach (var item in Items.Where(item => !string.IsNullOrEmpty(item.Value)))
|
|
|
|
|
|
//要修改的参数值,参数值为空,则清空参数值
|
|
|
|
|
|
foreach (var item in Items)
|
|
|
|
|
|
{
|
|
|
|
|
|
//if (item.Value==null)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// continue;
|
|
|
|
|
|
//}
|
|
|
|
|
|
var p1 = elem.GetParameters(item.Name).FirstOrDefault();
|
|
|
|
|
|
if (p1 == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
sb.AppendLine($"构件类别:{elem.Category.Name};构件名:{elem.Name};构件ID:{elem.Id};参数名:{item.Name};异常原因:参数不存在");
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (p1.IsReadOnly)
|
|
|
|
|
|
{
|
|
|
|
|
|
sb.AppendLine($"构件类别:{elem.Category.Name};构件名:{elem.Name};构件ID:{elem.Id};参数名:{item.Name};异常原因:只读参数");
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
//if (p1 == null || p1.Definition.Name == "ID-100-编号")
|
|
|
|
|
|
//{
|
|
|
|
|
|
// continue;
|
|
|
|
|
|
//}
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
//因为上方步骤已经将值全部修改为0或/,所以IsOverride或轨道交通参数值为/,0,两种情况都需要覆盖原值
|
|
|
|
|
|
if (
|
|
|
|
|
|
IsOverride
|
|
|
|
|
|
|| (
|
|
|
|
|
|
regex.IsMatch(p1.Definition.Name)
|
|
|
|
|
|
&& (
|
|
|
|
|
|
(p1.AsString() == "/" || p1.AsValueString() == "/")
|
|
|
|
|
|
|| (p1.AsString() == "0" || p1.AsValueString() == "0")
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
) //如果覆盖则填写,否则不操作
|
|
|
|
|
|
{
|
|
|
|
|
|
if (p1?.IsReadOnly == false)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (p1.StorageType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case StorageType.None:
|
|
|
|
|
|
break;
|
|
|
|
|
|
case StorageType.Integer:
|
|
|
|
|
|
p1.Set(Convert.ToInt16(item.Value));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case StorageType.Double:
|
|
|
|
|
|
p1.Set(Convert.ToDouble(item.Value));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case StorageType.String:
|
|
|
|
|
|
p1.Set(Convert.ToString(item.Value));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case StorageType.ElementId:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception exception)
|
|
|
|
|
|
{
|
|
|
|
|
|
sb.AppendLine(
|
|
|
|
|
|
$"构件类别:{elem.Category};构件名:{elem.Name};构件ID:{elem.Id};参数名:{p1.Definition.Name};异常原因:{exception.Message}"
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
trans.Commit();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
transG.Assimilate();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (sb.Length > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
LogAssists.WriteTxtFile("修改异常问题", sb.ToString());
|
|
|
|
|
|
}
|
|
|
|
|
|
MessageBox.Show("修改参数完成!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void BrowserExcelFile()
|
|
|
|
|
|
{
|
|
|
|
|
|
OpenFileDialog dialog =
|
|
|
|
|
|
new()
|
|
|
|
|
|
{
|
|
|
|
|
|
CheckFileExists = true,
|
|
|
|
|
|
Filter = WinDialogAssists.CreateFilter("Excel文件", "xlsx"),
|
|
|
|
|
|
Multiselect = false,
|
|
|
|
|
|
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
|
|
|
|
|
|
};
|
|
|
|
|
|
if (dialog.ShowDialog() != true)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
//Items?.Clear();
|
|
|
|
|
|
ExcelPath = dialog.FileName;
|
|
|
|
|
|
ReadExcel(dialog.FileName);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void ReadExcel(string path)
|
|
|
|
|
|
{
|
|
|
|
|
|
FileInfo fi = new(path);
|
|
|
|
|
|
using ExcelPackage package = new(fi);
|
|
|
|
|
|
var worksheet = package.Workbook.Worksheets[1];
|
|
|
|
|
|
////获取worksheet的行数
|
|
|
|
|
|
//int rows = worksheet .Dimension.End.Row;
|
|
|
|
|
|
////获取worksheet的列数
|
|
|
|
|
|
//int cols = worksheet .Dimension.End.Column;
|
|
|
|
|
|
worksheet.TrimLastEmptyRows();
|
|
|
|
|
|
|
|
|
|
|
|
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
Items = package.ToList<ParameterEditModel>(1, configuration => configuration.SkipCastingErrors());
|
|
|
|
|
|
|
|
|
|
|
|
//foreach (ParameterEditModel eamFacility in Items) { }
|
|
|
|
|
|
|
|
|
|
|
|
//var groups = Facilities.GroupBy(x => x.Story);
|
|
|
|
|
|
//foreach (var ZoomRBGroup in groups)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// if (ZoomRBGroup.Key == null)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// continue;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// StoryCodeMappers.Add(new() { Story = ZoomRBGroup.Key, });
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
//IsMapper = false;
|
|
|
|
|
|
//IsComparison = false;
|
|
|
|
|
|
//Instances.ForEach(ins => ins.IsMapped = false);
|
|
|
|
|
|
}
|
2026-01-16 17:07:43 +08:00
|
|
|
|
catch (EPPlus.Core.Extensions.Exceptions.ExcelValidationException ex)
|
2025-09-16 16:06:41 +08:00
|
|
|
|
{
|
2026-01-16 17:07:43 +08:00
|
|
|
|
System.Windows.MessageBox.Show("列名不存在或不匹配或检查表头是否存在换行或多余文字。", ex.Message);
|
2025-09-16 16:06:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomainOnAssemblyResolve;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!args.Name.Contains("ComponentModel.Annotations"))
|
|
|
|
|
|
{
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var assemblyFile = Path.Combine(GlobalVariables.DirAssembly, "System.ComponentModel.Annotations.dll");
|
|
|
|
|
|
return File.Exists(assemblyFile) ? Assembly.LoadFrom(assemblyFile) : null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
|
|
private void Init(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
Items = index == 0 ? GetInitCivilParameterList() : index == 1 ? GetInitMEPParameterList() : null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private List<ParameterEditModel> GetInitCivilParameterList()
|
|
|
|
|
|
{
|
|
|
|
|
|
return
|
|
|
|
|
|
[
|
|
|
|
|
|
new() { Name = "AM-200-模型权属单位", Value = "深圳市地铁集团有限公司" },
|
|
|
|
|
|
new() { Name = "AM-200-资产权属单位", Value = "深圳市地铁集团有限公司" },
|
|
|
|
|
|
new() { Name = "CM-100-创建单位", Value = "深圳市市政设计研究院有限公司" },
|
|
|
|
|
|
new() { Name = "ID-200-BIM对象分类编码执行标准", Value = "《城市轨道交通工程信息模型分类和编码标准》SJG102" },
|
|
|
|
|
|
new() { Name = "CM-100-校审单位", Value = "数云科际(深圳)技术有限公司" },
|
|
|
|
|
|
new() { Name = "FM-200-产品寿命", Value = "100" },
|
|
|
|
|
|
new() { Name = "FM-200-使用年限", Value = "100" },
|
|
|
|
|
|
new() { Name = "TC-400-设计使用年限", Value = "100" }
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private List<ParameterEditModel> GetInitMEPParameterList()
|
|
|
|
|
|
{
|
|
|
|
|
|
return
|
|
|
|
|
|
[
|
|
|
|
|
|
new() { Name = "AM-200-模型权属单位", Value = "深圳市地铁集团有限公司" },
|
|
|
|
|
|
new() { Name = "AM-200-资产权属单位", Value = "深圳市地铁集团有限公司" },
|
|
|
|
|
|
new() { Name = "CM-100-创建单位", Value = "深圳市市政设计研究院有限公司" },
|
|
|
|
|
|
new() { Name = "CM-100-校审单位", Value = "深圳市市政设计研究院有限公司" },
|
|
|
|
|
|
new() { Name = "CM-100-创建人及联系方式", Value = "/" },
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 参数编辑的模型
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class ParameterEditModel
|
|
|
|
|
|
{
|
|
|
|
|
|
[ExcelTableColumn("参数名")]
|
|
|
|
|
|
public string Name { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
[ExcelTableColumn("参数值")]
|
|
|
|
|
|
public string Value { get; set; }
|
|
|
|
|
|
}
|