Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Run Macro Failed Error

18 REPLIES 18
SOLVED
Reply
Message 1 of 19
mcclanathan
1965 Views, 18 Replies

Run Macro Failed Error

Hello,

I am creating a macro that gets all seleced elements, deletes any zones in the selection, then creates a new zone and adds the spaces from the selection to it.  The code that I thought would accomplish it is below.  It compiles, but when I run it I get the error message below.  Does someone know what is causing the error?

Thank you

 

public void GetSpacesAndCreateZone()
{
UIDocument uiDoc = this.ActiveUIDocument;
Document doc = uiDoc.Document;

//get phase and level from active view to be used for creating zone
View activeView = this.ActiveUIDocument.Document.ActiveView;
Parameter param = activeView.get_Parameter(BuiltInParameter.VIEW_PHASE);
ElementId eID = param.Id;
Phase phase = doc.GetElement(eID) as Phase;
Level lev = activeView.Level;

//space set to be added to the zone
SpaceSet spcSet = new SpaceSet();

//selected elements
SelElementSet selSet = uiDoc.Selection.Elements;

   foreach (Element e in selSet) 
   {
        if (e is Space)
        {
	   //Cast the element to a space
	   Space s = e as Space;
           //insert space into spcSet
           spcSet.Insert(s);
        }
    	else if (e is Zone)
        {
    	    ElementId znID = e.Id;
        	doc.Delete(znID);
        }
    	else
    	{
    	    selSet.Remove(e);
    	}
    }
	   
//create zone and add spaces
using (Transaction t = new Transaction(doc,"Create Zone"))
{
 t.Start();
   Zone zn = this.ActiveUIDocument.Document.Create.NewZone(lev, phase);
   zn.AddSpaces(spcSet);
   t.Commit();
}
}

 

18 REPLIES 18
Message 2 of 19
peterjegan
in reply to: mcclanathan

What is the error?

Message 3 of 19
jmcclanathan
in reply to: peterjegan

I thought I had uploaded it last time.  Here is an image of the error message:

 

ErrorMessage.png

Message 4 of 19
cshha
in reply to: jmcclanathan

You need to wrap the zone deletion code in a Transaction too,

 

else if (e is Zone)
        {
    	    ElementId znID = e.Id;
        	doc.Delete(znID);
        }

 I don't think anything else (aside from the part already wrapped in a Transaction) requires one.


Colin Stark
BIM Specialist & Software Developer
H.H. Angus & Associates Ltd.
Toronto, Canada
Message 5 of 19
mcclanathan
in reply to: cshha

I tried wrapping the zone deletion in a transaction.  That portion of the macro works.  Zones get deleted, but no new zone gets created and I still get the same error message.  Does if maybe have something to do with the way I'm trying to create a zone, or getting the phase used for creating the zone?  Here is the modified code that now wraps the zone deletion in a transaction:

 

public void GetSpacesAndCreateZone()
{
UIDocument uiDoc = this.ActiveUIDocument;
Document doc = uiDoc.Document;

//get phase and level from active view to be used for creating zone
View activeView = this.ActiveUIDocument.Document.ActiveView;
Parameter param = activeView.get_Parameter(BuiltInParameter.VIEW_PHASE);
ElementId eID = param.Id;
Phase phase = doc.GetElement(eID) as Phase;
Level lev = activeView.Level;

//space set to be used to create the zone
SpaceSet spcSet = new SpaceSet();

//selected elements
SelElementSet selSet = uiDoc.Selection.Elements;

   foreach (Element e in selSet) 
   {
        if (e is Space)
        {
	        //Cast the element to a space
	        Space s = e as Space;
           //insert space into spcSet
           spcSet.Insert(s);
        }
    	else if (e is Zone)
        {
		//delete the zone
		using (Transaction delZn = new Transaction(doc,"Delete Zone"))
		{
		 delZn.Start();	
        	 ElementId znID = e.Id;
	         doc.Delete(znID);
	         delZn.Commit();	
		}
        }
    	else
    	{
    		selSet.Remove(e);
    	}
 }
       
//create zone and add spaces
using (Transaction newZnTran = new Transaction(doc,"New Zone"))
{
 newZnTran.Start();    
   Zone zn = this.ActiveUIDocument.Document.Create.NewZone(lev, phase);
   zn.AddSpaces(spcSet);
     newZnTran.Commit();
    }

}
     

 

Message 6 of 19
arnostlobel
in reply to: mcclanathan

My gess is that you are still getting the exception because modifying a selection object also requires a transaction. And because Revit throws when you attempt to do that the code never reaches the point at which you add the zone.

I suggest you modify the code the following way: Do not create several transactions, one for each operation. It is not a very efficient way of modifying a document, and it will also create too many undo items on the undo stack (visible in the undo menu). I recommend the following approach instead:

  • In the foreach loop collect in one collection zones you want to remove and in another the remaining elements you want to remove from the selection set. Plus keep collection the spaces the way you already do.
  • Then after the foreach loop end create and start a new transaction and perform all three operations there:
    1. Remove the existing zones from the document
    2. Modify the selection set
    3. And create a new zone and add the spaces to it
  • Finally, commit the transaction
Arnošt Löbel
Message 7 of 19
mcclanathan
in reply to: arnostlobel

Thank you. Is there such a thing as a zone set that I could use to follow arnost's advice? If so, is there a way to find out on my own? I searched both Revit 2014 chm file and the api developers guide for "space set, "spcset", "zone set", "element set", and none of those searches found any kind of set.

For now, is it ok to start the transaction above the for loop and end it after the zone has been created? I tried it and it did not work. Here is the code and the error message it produced:

 

public void GetSpacesAndCreateZone()
{
UIDocument uiDoc = this.ActiveUIDocument;
Document doc = uiDoc.Document;

//get phase and level from active view to be used for creating zone
View activeView = this.ActiveUIDocument.Document.ActiveView;
Parameter param = activeView.get_Parameter(BuiltInParameter.VIEW_PHASE);
ElementId eID = param.Id;
Phase phase = doc.GetElement(eID) as Phase;
Level lev = activeView.Level;

//space set to be used to create the zone
SpaceSet spcSet = new SpaceSet();

//selected elements
SelElementSet selSet = uiDoc.Selection.Elements;

//create zone and add spaces
using (Transaction newZnTran = new Transaction(doc,"New Zone"))
{
 newZnTran.Start();	

   foreach (Element e in selSet) 
   {
        if (e is Space)
        {
	        //Cast the element to a space
	        Space s = e as Space;
           //insert space into spcSet
           spcSet.Insert(s);
        }
    	else if (e is Zone)
        {
        	ElementId znID = e.Id;
	        doc.Delete(znID);
		}
      
    	else
    	{
    		selSet.Remove(e);
    	}
   }
	   
   Zone zn = this.ActiveUIDocument.Document.Create.NewZone(lev, phase);
   zn.AddSpaces(spcSet);
   
 newZnTran.Commit();
 }

}

 error message.png

Message 8 of 19
arnostlobel
in reply to: mcclanathan

Hello Mcclanathan:

 

Yes, it is ok to keep it as you have it currently implemented. I generally recommend transactions to be as short-spanned as possible (hence my advice above), but since your command is expected to execute very fast without reaching to other modules and methods, it is all right to wrap the whole execution under one transaction.

 

To answer your question about the various sets: The SpaceSet and collections alike are an old kind of containers originated early in the Revit API of yesteryears. We do not use them anymore in newer API and we have been replacing them in the older API as well. Most of the methods in the current API now take (or return) regular .NET containers via generic interfaces, such as Ilist<>, ICollection<>, etc. For example, the Document.Delete method takes ICollection<ElementId>, which means you can use pretty much any standard .NET container. 

Arnošt Löbel
Message 9 of 19
jmcclanathan
in reply to: arnostlobel

Thank you for the advice.  It is helpful.  The macro still does not work.  Does anyone have an idea why it is getting the error message above?

Message 10 of 19
cshha
in reply to: jmcclanathan

Try switching 

ElementId eID = param.Id;

 to

ElementId eID = param.AsElementId();

 

The way you have it now, you are retrieving the parameter, and trying to cast it as a Phase.  The way I've shown it, you retrieve the value of the element ID stored in the parameter, which should represent the phase.

 

I haven't tested the code to see if it runs, but I don't see any more errors.


Colin Stark
BIM Specialist & Software Developer
H.H. Angus & Associates Ltd.
Toronto, Canada
Message 11 of 19
energygroup
in reply to: cshha

I switched to

ElementId eID = param.AsElementId();

 and it still doesn't work.  Does anyone see anything else the doesn't look right?   Here is the error message:

 

 

Error Message 2.png

 

 

 

Here is the code:

 

 

 

public void GetSpacesAndCreateZone()
{
UIDocument uiDoc = this.ActiveUIDocument;
Document doc = uiDoc.Document;

//get phase and level from active view to be used for creating zone
View activeView = this.ActiveUIDocument.Document.ActiveView;
Parameter param = activeView.get_Parameter(BuiltInParameter.VIEW_PHASE);
ElementId eID = param.AsElementId();
Phase phase = doc.GetElement(eID) as Phase;
Level lev = activeView.Level;

//space set to be used to create the zone
SpaceSet spcSet = new SpaceSet();

//selected elements
SelElementSet selSet = uiDoc.Selection.Elements;

//create zone and add spaces
using (Transaction newZnTran = new Transaction(doc,"New Zone"))
{
 newZnTran.Start();	

   foreach (Element e in selSet) 
   {
        if (e is Space)
        {
	        //Cast the element to a space
	        Space s = e as Space;
           //insert space into spcSet
           spcSet.Insert(s);
        }
    	else if (e is Zone)
        {
        	ElementId znID = e.Id;
	        doc.Delete(znID);
		}
      
    	else
    	{
    		selSet.Remove(e);
    	}
   }
	   
   Zone zn = this.ActiveUIDocument.Document.Create.NewZone(lev, phase);
   zn.AddSpaces(spcSet);
   
 newZnTran.Commit();
 }

}

 

 

Message 12 of 19
arnostlobel
in reply to: energygroup

It would help if you could provide some info from debugging. The standard message Revit provides  if an external command or macro fail (throws) is not always sufficient. If you could run your code in a debugger you'd be able to see at what line the exception is thrown, which would be a big help in narrowing down the problem.

 

My hunch is that you should probably remove the zone element you delete (in the foreach loop) from the selection too - and I mean before you delete it from the document. What the message is trying to tell you is that you (or you code, directly or indirectly) try to perform an operation on an object that no longer exist. And in this case, it could be the Selection object at the time you are removing from it, because it may still have references to zones you have already deleted (from the document).

 

Again, this is just a hunch. If you get to debug it you'd see what line exactly the problem raises at.

 

Cheers

Arnošt Löbel
Message 13 of 19
mcclanathan
in reply to: cshha

I changed the recommened code, and still get the same error.  Also, I figured out how to step into and debug.  When I do that, the lev variable is null.  Other than that, it steps all the way through and gets the error at the very end.  Does anyone know why lev would be null in the following code?

Level lev = activeView.Level;

The is a floor plan with a group of zones selected when I run the macro.

Message 14 of 19
arnostlobel
in reply to: mcclanathan

It's quite normal for the Level to be Null. Not all views have a level associated with it.. You need to test that in you macro.
Arnošt Löbel
Message 15 of 19
energygroup
in reply to: arnostlobel

I thouhgt that a floor plan requires a level?  Is that not true?  If not, can someone recommend the best way of getting the level it needs to apply the zones to?

Thank you

Message 16 of 19
arnostlobel
in reply to: energygroup

Yes, a floor-plan should have a level assigned. It is not obvious from the macro code that you wanted it to work only when a floor plan is the active view. The macro could be invoked with any view. That is why I wrote my previous comment. If you indeed run the macro when your currently active view is a floor plan, stop the macro in the debugger after the line at which you define the activeView variable and explore the view's properties to see if there is anything strange or unexpected about it. If there is no level Id, then look in Revit (UI) and check parameters of the view. Are no levels assigned there as well?
Arnošt Löbel
Message 17 of 19
mcclanathan
in reply to: arnostlobel

I got it to work.  The isue was with getting the level from the view.  The level property of the View is obsolete and was not getting the level of the view as I expected it to.  I changed the level to GenLevel and it works.  Here is the line of code I changed:

Level lev = activeView.GenLevel;

//Originally it was:
Level lev = activeView.Level;

 

Thanks for all the suggestions.

Message 18 of 19
energygroup
in reply to: mcclanathan

I got a new issue with the macro.  I got it working on my laptop (which is a single user license in case that matters) as a macro, then I created an external command and got that working on my laptop as well.  Then, I took the dll and and addin manifest and added the external command to my work computer (which is a network license), and I get the error message below.  Does anyone know what might be causing this message?

 

New Error Message.png

Message 19 of 19
arnostlobel
in reply to: energygroup

Energygroup:

 

It looks like your code is removing from a selection set an element that does not exist anymore (was deleted).

Have you implemented all the modifications I sugested earlier?

Can you share the latest version of your code? (The external command Execute method?)

 

Thanks

Arnošt Löbel

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community