功能更新

This commit is contained in:
GG Z
2026-02-22 21:12:18 +08:00
parent 7e2d5be3cd
commit 5a3a368a2e
10 changed files with 894 additions and 7 deletions

View File

@@ -0,0 +1,35 @@
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.DirectContext3D;
using Nice3point.Revit.Toolkit.External;
using ShrlAlgoToolkit.RevitAddins.Common.Assists;
using ShrlAlgoToolkit.RevitAddins.Standardizer;
namespace ShrlAlgoToolkit.RevitAddins.Standardizer
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class WriteParametersCmd : ExternalCommand
{
public override void Execute()
{
//System.Windows.MessageBox.Show(
// "若当前视图不是三维且所有元素可见则不会修改参数值",
// "注意",
// System.Windows.MessageBoxButton.OK,
// System.Windows.MessageBoxImage.Information
//);
//WriteParametersWin win = WpfSingletonHelper<WriteParametersWin>.GetInstance(out bool isNewCreate);
//if (isNewCreate)
//{
// win.DataContext = new WriteParametersViewModel(UiDocument);
// win.ShowAhead();
//}
//win.Activate();
WinDialogAssist.ShowOrActivate<WriteParametersView, WriteParametersViewModel>(UiDocument);
}
}
}

View File

@@ -0,0 +1,127 @@
<ui:MelWindow
x:Class="ShrlAlgoToolkit.RevitAddins.Standardizer.WriteParametersView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ShrlAlgoToolkit.RevitAddins.Standardizer"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="https://github.com/ShrlAlgo/Melskin"
Title="实例参数编辑"
Width="500"
Height="420"
d:DataContext="{d:DesignInstance Type=local:WriteParametersViewModel}"
mc:Ignorable="d">
<Window.Resources>
<ResourceDictionary Source="pack://application:,,,/ShrlAlgoToolkit.RevitAddins;component/WPFUI.xaml" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DataGrid
Grid.Row="0"
Grid.Column="0"
d:ItemsSource="{d:SampleData}"
AutoGenerateColumns="False"
CanUserAddRows="False"
ItemsSource="{Binding Items}">
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Name}"
Header="参数名"
IsReadOnly="True" />
<DataGridTextColumn Binding="{Binding Value, UpdateSourceTrigger=PropertyChanged}" Header="参数值" />
</DataGrid.Columns>
</DataGrid>
<UniformGrid
Grid.Row="1"
Grid.Column="0"
HorizontalAlignment="Center"
Rows="1">
<CheckBox
MinWidth="5"
Margin="5"
HorizontalAlignment="Center"
Content="仅选中"
IsChecked="{Binding IsSelectedItems}"
ToolTip="选中元素修改,否则全部可见(临时隐藏也算不可见)元素修改" />
<CheckBox
MinWidth="5"
Margin="5"
HorizontalAlignment="Center"
Content="覆盖现值"
IsChecked="{Binding IsOverride}"
ToolTip="已有值会被表中填写值覆盖" />
<ListBox
Margin="5"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<b:Interaction.Triggers>
<b:EventTrigger EventName="SelectionChanged">
<b:InvokeCommandAction Command="{Binding InitCommand}" CommandParameter="{Binding SelectedIndex, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}}" />
</b:EventTrigger>
</b:Interaction.Triggers>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem Content="土建" ToolTip="加载默认土建填写参数" />
<ListBoxItem Content="机电" ToolTip="加载默认机电填写参数" />
</ListBox>
</UniformGrid>
<UniformGrid
Grid.Row="2"
Grid.Column="0"
Rows="1">
<TextBox
Margin="5"
ui:InputAssist.PlaceholderText="Excel文件路径"
Text="{Binding ExcelPath, UpdateSourceTrigger=PropertyChanged}"
ToolTip="输入路径回车读取文件">
<TextBox.InputBindings>
<KeyBinding Key="Return" Command="{Binding OpenExcelCommand}" />
</TextBox.InputBindings>
<!--<b:Interaction.Triggers>
<b:EventTrigger EventName="LostFocus">
<b:InvokeCommandAction Command="{Binding OpenExcelCommand}" CommandParameter="{Binding Text, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TextBox}}" />
</b:EventTrigger>
</b:Interaction.Triggers>-->
</TextBox>
<!--<TextBox md:HintAssist.Hint="忽略属性" Text="{Binding ExcelPath, UpdateSourceTrigger=PropertyChanged}" ToolTip="输入路径回车读取文件">
<TextBox.InputBindings>
<KeyBinding Key="Return" Command="{Binding OpenExcelCommand}" />
</TextBox.InputBindings>
</TextBox>-->
<Button
Margin="5"
Command="{Binding BrowserExcelFileCommand}"
Content="打开Excel文件" />
<Button
Margin="5"
Command="{Binding GetParamsCommand}"
Content="从构件提取参数" />
</UniformGrid>
<UniformGrid
Grid.Row="3"
Grid.Column="0"
HorizontalAlignment="Center"
Rows="1">
<Button
Margin="5"
Command="{Binding ExportExcelCommand}"
Content="导出Excel文件" />
<Button
Margin="5"
HorizontalAlignment="Center"
Command="{Binding WriteParamsCommand}"
Content="填写属性值"
ToolTip="深圳轨道交通标准的属性未填值会默认为“/”并且会跳过修改“ID-100-编号”" />
</UniformGrid>
</Grid>
</ui:MelWindow>

View File

@@ -0,0 +1,16 @@
using System.Windows;
using System.Windows.Media;
namespace ShrlAlgoToolkit.RevitAddins.Standardizer
{
/// <summary>
/// WriteParametersWin.xaml 的交互逻辑
/// </summary>
public partial class WriteParametersView
{
public WriteParametersView()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,359 @@
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using Autodesk.Revit.DB;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Win32;
using MiniExcelLibs.Attributes;
using Nice3point.Revit.Toolkit.External.Handlers;
using ShrlAlgoToolkit.RevitAddins;
using ShrlAlgoToolkit.RevitAddins.Common.Assists;
using ShrlAlgoToolkit.RevitAddins.Common.Extensions;
namespace ShrlAlgoToolkit.RevitAddins.Standardizer;
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 ParameterModel(string Name, object Value);
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(ExportExcelCommand))]
[NotifyCanExecuteChangedFor(nameof(WriteParamsCommand))]
private List<ParameterModel> items;
[ObservableProperty]
private string excelPath;
private readonly UIDocument uiDocument;
private bool HasItems => Items?.Any() == true;
[RelayCommand]
private void GetParams()
{
Items = null;
List<ParameterModel> models = [];
Document doc = uiDocument.Document;
try
{
Reference reference = uiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element, "请选择提取参数的元素");
Element elem = doc.GetElement(reference);
foreach (Parameter param in elem.Parameters)
{
if (!param.HasValue || string.IsNullOrEmpty(param.AsString()))
{
models.Add(new ParameterModel() { Name = param.Definition.Name });
}
}
Items = models.OrderBy(m => m.Name).ToList();
}
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 = "Excel文件(xlsx)|*.xlsx",
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
};
if (dialog.ShowDialog() != true)
{
return;
}
string excel = dialog.FileName;
FileInfo fi = new(excel);
Dictionary<string, object> data = new() { { "参数表", Items } };
data.SaveAsExcel(excel);
MessageBoxResult result = MessageBox.Show("是否打开Excel表", "提示", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
Process.Start(excel);
}
}
[RelayCommand(CanExecute = nameof(HasItems))]
private void WriteParams()
{
Document doc = uiDocument.Document;
List<Element> elements = IsSelectedItems
? uiDocument.Selection.GetElementIds().Select(id => doc.GetElement(id)).ToList()
: new FilteredElementCollector(doc, doc.ActiveView.Id)
.WhereElementIsNotElementType()
.ToElements()
.Where(
e =>
e.CanHaveTypeAssigned()
&& e.HasPhases()
&& e.get_BoundingBox(doc.ActiveView) != null
&& e.Category is { Parent: null, CategoryType: CategoryType.Model }
)
.ToList();
StringBuilder sb = new();
handler.Raise(_ =>
{
using (TransactionGroup transG = new(doc, "填写属性值"))
{
transG.Start();
foreach (Element elem in elements)
{
if (!elem.IsValidObject)
{
continue;
}
using Transaction trans = new(doc, "填写属性值");
//FailureHandlingOptions options = trans.GetFailureHandlingOptions();
//FailuresPreProcessor failuresProcessor = new();
//options.SetFailuresPreprocessor(failuresProcessor);
//trans.SetFailureHandlingOptions(options);
trans.Start();
Regex regex = new(@"^\D{2}-\d00");
//将“”空值填写“/”
foreach (Parameter parameter in elem.Parameters)
{
//if (parameter.Definition.Name == "ID-100-编号")
//{
// continue;
//}
//不为空时,跳过设置“/”
if (!(string.IsNullOrEmpty(parameter.AsString()) && string.IsNullOrEmpty(parameter.AsValueString())))
{
continue;
}
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 (ParameterModel item in Items)
{
Parameter p1 = elem.GetParameters(item.Name).FirstOrDefault();
if (p1 == null)
{
sb.AppendLine($"构件类别:{elem.Category};构件名:{elem.Name}构件ID{elem.Id};参数名:{item.Name};异常原因:参数不存在");
continue;
}
//if (p1.Definition.Name == "ID-100-编号")
//{
// continue;
//}
try
{
if (
IsOverride
|| (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;
}
}
}
//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)
{
LogAssist.WriteTextFile( sb.ToString(), "修改异常问题");
}
MessageBox.Show("修改参数完成!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
});
}
[RelayCommand]
private void BrowserExcelFile()
{
OpenFileDialog dialog =
new()
{
CheckFileExists = true,
Filter = "Excel文件(*.xlsx)|*.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)
{
Items= [.. path.ReadExcel<ParameterModel>()];
}
private static Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
{
if (!args.Name.Contains("ComponentModel.Annotations"))
{
return null;
}
string assemblyFile = Path.Combine(Variables.DirAssembly, "System.ComponentModel.Annotations.dll");
return File.Exists(assemblyFile) ? Assembly.LoadFrom(assemblyFile) : null;
}
[RelayCommand]
private void Init(int index)
{
if (index == 0)
{
Items = GetInitCivilParameterList();
}
else
{
Items = index == 1 ? GetInitMEPParameterList() : null;
}
}
private List<ParameterModel> 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<ParameterModel> 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 = "/" },
];
}
}
public class ParameterModel
{
[ExcelColumn(Name="参数名")]
public string Name { get; set; }
[ExcelColumn(Name ="参数值")]
public string Value { get; set; }
}