Tagging on multiple views with Dynamo

One of the most useful built-in automations in Revit is the “Tag All Not Tagged” command. However it tags elements in the active view only. In larger projects we often have dozens of views where we have to repeat the procedure. Therefore I have tried to create a Dynamo/Python script that can work on a view list and tag elements missing annotation.

The Dynamo definition is really simple here. We just have to collect a list of views, that we want to work on, category of the tagged elements and the tag itself.

The actual work is done inside of the Python node. First we have to convert given element category to a BuiltInCategory enum value. Then we will be able to use it as a filter for the FilteredElementCollector.

import System
bic = System.Enum.ToObject(BuiltInCategory,category.Id.IntegerValue) 

The FilteredElementCollector does actually most of the job in this script. We use two of them. First one collects all the elements in the view that potentially need to be tagged. Second collector gathers all tags present.

elementCollector = FilteredElementCollector(doc,v.Id).OfCategory(bic)
tagCollector = FilteredElementCollector(doc,v.Id).OfClass(IndependentTag)

Now, we just have to loop through the elements and check if they are not already tagged. We do that by comparing their id with ids of tag hosts.

notTagged = []
for e in elementCollector:
	tagged = False
	for t in tagCollector:
		if t.TaggedLocalElementId==e.Id:
			tagged = True
	if not tagged:
		notTagged.append(e)

Finally, we create new tags for elements that require them and set tag type to the one specified in the input.

for e in notTagged:
	t = IndependentTag.Create(doc,v.Id,Reference(e),False,TagMode.TM_ADDBY_CATEGORY,TagOrientation.Horizontal,e.Location.Point)
	t.ChangeTypeId(tag.Id)

The complete code can look like below. Also on the bottom of the post you can find a complete Dynamo file for download.

import clr
import System

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

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

doc = DocumentManager.Instance.CurrentDBDocument

#The inputs to this node will be stored as a list in the IN variables.
views = UnwrapElement(IN[0])
category = UnwrapElement(IN[1])
tag = UnwrapElement(IN[2])

bic = System.Enum.ToObject(BuiltInCategory,category.Id.IntegerValue)

output = []

TransactionManager.Instance.EnsureInTransaction(doc)

for v in views:
	if not v.IsTemplate:
		elementCollector = FilteredElementCollector(doc,v.Id).OfCategory(bic)
		tagCollector = FilteredElementCollector(doc,v.Id).OfClass(IndependentTag)
		notTagged = []
		for e in elementCollector:
			tagged = False
			for t in tagCollector:
				if t.TaggedLocalElementId==e.Id:
					tagged = True
			if not tagged:
				notTagged.append(e)
				
		for e in notTagged:
			t = IndependentTag.Create(doc,v.Id,Reference(e),False,TagMode.TM_ADDBY_CATEGORY,TagOrientation.Horizontal,e.Location.Point)
			t.ChangeTypeId(tag.Id)
			output.append(t)
		
TransactionManager.Instance.TransactionTaskDone()
			
#Assign your output to the OUT variable.
OUT = output
Posts created 45

15 thoughts on “Tagging on multiple views with Dynamo

  1. Thank you very much. May God bless you for saving from this trouble. I’m a dynamo beginer and dunno python so I tried several times in dynamo but I couldnt

  2. This works great for doors! Thank you so much! 🙂
    Is there a way to do this for rooms? Room tags?

    1. Hi Renee!
      It is possible, however RoomTags are a different kind of tags in Revit so some changes have to be made.
      First of all you have to import Architecture part of Revit API:

      from Autodesk.Revit.DB.Architecture import *

      Then the main loop of the script would look like this:

      for v in views:
        if not v.IsTemplate:
         elementCollector = FilteredElementCollector(doc,v.Id).OfCategory(bic)
         tagCollector = FilteredElementCollector(doc,v.Id).OfClass(SpatialElementTag)

         notTagged = []
         for e in elementCollector:
          tagged = False
          for t in tagCollector:
           if t.Room==e:
            tagged = True
          if not tagged:
           notTagged.append(e)

         for e in notTagged:
          doc.Create.NewRoomTag(e.Id,UV(e.Location.Point.X,e.Location.Point.Y),v.Id)
          t.ChangeTypeId(tag.Id)
          output.append(t)

      1. Hi, I followed along with the code, but it is giving me an error saying that it expected a LinkId, but got ElementId

        1. Hi, are you trying to tag elements from linked files? I am afraid the above code does not work for links. If not can you show a screenshot of your Dynamo definition and the error message? (you can send it to lu@lubim.co)

          Regards

          1. Hi Maciek,
            I`m having the same error message as Spencer did with the room tags. I`m trying to place roomtags in all views. But it gives me the error expecting LinkElementId, got ElementId.
            Why is it expecting a LinkElementId? I`m not trying to tag linked rooms..
            I would be very thankfull if you could send the sollution to this problem.
            Regards,
            Wouter

          2. Hi,
            thank for the error confirmation. I think there might have been an API change. It seems like an easy fix – I will try to make a new post about room tagging tonight with the correct solution.

  3. Hi,

    I have amended the script to only tag a selection of views, rather than all and am getting this error on the Python Script node:

    Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed.
    Traceback (most recent call last):
    File “”, line 19, in
    AttributeError: ‘NoneType’ object has no attribute ‘Id’

    Any ideas?

    Cheers,

    1. HI!
      if the line 19 is “bic = System.Enum.ToObject(BuiltInCategory,category.Id.IntegerValue)” than it seems that you category variable is null – no object is assigned to it…are you passing a correct category type?

  4. HI, I have a question for you.
    First, very nice explained, It helped me very good.

    But I would like to Tag Curtain Walls by “Mark A”.

    Could you help me?

    Greets,
    Rick

    1. Hi,
      to tag Mark of the element you just have to use a tag that has a label for that, but I am guessing that is not the problem.

      The issue might be in the fact that wall elements do not have a location point (they have a location curve).
      So you have to change the code a little. You have to eg. calculate a midpoint of the location curve beforehand and then pass it to the tag-create function (instead of the location point) :

      lc = e.Location
      lp0 = lc.Curve.GetEndPoint(0)
      lp1 = lc.Curve.GetEndPoint(1)
      lp = lp0 + (lp1-lp0)/2
      t = IndependentTag.Create(doc,v.Id,Reference(e),False,TagMode.TM_ADDBY_CATEGORY,TagOrientation.Horizontal,lp)

  5. What will be the total code?
    Could you help me?

    My Python skills aren’t very high.

    1. Hi, I have sent you a dyn file via email. I don’t think large amount of code would be readable here in the comment. Let me know if it helps!

Leave a Reply

Your email address will not be published.

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top