Skip to content
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
8ea8f86
Переработка механизма копирования параметров, теперь сначала создаютс…
Redomine Apr 23, 2026
c415a0c
Вычитка кода
Redomine Apr 24, 2026
3e20683
Вычитка кода
Redomine Apr 24, 2026
2447b95
Упрощение алгоритма
Redomine May 6, 2026
755b50d
Вычитка кода
Redomine May 6, 2026
35e9891
Добавлена ошибка при отсутствии параметра в шаблоне
Redomine May 6, 2026
b01fc12
1) Унификация имен - RevitParam это revitParam и производные, а Param…
Redomine May 6, 2026
7fd9dff
Правка имен констант и методов Parameter -> Param
Redomine May 8, 2026
355f0e7
Некорректное логгирование ошибки создания спецификаций заменено на вы…
Redomine May 12, 2026
f609617
1) Скорректирована группировка. Теперь группируем непосредственно по …
Redomine May 12, 2026
4c7c966
Revert "Переработка механизма копирования параметров, теперь сначала …
Redomine May 13, 2026
e953200
Полная смена логики. Теперь перед копированием параметры проверяются,…
Redomine May 14, 2026
092eb74
Вычитка кода, убрал статику
Redomine May 14, 2026
a3c8d65
Модификация SplitRevitParamsByBinding. Все что не общий параметр сраз…
Redomine May 25, 2026
6d0574f
Дополнил документацию
Redomine May 25, 2026
93ff71a
GetRevitSharedParamElement заменен на bool HasRevitElementParam
Redomine May 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 161 additions & 11 deletions src/dosymep.Bim4Everyone/Templates/ProjectParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Text;
using System.Threading.Tasks;

using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;

using dosymep.Bim4Everyone;
Expand All @@ -15,11 +14,15 @@
using dosymep.Revit;
using dosymep.SimpleServices;

using Application = Autodesk.Revit.ApplicationServices.Application;

namespace dosymep.Bim4Everyone.Templates {
/// <summary>
/// Класс по копирование параметров проекта.
/// </summary>
public class ProjectParameters {
private const string ParamTransferScheduleNamePrefix = "BIM4E_PARAM_TRANSFER_";

private readonly ILoggerService _loggerService;

/// <summary>
Expand Down Expand Up @@ -304,7 +307,12 @@ private static bool CopyViewSchedule(Document source, Document target, bool remo
return false;
}

ICollection<ElementId> copiedElements = ElementTransformUtils.CopyElements(source, new[] { viewSchedule.Id }, target, Transform.Identity, new CopyPasteOptions());
ICollection<ElementId> copiedElements = ElementTransformUtils.CopyElements(
source,
new[] { viewSchedule.Id },
target,
Transform.Identity,
CreateCopyPasteOptions());
if(removeSchedule) {
// Удаляем скопированный вид,
// так как он нужен был для переноса параметра
Expand Down Expand Up @@ -332,7 +340,12 @@ private static bool CopyViewSchedules(Document source, Document target, bool rem
return false;
}

ICollection<ElementId> copiedElements = ElementTransformUtils.CopyElements(source, viewSchedules.Select(item => item.Id).ToArray(), target, Transform.Identity, new CopyPasteOptions());
ICollection<ElementId> copiedElements = ElementTransformUtils.CopyElements(
source,
viewSchedules.Select(item => item.Id).ToArray(),
target,
Transform.Identity,
CreateCopyPasteOptions());
if(removeSchedule) {
// Удаляем скопированные виды,
// так как они нужны были для переноса параметра
Expand Down Expand Up @@ -367,19 +380,156 @@ private void RevitParamsCopy(Document target, IEnumerable<RevitParam> revitParam
source.Close(false);
}
}


private void RevitParamsCopy(
Document source,
Document target,
IEnumerable<RevitParam> revitParams)
{
(ICollection<RevitParam> regularCopyParams, ICollection<RevitParam> paramsWithoutBinding)
= SplitRevitParamsByBinding(target, revitParams);

ParameterElement[] regularCopyParamsElements = GetRevitParamElements(source, regularCopyParams);
ParameterElement[] paramsWithoutBindingElements = GetRevitParamElements(source, paramsWithoutBinding);

if(regularCopyParamsElements.Length > 0) {
ElementTransformUtils.CopyElements(
source,
regularCopyParamsElements.Select(item => item.Id).ToArray(),
target,
Transform.Identity,
new CopyPasteOptions());
}

if(paramsWithoutBindingElements.Length > 0) {
CopyParamsByMultiCategorySchedule(
source,
target,
paramsWithoutBindingElements);
}
}

private void RevitParamsCopy(Document source, Document target, IEnumerable<RevitParam> revitParams) {
ElementId[] sourceParamElementIds = revitParams
.Where(item => !item.IsExistsParam(target))
/// <summary>
/// Возвращает элементы параметров из документа.
/// </summary>
/// <param name="source">Документ с параметрами.</param>
/// <param name="revitParams">Параметры.</param>
/// <returns>Возвращает элементы параметров.</returns>
private ParameterElement[] GetRevitParamElements(Document source, IEnumerable<RevitParam> revitParams) {
return revitParams
.Select(item => item.GetRevitParamElement(source))
.Where(item => item != null)
.Select(item => item.Id)
.ToArray();
}

if(sourceParamElementIds.Length > 0) {
ElementTransformUtils.CopyElements(source, sourceParamElementIds, target,
Transform.Identity,
new CopyPasteOptions());
/// <summary>
/// Разделяет параметры на параметры для обычного копирования и общие параметры без привязки к категориям.
/// </summary>
/// <param name="target">Целевой документ.</param>
/// <param name="revitParams">Параметры, которые нужно разделить.</param>
/// <returns>Возвращает параметры для обычного копирования и параметры без привязки.</returns>
private (
ICollection<RevitParam> RegularCopyParams,
ICollection<RevitParam> ParamsWithoutBinding) SplitRevitParamsByBinding(
Document target,
IEnumerable<RevitParam> revitParams) {
var regularCopyParams = new List<RevitParam>();
var paramsWithoutBinding = new List<RevitParam>();

foreach(RevitParam revitParam in revitParams) {
if(!(revitParam is SharedParam)) {
regularCopyParams.Add(revitParam);
continue;
}

if(!HasRevitElementParam(target, revitParam)) {
regularCopyParams.Add(revitParam);
continue;
}

(Definition Definition, Binding Binding) paramBinding = revitParam.GetParamBinding(target);
if(paramBinding.Definition == null || paramBinding.Binding == null) {
paramsWithoutBinding.Add(revitParam);
}
}

return (regularCopyParams, paramsWithoutBinding);
}

/// <summary>
/// Проверяет, существует ли элемент параметра в документе.
/// </summary>
/// <param name="document">Документ.</param>
/// <param name="revitParam">Параметр Revit.</param>
/// <returns>Возвращает true, если элемент параметра существует, иначе false.</returns>
private bool HasRevitElementParam(Document document, RevitParam revitParam) {
if(!(revitParam is SharedParam sharedParam)) {
return false;
}

return new FilteredElementCollector(document)
.OfClass(typeof(SharedParameterElement))
.OfType<SharedParameterElement>()
.Any(item => item.GuidValue.Equals(sharedParam.Guid));
}

/// <summary>
/// Копирует параметры через временную мультикатегорийную спецификацию.
/// </summary>
/// <param name="source">Файл шаблона.</param>
/// <param name="target">Целевой документ.</param>
/// <param name="paramsElements">Параметры из шаблона.</param>
private void CopyParamsByMultiCategorySchedule(
Document source,
Document target,
IEnumerable<ParameterElement> paramsElements) {
ViewSchedule viewSchedule = null;

using(var transaction = source.StartTransaction("Создание временной спецификации параметров")) {
viewSchedule = ViewSchedule.CreateSchedule(source, ElementId.InvalidElementId);
viewSchedule.Name = $"{ParamTransferScheduleNamePrefix}{Guid.NewGuid():N}";

foreach(ParameterElement param in paramsElements) {
SchedulableField schedulableField = viewSchedule.Definition
.GetSchedulableFields()
.FirstOrDefault(item => item.ParameterId == param.Id);
if(schedulableField == null) {
throw new InvalidOperationException(
$"Не удалось добавить параметр '{param.Name}' во временную спецификацию.");
}

viewSchedule.Definition.AddField(schedulableField);
}

transaction.Commit();
}

CopyViewSchedule(source, target, true, viewSchedule);
}

/// <summary>
/// Создает настройки копирования элементов.
/// </summary>
/// <returns>Возвращает настройки копирования элементов.</returns>
private static CopyPasteOptions CreateCopyPasteOptions() {
var copyPasteOptions = new CopyPasteOptions();
copyPasteOptions.SetDuplicateTypeNamesHandler(new UseDestinationDuplicateTypeNamesHandler());

return copyPasteOptions;
}

/// <summary>
/// Обработчик совпадений имен типов при копировании элементов.
/// </summary>
private class UseDestinationDuplicateTypeNamesHandler : IDuplicateTypeNamesHandler {
/// <summary>
/// Обрабатывает совпадения имен типов при копировании элементов.
/// </summary>
/// <param name="args">Аргументы обработчика совпадений имен типов.</param>
/// <returns>Возвращает действие для обработки совпадающих типов.</returns>
public DuplicateTypeAction OnDuplicateTypeNamesFound(DuplicateTypeNamesHandlerArgs args) {
return DuplicateTypeAction.UseDestinationTypes;
}
}

Expand Down
Loading