Hi Jeremy,
I attached my code to work with the first option you suggested. It works perfectly fine when originDocument is different than destinationDocument, but when I'm trying to copy in the same document, "Mark" parameter values are not copied to the copied elements. Even that I have verify in the line before the copyElements, that the elements to be copied have the Mark Parameter Value.
¿Any Thoughts?
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.DB.Visual;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using RevitMV.Auth.services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
namespace RevitMV
{
[Transaction(TransactionMode.Manual)]
class RB_LS_CopyPasteLosas : MN_MasterClass
{
public override Result ExecuteTool(ExternalCommandData commandData, ref string message, ElementSet elements)
{
UIApplication rvtUIApp = commandData.Application;
UIDocument rvtUIDoc = rvtUIApp.ActiveUIDocument;
Autodesk.Revit.ApplicationServices.Application revitApp = rvtUIApp.Application;
Document m_rvtDoc = rvtUIDoc.Document;
List<View> openViews = GetAllOpenViews(rvtUIApp);
try
{
View originView;
View destinationView;
IList<Reference> refs;
Document originDoc;
Document destinationDoc;
XYZ puntoInicio;
XYZ puntoFinal;
int copiedBarsCount = 0;
int pastedBarsCount = 0;
List<ElementId> detailItemBarras_list = new List<ElementId>();
List<List<ElementId>> rebarToCopy_list = new List<List<ElementId>>();
List<ElementId> rebarToCopy_list_flat = new List<ElementId>();
List<ElementId> rbcCopiedIds = new List<ElementId>();
List<ElementId> rbCopiedIds = new List<ElementId>();
using (Transaction trans1 = new Transaction(m_rvtDoc))
{
trans1.Start("CopyPaste - Copiar Barras");
Selection sel = rvtUIDoc.Selection;
ElementoSimboloFiltro selFilter = new ElementoSimboloFiltro();
refs = sel.PickObjects(ObjectType.Element, selFilter, "Elija las barras a aplicar CopyPaste");
copiedBarsCount = refs.Count;
//Ocultamos los rebars para mejorar seleccion e puntos
RB_LS_ArmarLosas.HideCategoryTemporary(m_rvtDoc, BuiltInCategory.OST_Rebar);
//Seleccionamos punto de origen
Selection selection1 = rvtUIDoc.Selection;
puntoInicio = selection1.PickPoint("Seleccione punto de origen, Se copiara desde el punto de origen al punto de destino");
originDoc = rvtUIApp.ActiveUIDocument.Document;
originView = originDoc.ActiveView;
//Buscamos los detail item y los Rebars a ser copiados.
foreach (var reference in refs)
{
//Elemento simbolico de losas
Element detailItemBarras = originDoc.GetElement(reference.ElementId) as Element;
//Obtenemos los rebar containers
List<RebarContainer> rebarContainerList = RB_LS_ArmarLosas.GetRebarContainersFromSymbol(originDoc, detailItemBarras);
List<Rebar> rebarList = RB_LS_ArmarLosas.GetRebarFromSymbol(originDoc, detailItemBarras);
//Creamos la lista de ids de los rebar containers
List<ElementId> rebarContainersToCopy = rebarContainerList.Select(rc => rc.Id).ToList();
List<ElementId> rebarToCopy = rebarList.Select(rb => rb.Id).ToList();
detailItemBarras_list.Add(detailItemBarras.Id);
rebarToCopy_list.Add(rebarContainersToCopy.Count > 0 ? rebarContainersToCopy : rebarToCopy);
}
rebarToCopy_list_flat = rebarToCopy_list.SelectMany(innerList => innerList).ToList();
//CopyElement Entrega los elementos copiados en desorden, por lo que:
//Agregamos parametro para identificar las barras copiadas, en el parametro Mark se agrega el indice de la lista.
detailItemBarras_list.ForEach(e => originDoc.GetElement(e).LookupParameter("Mark").Set(detailItemBarras_list.IndexOf(e).ToString()));
//Agregamos parametro para identificar las barras copiadas, en el parametro Mark se agrega el indice de la lista
rebarToCopy_list_flat.ForEach(e => originDoc.GetElement(e).LookupParameter("Mark").Set(rebarToCopy_list_flat.IndexOf(e).ToString()));
var openDocuments = GetAllOpenDocumnets(rvtUIApp);
//Cuadro de dialogo para seleccion vista de destino
var dlg = new RB_DG_LS_CopyPaste(openDocuments);
dlg.ShowDialog();
if (dlg.DialogResult == false) return Result.Failed;
destinationView = dlg.SelectedView;
destinationDoc = destinationView.Document;
//Se muestran rebars nuevamente
RB_LS_ArmarLosas.DeactivateTemporaryView(m_rvtDoc);
//Make visible Mark Values for next transaction
originDoc.Regenerate();
trans1.Commit();
}
//Activamos el documento de destino
if (destinationDoc.PathName != originDoc.PathName)
{
rvtUIDoc=new UIDocument(destinationView.Document);
rvtUIApp.OpenAndActivateDocument(destinationDoc.PathName);
}
else
{
destinationDoc = originDoc;
}
//Change la vista activa
rvtUIDoc.ActiveView = destinationView;
rvtUIDoc.RefreshActiveView();
//Hacemos la seleccion de destino
Selection selection2 = rvtUIDoc.Selection;
puntoFinal = selection2.PickPoint("Seleccione punto de destino, Se copiara desde el punto de origen al punto de destino");
destinationDoc = rvtUIApp.ActiveUIDocument.Document;
using (Transaction trans2 = new Transaction(destinationDoc))
{
try
{
trans2.Start("CopyPaste - Pegar Barras");
destinationDoc.Regenerate();
//transformation
Transform transform = Transform.CreateTranslation(new XYZ(puntoFinal.X - puntoInicio.X, puntoFinal.Y - puntoInicio.Y, destinationView.GenLevel.ProjectElevation - originView.GenLevel.ProjectElevation));
Transform transformSymbol = Transform.CreateTranslation(new XYZ(puntoFinal.X - puntoInicio.X, puntoFinal.Y - puntoInicio.Y, 0));
//Copypasteoptiones
CopyPasteOptions copyPasteOptions = new CopyPasteOptions();
//Copiamos los symbolos de las losas
List<ElementId> simbCopiedId_list = ElementTransformUtils.CopyElements(originView, detailItemBarras_list, destinationView, transformSymbol, copyPasteOptions).ToList();
//Copiamos los Rebar
rbcCopiedIds = ElementTransformUtils.CopyElements(originDoc, rebarToCopy_list_flat, destinationDoc, transform, copyPasteOptions).ToList();
//Ordenamos los ids copiados por el parametro Mark
simbCopiedId_list = simbCopiedId_list.OrderBy(e => int.Parse(destinationDoc.GetElement(e).LookupParameter("Mark").AsValueString())).ToList();
//Ordenamos los ids copiados por el parametro Mark, producto que CopyElement devuelve una lista desordenada.
rbcCopiedIds = rbcCopiedIds.OrderBy(e => int.Parse(destinationDoc.GetElement(e).LookupParameter("Mark").AsValueString())).ToList();
//Eliminamos el Mark para el documento de destino.
rbcCopiedIds.ForEach(e => destinationDoc.GetElement(e).LookupParameter("Mark").Set(""));
simbCopiedId_list.ForEach(e => destinationDoc.GetElement(e).LookupParameter("Mark").Set(""));
//Reconstruimos las listas de los ids copiados
List<List<ElementId>> rbcCopiedIds_list = new List<List<ElementId>>();
int index = 0;
foreach (var simbCopiedId in simbCopiedId_list)
{
List<ElementId> rbcCopiedIds_aux = new List<ElementId>();
rbcCopiedIds_aux = rbcCopiedIds.GetRange(index, rebarToCopy_list[index].Count);
rbcCopiedIds_list.Add(rbcCopiedIds_aux);
index += rebarToCopy_list[index].Count;
}
//Asignamos los hosts y los UID a los rebar containers y rebar
pastedBarsCount = 0;
List<ElementId> simbolsToDelete = new List<ElementId>();
List<ElementId> rebarToDelete = new List<ElementId>();
foreach (var simbCopiedId in simbCopiedId_list)
{
FamilyInstance copiedSymbolElement = destinationDoc.GetElement(simbCopiedId) as FamilyInstance;
List<Floor> losas_host = RB_LS_ArmarLosas.GetLosaHostFromSymbol(destinationDoc, copiedSymbolElement);
if (losas_host.Count == 0)
{
//Borramos los elementos copiados si no tienen host
simbolsToDelete.Add(simbCopiedId);
rebarToDelete.AddRange(rbcCopiedIds_list[simbCopiedId_list.IndexOf(simbCopiedId)]);
continue;
}
Floor losaHost = losas_host?.First();
foreach (ElementId rbcId in rbcCopiedIds_list[simbCopiedId_list.IndexOf(simbCopiedId)])
{
Element rebarCopied = destinationDoc.GetElement(rbcId);
if (rebarCopied is RebarContainer rbcCopied)
{
rbcCopied.SetHostId(destinationDoc, losaHost.Id);
FN_Rebar.AssignRbcParam(rbcCopied, FN_params.RB_uId, copiedSymbolElement.UniqueId, ParamType.s);
rbcCopied.SetUnobscuredInView(destinationView, true);
}
else if (rebarCopied is Rebar rbCopied)
{
rbCopied.SetHostId(destinationDoc, losaHost.Id);
rbCopied.LookupParameter(FN_params.RB_uId).Set(copiedSymbolElement.UniqueId);
rbCopied.SetUnobscuredInView(destinationView, true);
}
}
pastedBarsCount++;
}
//Borrar elementos sin host
destinationDoc.Delete(simbolsToDelete);
destinationDoc.Delete(rebarToDelete);
trans2.Commit();
}
catch (Exception e)
{
LoggerMain.Logger.Error(e, "Error al hacer CopyPaste Losas");
TaskDialog.Show("Error", e.Message);
}
}
using (Transaction trans3=new Transaction(originDoc))
{
trans3.Start("Borramos parametro Mark de barras y simbolos de Origen");
try
{
////Borramos el parametro Mark para el documento de origen.
rebarToCopy_list_flat.ForEach(e => originDoc.GetElement(e).LookupParameter("Mark").Set(""));
detailItemBarras_list.ForEach(e => originDoc.GetElement(e).LookupParameter("Mark").Set(""));
}
catch (Exception e)
{
LoggerMain.Logger.Error(e, "Error al borrar el Mark");
TaskDialog.Show("Error", e.Message);
}
trans3.Commit();
}
if (destinationView.Document != originDoc)
{
rvtUIDoc = new UIDocument(destinationView.Document);
rvtUIApp.OpenAndActivateDocument(destinationDoc.PathName);
}
//Change view
rvtUIDoc.ActiveView = destinationView;
rvtUIDoc.RefreshActiveView();
//Mensaje final
TaskDialog.Show("Copy Paste exitoso", "Barras copiadas: " + copiedBarsCount + "\nBarras pegadas: " + pastedBarsCount);
}
catch (Exception e)
{
LoggerMain.Logger.Fatal(e, "Error al hacer CopyPaste Losas");
TaskDialog.Show("Error", e.Message);
return Result.Failed;
}
LoggerMain.ProcesoExitosoInfo();
return Result.Succeeded;
}
public class ElementoSimboloFiltro : ISelectionFilter
{
public bool AllowElement(Element elem)
{
if (elem.Category != null)
{
if (elem.Name.Contains("SPR_SYM_Losa") || elem.Name.Contains("Armaduras con empalmes"))
{
return true;
}
}
return false;
}
public bool AllowReference(Reference reference, XYZ xyz)
{
return true;
}
}
public List<View> GetAllOpenViews(UIApplication uiApp)
{
List<View> openViews = new List<View>();
foreach (Document doc in uiApp.Application.Documents)
{
// Get the active document
UIDocument uiDoc = new UIDocument(doc);
// Get all open UIViews
IList<UIView> uiViews = uiDoc.GetOpenUIViews();
foreach (UIView uiView in uiViews)
{
// Get the view ID from the UIView and convert it to a View object
View view = doc.GetElement(uiView.ViewId) as View;
if (view != null)
{
openViews.Add(view);
}
}
}
return openViews;
}
public List<Document> GetAllOpenDocumnets(UIApplication uiApp)
{
List<Document> openDocs = new List<Document>();
foreach (Document doc in uiApp.Application.Documents)
{
openDocs.Add(doc);
}
return openDocs;
}
}
}