Revit API Prompt for Placement

Revit API Prompt for Placement

trentNBSG7
Explorer Explorer
560 Views
5 Replies
Message 1 of 6

Revit API Prompt for Placement

trentNBSG7
Explorer
Explorer

I am trying to put together a seemingly simple Revit API script that when ran, will search my current document for the Electrical Device I specify and then place me in placement mode with said family. I am currently trying to achieve this with the uiapp.ActiveUIDocument.PromptForFamilyInstancePlacement method, but it puts me in a broken state where I cant get my family placement to accept, I can only hit ESC and get the "The user aborted the pick operation." pops up. I am happy to share my code if it helps with troubleshooting. I am aware that PromptForFamilyInstancePlacement might not be the best tool, but I haven't had success with other methods yet. Any help or direction would be appreciated.

0 Likes
561 Views
5 Replies
Replies (5)
Message 2 of 6

jeremy_tammik
Alumni
Alumni

Sound like a possible and useful approach to me. So yes, I wonder why it does not work as expected for you.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 6

sragan
Collaborator
Collaborator

Yes, it would help if you could post the relevant code, and also the family you are trying to place.

 

Note that some families may have an option bar on the upper left when you go to place them with options for things like "place on vertical face", or "place of face", etc.

 

Also, if you are trying to place something that is ceiling mounted, and there are no ceilings in the project, of course it isnt going to work.

 

 

0 Likes
Message 4 of 6

trentNBSG7
Explorer
Explorer

I added text dialogues to my code to give indication where the broken state is occurring. Am I using the PromptForFamilyInstancePlacement method incorrectly so that it's causing me to get stuck? I can place as many instance as I want, but I cant get out of the placement state unless I hit ESC, which causes the user aborted error.

Here is the code at the moment -

#region Namespaces
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
#endregion

namespace Get_Family_Information
{
    [Transaction(TransactionMode.Manual)]
    public class Command1 : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            // This is a variable for the Revit application
            UIApplication uiapp = commandData.Application;

            // This is a variable for the current Revit model
            Document doc = uiapp.ActiveUIDocument.Document;

            // Retrieve the family name and family symbol
            string targetFamilyName = "RECEPT - Standard  - Type";
            string targetFamilySymbol = "General - 180 VA";

            // Retrieve the specified family and symbol
            Family family = GetFamily(doc, targetFamilyName);
            FamilySymbol symbol = GetFamilySymbol(family, targetFamilySymbol);

            if (family != null && symbol != null)
            {
                try
                {
                    // Place the family symbol in "Place Component" mode
                    uiapp.ActiveUIDocument.PromptForFamilyInstancePlacement(symbol);

                    return Result.Succeeded;
                }
                catch (Autodesk.Revit.Exceptions.OperationCanceledException)
                {
                    TaskDialog.Show("Info", "Placement operation canceled by the user.");
                    return Result.Cancelled;
                }
                catch (Exception ex)
                {
                    TaskDialog.Show("Error", ex.Message);
                    return Result.Failed;
                }
            }
            else
            {
                TaskDialog.Show("Error", "Family or symbol not found.");
                return Result.Failed;
            }
        }

        private Family GetFamily(Document doc, string familyName)
        {
            return new FilteredElementCollector(doc)
                .OfClass(typeof(Family))
                .FirstOrDefault<Element>(
                    e => e.Name.Equals(familyName)) as Family;
        }

        private FamilySymbol GetFamilySymbol(Family family, string symbolName)
        {
            if (family != null)
            {
                return new FilteredElementCollector(family.Document)
                    .OfClass(typeof(FamilySymbol))
                    .Cast<FamilySymbol>()
                    .FirstOrDefault(s => s.FamilyName.Equals(family.Name) && s.Name.Equals(symbolName));
            }
            return null;
        }

        public static String GetMethod()
        {
            var method = MethodBase.GetCurrentMethod().DeclaringType?.FullName;
            return method;
        }
    }
}

 
The ultimate goal is to have a code that I can adapt to place any specified family type with just one button input. I am new to Revit API so perhaps I am making this task more complicated that it has to be by pursuing this route? I am open to redirection if I am trying to reinvent the wheel.

0 Likes
Message 5 of 6

sragan
Collaborator
Collaborator

Yes, there was something that changed with the escape, and it causes error messages where it didn't do that in older versions.


I don't think you want to return Canceled for an escape, you basically want to exit quietly. 

0 Likes
Message 6 of 6

sragan
Collaborator
Collaborator
0 Likes