Are you working in dynamo or in python itself?
I’m not sure if it’s totally relevant, but it could help finding an answer;
- Changing your familyinstance type.
So this is actually not that hard, it’s just a bit inconvenient.
NewFamilyInstance will always use the ‘last used’ type used by the interface.(1)
But we CAN change the type after the instance is created.
The element will have a ‘ChangeTypeId()’ function that you can use. You’ll also need to get all the type id’s for that family I presume. Here’s how:
# 1. Get all family types/symbols ( yeah ..)
# note that this won't work for walls/floors or other system families.
all_family_types = list(famsymb.Family.GetFamilySymbolIds())
#2. Change the type fo the element to what you've chosen as a type.
# provided you've created a variable named chosen_type_id which contains a single elementID from all_family_types
Now for choosing a position. Also a bit more convoluted at first glance. But not too bad. The biggest thing here is the way the selection tool works.
Mainly, what happens if a user presses the ‘Escape’ button.
Revit will throw out an error which you have to catch in order for your script to keep running. This might sound scary, but it’s actually a pretty clean way to detect specific circumstances and have code be interrupted. It will make your code more robust. But I suggest diving into a tutorial video about exceptions for that.
# You'll need to add an additional import at the top of your code
# try either (remove 1)
from Autodesk.Revit import UI as UI
from pyrevit import UI
uidoc = __revit__.ActiveUIDocument
snap_mode = UI.Selection.ObjectSnapTypes.Intersections
desired_location = XYZ() # set up a 'default' location at 0,0,0
desired_location = uidoc.Selection.PickPoint(snap_mode)
except Autodesk.Revit.Exceptions.OperationCanceledException as cancelled_ex:
# this part of the code gets executed when the user presses escape.
# desired_location is already set to (0,0,0) so we don't really need to do anything here.
# I'm just putting in a print statement for the info, but you can also just write pass. Should work fine.
print('User cancelled operation')
# pass is sort of like a 'do nothing' line; But it counts as code.
# but it keeps your code readable. You can use pass in other places as well. It's not limited to exceptions. It's just an empty line.
That should do it.
Now for a bit of an extra, IF you run your scripts from python (don’t know about dynamo tbh)
you can import a logger that provides some more clean output, and which can help you debug your code.
from pyrevit import script
logger = script.get_logger()
output = script.get_output()
output.close_others() # this just makes sure your previous logger windows get closed on the next script run
logger.info('This is a standard info log')
logger.warn('This is a warning log, should be orange')
logger.error('This is an error log, red')
These don’t change much, but it can help you
(1) Now looking at revitapidocs it seems that there’s no way around it. (I could be wrong, I glossed over it)