@GavinCrump I had to remove the design script references that were conflicting with the Python references to Revit points. Really wish we had an editor with full intellisense and only allowed strict formatting!
...
objPoint = XYZ(x, y, 0) ##GET POINT
...
if GAiv:
AnnoEXST.append(GAFamType) ##Add it to the existing list
for GAinVIew in AnnosInView: ##Cycle through to set it
if GAinVIew.Name==GetGAName(GAFamType): ##GenericAnnotaitonFamilyTypeCompare
GAiv.Location.Point = objPoint ##<<<Sets Fixed Position for element in list.
break
Script in full context:
##https://gist.github.com/gtalarico/e6be055472dfcb6f597e3dcd20d11f37
#import System.Collections.Generic
#from System.Collections.Generic import List
##clr.AddReference('RevitAPIUI')
##from Autodesk.Revit.UI import *
import clr
clr.AddReference('System')
clr.AddReference('RevitAPI')
##clr.AddReference('RevitNodes')
##clr.ImportExtensions(Revit.Elements)
##clr.ImportExtensions(Revit.GeometryConversion)
###Creates a Drafting View###
from Autodesk.Revit.DB import Transaction, Element, ElementTransformUtils
##https://forum.dynamobim.com/t/collecting-all-elements-of-family-types-in-active-view/19838/2
from Autodesk.Revit.DB import FilteredElementCollector, BuiltInCategory, BuiltInParameter, ParameterValueProvider, ElementId, ElementParameterFilter, FilterNumericEquals, FilterElementIdRule, ElementTransformUtils
# Drafting Views
from Autodesk.Revit.DB import ViewFamilyType, ViewDrafting, Element
from Autodesk.Revit.DB import ViewFamily
clr.AddReference('RevitServices') ##May need to re-add for Document Manager
import sys
import System ##filterAnnot = System.Predicate
from System.Collections.Generic import List ##Not same as type() = List
import math ##For truncate to integer-RA
import re ##Regular expressions for 'natural' sort
from itertools import groupby
#from Autodesk.Revit.DB import *
from Autodesk.Revit.DB import FamilySymbol, FamilyInstance, XYZ, AnnotationSymbol
#import Revit
#from Revit import *
#from Autodesk.DesignScript.Geometry import * ##Point(X,Y,Z) ##cannot use for PY nodes outside Dynamo
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uidoc=DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
##uidoc = __revit__.ActiveUIDocument
##doc = __revit__.ActiveUIDocument.Document
#####################################################################################
##Create a Drafting View#
def get_drafting_type_id(DraftingType):
##Selects First available ViewType that Matches Drafting Type.## ##https://mgfx.co.za/blog/building-architectural-design/revit-view-type-creation-using-excel-with-dynamo-and-python/
viewfamily_types = FilteredElementCollector(doc).OfClass(ViewFamilyType)
for i in viewfamily_types:
if i.ViewFamily == ViewFamily.Drafting: ##*.ViewFamily Backwards 'parent' ref I've been looking for!##<<<<<<<<<<<<<<<<<<<<<<<<<<HERE
return i.Id
def GetDraftingViews():
##https://forums.autodesk.com/t5/revit-api-forum/view3d-collector/td-p/5277451
DraftingViewsList = FilteredElementCollector(doc).OfClass(ViewDrafting).ToElements()
##DraftingViewTemplates = [v.Id for v in DraftingViewsList if v.IsTemplate == True]
DraftingViewsList = [v for v in DraftingViewsList if v.IsTemplate == False]
return [DraftingViewsList]
def GetDraftingViewTemplates():
##https://forums.autodesk.com/t5/revit-api-forum/view3d-collector/td-p/5277451
DraftingViewsList = FilteredElementCollector(doc).OfClass(ViewDrafting).ToElements()
DraftingViewTemplates = [v for v in DraftingViewsList if v.IsTemplate == True]
##DraftingViewsList = [v.Id for v in DraftingViewsList if v.IsTemplate == False]
return [DraftingViewTemplates]
def GetDraftingViewByBame(strName=""): ##Check if drafting view existds = if not, create it and assign view name
if not strName == "": ##If string name is set look for the drafting view
DraftingView = FilteredElementCollector(doc).OfClass(ViewDrafting).ToElements() ##Get all drafting views
DraftingView = [v for v in DraftingView if v.Name == strName] ##Return Drafting view for each Drafting view eq. Name
if DraftingView:
DraftingView =DraftingView[0] ##Return single item not list<<<<<<<<<<<<<<<
if not DraftingView: ##If no drafting view found
drafting_type_id = get_drafting_type_id() ##Get TYPE ID
DraftingView = ViewDrafting.Create(doc, drafting_type_id) ##Create View
##After creating view-
if not strName=="" : ##IF string is not null set the name of the new view
DraftingView.Name = strName
return DraftingView ##Return single value
def GetGenericAnnotationTypes():
##BAsed in part
##https://forum.dynamobim.com/t/how-can-i-collect-all-family-types-that-are-considered-annotation-symbols-in-revit/37480/10
##https://forum.dynamobim.com/t/get-all-generic-annotations-in-a-view/80514/2
filterAnnot = System.Predicate[System.Object](lambda x : x.Family.FamilyCategory.Name == "Generic Annotations")
symbAnnot = List[Element](FilteredElementCollector(doc).OfClass(FamilySymbol).ToElements()).FindAll(filterAnnot)
return symbAnnot
def Lambda_Natural_sort(l): ##Slow 50x but effective ##ORiginal function doesn't work with Objects.
ConvertText = lambda ConvertText: int(ConvertText) if ConvertText.isdigit() else ConvertText.lower()
alphanum_key = lambda key: [ ConvertText(c) for c in re.split('([0-9]+)', key) ]
return sorted(l, key = alphanum_key)
def Lambda_GenAnno_Sort_w_fam_name(lstObj):
ConvertText = lambda ConvertText: int(ConvertText) if ConvertText.isdigit() else ConvertText.lower()
alphanum_key = lambda i: [ ConvertText(c) for c in re.split('(\d+)', i) ]
##GenAnnoTypeName##https://forum.dynamobim.com/t/python-script-to-get-type-name-from-an-element/63306/2
GAstrName = lambda j: [ alphanum_key(c) for c in (j.Family.Name + GetGAName(j))]
return sorted(lstObj, key = GAstrName)
def GetGAName(GA): ##GenericAnnotationFamilyType".Name"
return doc.GetElement(GA.Id).get_Parameter(BuiltInParameter.ALL_MODEL_TYPE_NAME).AsString()
def GroupGenAnnos(lstElems):
##test to Group By Key https://forum.dynamobim.com/t/group-by-key-in-python/39145/2
grp=[]
ukey=[]
##Presorted by genannolistfort_w_family_name
for k, g in groupby(lstElems, lambda x:x.Family.Name):
grp.append(list(g))
ukey.append(k)
#Assign your output to the OUT variable.
return grp
def GetAnnosInView(viewView):
##https://forum.dynamobim.com/t/get-all-generic-annotations-in-a-view/80514/2
symbAnnot = [x for x in FilteredElementCollector(doc,viewDraft.Id).OfCategory(BuiltInCategory.OST_GenericAnnotation).WhereElementIsNotElementType()]
def ListConv(x): ## Returns list if single item
if type(x) is list :
return x ##Leave as list if laready list
else:
try:
z=iter(x) ##if element is iterable- e.g. Generic.List - it can be converted to regular list
return [x for x in x] ##Convert to list if single item
except:
return[x] ##Convert single element to list
def ListOfList1InList2(list1,list2):
list1Out=[]
for x in list1: ##For each element in 1st list (Check against elements in 2nd list)
found = False ##Reset to not found for next element
for y in list2:
if x==y: ##If found,
found =True ##Set founc to TRUE
break ##Can stop looking in second list this round
list1Out.append(found) ##Append result
return list1Out
def List1InList2(list1,list2): ##If any of list 1 in list 2 return TRUE else False
for x in list1: ##For each element in 1st list (Check against elements in 2nd list)
for y in list2:
if x==y: ##If found,
return True ##Return True
return False ##Return false
def GenAnnosInView(viewView):
##GET ANNOTATIONSIN VIEW
##https://forum.dynamobim.com/t/get-all-generic-annotations-in-a-view/80514/2
FEC=FilteredElementCollector(doc,viewView).OfCategory(BuiltInCategory.OST_GenericAnnotation).WhereElementIsNotElementType()
return FEC
def PlaceGenAnnoArray(GAFamTypes, viewView): #Single family of generic annotaiton types to place
##cast CONSTANTS
xSpace = 8.5/12.0 ##Horizontal spacing 8-1/2" Wide
ySpace = 3.0/8.0/12.0 ##Vertical spacing 3/16" tall (Text is 3/32" high)
yLimit = 10.0/12.0 ##Limit of Y column height 10" (8-1/2"x11" Guide to format into sheet size references)
yCount = int(math.floor(yLimit/ySpace)) ##Number of rows in a column for reset y value
column = 0 ##Column location
count = 1 ##Count position in array of all family types
AnnoEXST=[] ##Existing annotaitons in view
AnnoNEWW=[] ##New annotaitons creted
##get AllGenAnnosInView - if any...
AnnosInView =[]
#AnnosInView = FilteredElementCollector(doc,viewView.Id).OfCategory(BuiltInCategory.OST_GenericAnnotation).WhereElementIsNotElementType().ToElements
##https://forum.dynamobim.com/t/get-all-generic-annotations-in-a-view/80514/13 SeanP
filterAnnot = System.Predicate[System.Object](lambda x : doc.GetElement(x.GetTypeId()).Family.FamilyCategory.Name == "Generic Annotations")
AnnosInView = List[Element](FilteredElementCollector(doc, viewView.Id).OfClass(FamilyInstance).ToElements()).FindAll(filterAnnot)
AnnosInView = UnwrapElement(AnnosInView) ##Unwrap to get to get to Revit Type Elements
for GAFamType in GAFamTypes :
#from 0,0 run down then over for simplicity. These typically will NOT end up on printed sheets
#But are head to use to schedule. Any object in any view will schedule regardless of on/off sheet palcement.
column = math.floor( yLimit / count * ySpace) ##Get column based on placed elements and Y limit sizes
x= column * xSpace ##Get x location
y= -ySpace * (count-1 - (column * yCount)) ##Offset Y by column displacemnet
objPoint = XYZ(x, y, 0) ##GET POINT
#return List1InList2([GetGAName(GAFamType)], [x.Name for x in AnnosInView]) ##DEBUG
##if List1InList2([GetGAName(GAFamType)], [x.Name for x in AnnosInView]): ##if GAFamType Name in list of names in view
#return 3
GAiv = None
if AnnosInView : ##If ther eare annos in the view
for GAivx in AnnosInView: ##For each Gen Anno in view
Found = False ##Reset Found
for y in GAFamTypes:
if GetGAName(GAFamType)==GAivx.Name: ##If found,
Found = True ##Return True
GAiv=GAivx
break ##Break with Found set
if Found: ##If found (after for y)
break ##Exit out of outer loop with GAiv (Gen Anno In View) set
else:
GAiv=None
if GAiv:
AnnoEXST.append(GAFamType) ##Add it to the existing list
for GAinVIew in AnnosInView: ##Cycle through to set it
if GAinVIew.Name==GetGAName(GAFamType): ##GenericAnnotaitonFamilyTypeCompare
GAiv.Location.Point = objPoint ##Sets Fixed Position for element in list.
break
else: ##Not List1InList2
GAinVIew = doc.Create.NewFamilyInstance(objPoint, GAFamType, viewView) ##Create NEW annotaiton in its loaiton
AnnoNEWW.append(GAinVIew) ##Append it to the new list as a double check
count +=1 ##increment counter
return [AnnoNEWW,AnnoEXST] ##Return the New and Existing. Re-running should only return existing.
####
###
#######################################################################################
def Main(): ###Entry point to procedures
t = Transaction (doc, 'Create Drafting View')
t.Start()
outNEWW=[]
outEXST=[]
GenAnnoTypes = []
GenAnnoTypes = GetGenericAnnotationTypes() ##LIST of FAMILY TYPE of GenAnnoTypes
GenAnnoTypes = Lambda_GenAnno_Sort_w_fam_name(GenAnnoTypes) ##Sort in natural order- numbers as numbers text as text
GenAnnoTypes = GroupGenAnnos(GenAnnoTypes) ##Create nested list by Family and Types
for GAFamType in GenAnnoTypes: ##2D list [1.GenAnnoFamilies][2.GenAnnoTypes]
DraftViewName = ""
DraftViewName = GAFamType[0].Family.Name ##FAmily name used for drafting view name
viewDraft = GetDraftingViewByBame(DraftViewName) ##Get or create drafting view by name
OUT = PlaceGenAnnoArray (GAFamType, viewDraft) ##Place or update gfams per view
##Separate lists into NEW and EXISTING##
#outNEWW.append(OUT[0]) ##New is index 0
#outEXST.append(OUT[1]) ##Existing is index 1
#OUT=[outNEWW,outEXST] ##Set final OUT to [NEW,Existing] Lists
t.Commit()
return OUT
############################################################################################
############################################################################################
OUT=Main () ##Entry point to run all scripts
############################################################################################
############################################################################################