Copy elements from document/link with neverending Duplicate Types window question

Hello,

I am copying several elements from links or documents to the current project file opened with Dynamo with the nodes of rhythm or springs, but it takes so long because majority of elements contain other elements that Revit indicates they are duplicated and if I want to overwrite with OK button.

is possible to copy all without any question of Duplicate Types?
image

You would have to use a CopyElements method with CopyPasteOptions so that you can set the SetDuplicateTypeNamesHandler to ignore duplicates.

2 Likes

You’d have to write the code using those methods and members I linked.

2 Likes

Hello @Nick_Boyts

I understand that I would have to define the CopyPasteOptions of the code.

But how is the variable of CopyPasteOptions defined? I tried adding also this code but it seems it needs more definition:

copy = ElementTransformUtils.CopyElements(Document, ICollection(ElementId), Document, Transform, CopyPasteOptions)

options = CopyPasteOptions()
options.SetDuplicateTypeNamesHandler()

copy = ElementTransformUtils.CopyElements(Document, ICollection(ElementId), Document, Transform, options)

I suggest doing some research on python coding with the Revit API. It can seem like a big step but it’s incredibly powerful once you get comfortable with it.
image
The argument you have to supply is the object in green, IDuplicateTypeNamesHandler. If you click on it it will explain what it does and give you a link to all its members. You’d have to check the members to see how that value is set. You may even have to do this multiple times if the argument is another method that needs defining.

Hello
the implementation of a Net Interface is quite specific in Python
here is a sample example

import clr
import sys
import System
from System.Collections.Generic import List
# all imports and some code
# ...
# ...
# ...
# current_doc = ...
# ...

class CustomCopyHandler(IDuplicateTypeNamesHandler):
	def OnDuplicateTypeNamesFound(self, args):
		return DuplicateTypeAction.UseDestinationTypes

souceDoc = UnwrapElement(IN[0])
myElements = UnwrapElement(IN[1])

copyOptions = CopyPasteOptions()
copyOptions.SetDuplicateTypeNamesHandler(CustomCopyHandler())	

# start transaction 
TransactionManager.Instance.ForceCloseTransaction()
TransactionManager.Instance.EnsureInTransaction(current_doc)
myElementIds  = List[ElementId]([x.Id for x in myElements])
newCopyElementIds = ElementTransformUtils.CopyElements(souceDoc, myElementIds, current_doc, None , copyOptions)	
# rest of code 
# ...
# ...		
TransactionManager.Instance.TransactionTaskDone()
6 Likes

@c.poupin would you know what Argument the CopyHandler is expecting? I have not actually had to pass things like this in the past. @solamour @Michael_Kirschner2

import clr
import sys
import System

clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference('System')
from System.Collections.Generic import List

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

class CustomCopyHandler(IDuplicateTypeNamesHandler):
    def OnDuplicateTypeNamesFound(self, args):
        return DuplicateTypeAction.UseDestinationTypes

doc = DocumentManager.Instance.CurrentDBDocument

#Preparing input from dynamo to revit
linkInst = UnwrapElement(IN[0])
linkViews = UnwrapElement(IN[1])
newViews = UnwrapElement(IN[2])

LinkIds = []
NewIds = []
Items = []

#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)

opts = CopyPasteOptions()
opts.SetDuplicateTypeNamesHandler(CustomCopyHandler()) #Line 47 from Error
Items.append(ElementTransformUtils.CopyElements(linkView,List[ElementId](oldItems),newView,Transform.Identity,opts))

UPDATE:
It works fine if I run it against IP2, is there something in CP3 that I need to adjust for the interface?

1 Like

Hi @SeanP

it’s a know issue

you can try to change the namespace of the class (with __namespace__ attribute) but it’s unstable currently

pyRevit has similar issue

for information the next version of PythonNet has many BREAKING

Till date (PythonNet and/or IronPython can evolve), I use both 2 engines, each one has it’s own advantages:

  • IronPython has better .Net integration
  • CPython3 / PythonNet allows to use an updated version of Python (with modern packages) and with a .Net integration but not as advanced as IronPython

but all this remains my own opinion

3 Likes

Thank you as always @c.poupin the namespace attribute worked for me in this instance.

class CustomCopyHandler(IDuplicateTypeNamesHandler):
    __namespace__ = "Autodesk.Revit.DB"
    def OnDuplicateTypeNamesFound(self, args):
            return DuplicateTypeAction.UseDestinationTypes
2 Likes

this method works once per Revit session
An example with IFamilyLoadOptions interface
https://s10.gifyu.com/images/test_PythonNet_Interface3.gif

2 Likes

Yes, found this out rather quickly, and went back to IP2. I’ll stay there until there is another way to do it, but this is also why I’ll be eventually rolling this into an addin and remove the issue completely.

Thanks again!

2 Likes

hello, I used this code to copy elements in order to modify them on the same page, but despite the code I do not find the same argument, only the ids, and I cannot modify them being refused as an element?
Thank you for any help you can give me

import clr
import sys
import System

clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference('System')
from System.Collections.Generic import List

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

current_doc = DocumentManager.Instance.CurrentDBDocument

class CustomCopyHandler(IDuplicateTypeNamesHandler):
#    __namespace__ = "Autodesk.Revit.DB"
    def OnDuplicateTypeNamesFound(self, args):
            return DuplicateTypeAction.UseDestinationTypes

myElements = UnwrapElement(IN[0])
CopyElement = []
oldItems = []

copyOptions = CopyPasteOptions()
copyOptions.SetDuplicateTypeNamesHandler(CustomCopyHandler())	

# start transaction 
TransactionManager.Instance.ForceCloseTransaction()
TransactionManager.Instance.EnsureInTransaction(current_doc)
myElement  = List[ElementId]([x.Id for x in myElements])
CopyElement = ElementTransformUtils.CopyElements(current_doc, myElement , current_doc , Transform.Identity , copyOptions)
#CopyElement.append(ElementTransformUtils.CopyElements(current_doc, myElement , current_doc , Transform.Identity , copyOptions))
		
TransactionManager.Instance.TransactionTaskDone()
OUT = CopyElement


I specify that I am French that I translate with “translate” I apologize for the mistakes

The copy method only returns ElementIds. From those you can get the element.

OUT = [current_doc.GetElement(x) for x in CopyElement]
1 Like

Is Ok just change “oc” by “doc” (y)