Hi, all.
I’m new to pyRevit toolbar creation (just saw my first couple of videos on the topic recently), but am very excited for the opportunities ahead!
Could someone help me write a script for a pushbutton that will insert a detail family (or load one if it’s not already loaded)? The pseudo-code is as follows:
click button to start script (already have this and the button already works - but the script itself does nothing yet).
script will check if a specific detail family, say “symbol.rfa”, is loaded into current project model.
if it is loaded, the script gets it ready to be inserted into the working view (similar to how the “Detail Component” in the Annotate tab already works).
if is not loaded, the script will then load that detail family from a specific folder, say C:\pyRevit\MyTools.
after loading it into the current project model, the script gets it ready to be inserted into the working view.
It looks like the code there would require the Revit family to be actually located in the folder for the pushbutton itself. And I’m not sure if the program would even check if the family is already loaded in the project model before attempting to load the family.
Is there a way to write a script that will do that? Just like the pseudo-code above? That way we can keep all of our families in their usual folder (so it’s easy to make updates), write down the actual file path in the script, and go from there.
You are right - after reading, it is exactly what I need
I forgot to mention on the OP, but I am also new to Python (never wrote a thing in this language) and do not know how to convert C# to it in order to place it in the scipt.py file - could you give me a hand on that by any chance?
Got the code from Jeremy Tammik converted to Python (thanks Jeremy and Jean-Mark!).
Issue now is that it doesn’t seem to compile. I wish I knew enough about Python to fix it, but alas I can’t… Could someone help me figure this one out?
import clr
import os.path
import System
import Autodesk.Revit.DB as DB
import Autodesk.Revit.UI as UI
clr.AddReference("RevitAPI")
clr.AddReference("RevitAPIUI")
class CmdTableLoadPlace(UI.IExternalCommand):
FamilyName = "family_api_table"
_family_folder = os.path.dirname(System.Reflection.Assembly.GetExecutingAssembly().Location)
_family_ext = "rfa"
_family_path = os.path.join(_family_folder, FamilyName)
_family_path = os.path.splitext(_family_path)[0] + "." + _family_ext
_added_element_ids = []
def Execute(self, commandData):
uiapp = commandData.Application
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
doc = uidoc.Document
# Retrieve the family if it is already present:
family = DB.FilteredElementCollector(doc).OfClass(DB.Family).FirstOrDefault(lambda f: f.Name == self.FamilyName)
if not family:
# It is not present, so check for the file to load it from:
if not os.path.exists(self._family_path):
TaskDialog.Show("Error", "Please ensure that the sample table family file '{0}' exists in '{1}'.".format(self.FamilyName, self._family_folder))
return UI.Result.Failed
# Load family from file:
with DB.Transaction(doc, "Load Family") as tx:
family = doc.LoadFamily(self._family_path)
# Determine the family symbol
symbol = None
for s in family.Symbols:
symbol = s
# Our family only contains one symbol, so pick it and leave
break
# Place the family symbol:
# Subscribe to document changed event to retrieve family instance elements added by the PromptForFamilyInstancePlacement operation:
app.DocumentChanged += self.OnDocumentChanged
self._added_element_ids.clear()
# PromptForFamilyInstancePlacement cannot be called inside transaction.
uidoc.PromptForFamilyInstancePlacement(symbol)
app.DocumentChanged -= self.OnDocumentChanged
# Access the newly placed family instances:
n = len(self._added_element_ids)
msg = "Placed {0} {1} family instance{2}{3}".format(n, family.Name, self.PluralSuffix(n), self.DotOrColon(n))
ids = ", ".join(str(id.IntegerValue) for id in self._added_element_ids)
TaskDialog.Show("Information", "{0}\n{1}".format(msg, ids))
return UI.Result.Succeeded
def OnDocumentChanged(self, sender, args):
self._added_element_ids.extend(args.GetAddedElementIds())
def PluralSuffix(self, n):
return "" if n == 1 else "s"
def DotOrColon(self, n):
return ":" if n == 0 else "."