I tried to copy elements from a Revit Link and A Revit document from the background including option to overwrite existing elements definition or types in the current active revit project file. When try with a Revit document in the background it doesn’t overwrite the existing, it renames the existing adding a sequence number at the end as suffix and also duplicates family types. Although if copying from a link it overwrites, why is that? Is there any option to overwrite existing elements when copying from a Document?
that is how revit treats copy between files. you will have to load the families in question into your project dont have a solution for you in dynamo. sry
In my experience most objects behave this way, or sometimes even do not copy. The best approach I’ve found to be absolutely sure to update to the new type copied in is:
Temporarily rename type in project to replace
Copy in new type
Swap all old types to new type
Delete old type
Not simple for some cases (e.g. view templates, stacked walls etc.), but haven’t seen a sure way to replace one with the other. The Revit API and Revit don’t behave as such such so not sure a simple method is available.
In the case of loadable families, they are a bit easier. You can use IFamilyLoadOption interface to specify the overwrite behavior. Not like this for system families however.
what i mean is if you have to seperate revit files open and try to copy between them revit behaves exactly the way you describe.
if you have the same file linked in to the project and you use bind link it will instead write over if prompt to do so.
what i am trying to say is you need to get your script to either bind the elements from your link to your project or load the families you want from a folder system (for instance you saved all families in the project to a folder on desktop)
why the comments are so negative? I had good experience with Revit Links but not with Document in background to try to copy things, I would like to know if the options or method to copy should be different to make it work as copying from links.
I am not going to use Bind anymore because all the bind elements appear moved vertically unknown distance from the original and Autodesk never resolved this, I wrote a claim and had videocall more than year ago about this behaviour.
not really sure what in my comments you percive as negative, just stating this is how Revit behaves. and you would have to change your approch of solving the problem.
The best method for copy in background for me is this approach, I assume you’ve got that part sorted already though. If I come across better inbuilt ways versus rename/reassign/delete I’ll return to this thread, but for now it’s the best I’ve known of. I know other tools such Ideate Style Manager work that way also for style consolidation so I assume it’s probably the best option for now.
Post some code so we can have a look at what the issue is. Things like category, units, element associations, style, etc. all impact the action of ‘copying’ significantly. Otherwise all the community can do is guess, and guesses by their nature will come across as less helpful and will feel more negative.
One thought you could try without posting the code… since you have copying elements from links working, why not link the document into the project you want to copy into instead of opening it in the background, then copy the element from the link, and then unload the link.
I was thinking the same, but wanted to try both cases as sometimes I cannot edit or add links to the Revit files, so open document in Background.
Here a sample of the code I was writting and ended in this questions, if you understand it and can give a solution from this I would appreciate it.
You need to feed Input 0 with a Document and input 1 with elements to copy from the document
import clr
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from System.Collections.Generic import List
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)
# Get the current document
doc = DocumentManager.Instance.CurrentDBDocument
# Get the input documents and elements
inputdocs = UnwrapElement(IN[0])
elements_inputs = UnwrapElement(IN[1])
# Custom handler for duplicate types
class CustomCopyHandler(IDuplicateTypeNamesHandler):
def OnDuplicateTypeNamesFound(self, args):
return DuplicateTypeAction.UseDestinationTypes
options = CopyPasteOptions()
options.SetDuplicateTypeNamesHandler(CustomCopyHandler())
OUT = []
if len(inputdocs) == 1 and not any(isinstance(item, list) for item in elements_inputs):
# IN[0] is a single item and IN[1] is a flattened list
doc_or_link = inputdocs[0]
elements_input = elements_inputs
# Check if it's a RevitLinkInstance
if isinstance(doc_or_link, RevitLinkInstance):
linkDoc = doc_or_link.GetLinkDocument()
tf1 = doc_or_link.GetTotalTransform()
else:
# It's a Document
linkDoc = doc_or_link
tf1 = Transform.Identity
# Gather the ElementIds directly from the list
eId = List[ElementId]()
for e in elements_input:
eId.Add(e.Id)
TransactionManager.Instance.EnsureInTransaction(doc)
try:
# Copy the elements from linkDoc to the current document
copy = ElementTransformUtils.CopyElements(linkDoc, eId, doc, tf1, options)
except Exception as e:
OUT.append(str(e))
else:
for i in copy:
e = doc.GetElement(i)
if e is not None:
OUT.append(e.ToDSType(False))
finally:
TransactionManager.Instance.TransactionTaskDone()
else:
# IN[0] is a list of items and IN[1] can be either a list of sublists or a flattened list
for doc_or_link, elements_input in zip(inputdocs, elements_inputs):
# Check if it's a RevitLinkInstance
if isinstance(doc_or_link, RevitLinkInstance):
linkDoc = doc_or_link.GetLinkDocument()
tf1 = doc_or_link.GetTotalTransform()
else:
# It's a Document
linkDoc = doc_or_link
tf1 = Transform.Identity
if isinstance(elements_input, list):
# Input is a list of sublists
for sublist in elements_input:
# Gather the ElementIds from each sublist
eId = List[ElementId]()
for e in sublist:
eId.Add(e.Id)
TransactionManager.Instance.EnsureInTransaction(doc)
try:
# Copy the elements from linkDoc to the current document
copy = ElementTransformUtils.CopyElements(linkDoc, eId, doc, tf1, options)
except Exception as e:
OUT.append(str(e))
else:
for i in copy:
e = doc.GetElement(i)
if e is not None:
OUT.append(e.ToDSType(False))
finally:
TransactionManager.Instance.TransactionTaskDone()
else:
# Input is a flattened list
# Gather the ElementIds directly from the list
eId = List[ElementId]()
for e in elements_input:
eId.Add(e.Id)
TransactionManager.Instance.EnsureInTransaction(doc)
try:
# Copy the elements from linkDoc to the current document
copy = ElementTransformUtils.CopyElements(linkDoc, eId, doc, tf1, options)
except Exception as e:
OUT.append(str(e))
else:
for i in copy:
e = doc.GetElement(i)
if e is not None:
OUT.append(e.ToDSType(False))
finally:
TransactionManager.Instance.TransactionTaskDone()
OUT
I don’t see any reason why these would perform differently offhand. I might find time to check this out later this week, but… as you are modifying the active document, I don’t see why you couldn’t first link the source model into the document, then transform them over (as that is what works).