macro doesnt work properly on big projects

macro doesnt work properly on big projects

Gilles.Lagrilliere
Advocate Advocate
1,066 Views
12 Replies
Message 1 of 13

macro doesnt work properly on big projects

Gilles.Lagrilliere
Advocate
Advocate

Hello everyone

 

I created a macro that gives my tags the same color as the element that is tagged.

it works great on small projects. But if I use it on a big project, revit can't handle it.

 

how can i fix this? I have no clue.

 

i'm a beginner with macro's so i'm not surprised if my macro is bad written. apologies in advance.

you can find my macro in the attachment. 

0 Likes
Accepted solutions (1)
1,067 Views
12 Replies
Replies (12)
Message 2 of 13

jeremy_tammik
Alumni
Alumni

For easier readability, convenience, so other are not forced to download and unpack your zip file, here is a copy of your code, slightly reformatted for readability:

 

  public void test( UIDocument uiDoc )
  {
    //current document
    //UIDocument uiDoc = new UIDocument( Document );
    //Document doc = this.Application.ActiveUIDocument.Document;

    Document doc = uiDoc.Document;

    //current view and open views
    View curView = doc.ActiveView;
    var openViews = uiDoc.GetOpenUIViews();
    List<ElementId> openV1 = new List<ElementId>();

    foreach( var view in openViews )
    {
      var i = view.ViewId;
      openV1.Add( i );
    }


    //get builtincategory of selected tag
    Reference sel = uiDoc.Selection.PickObject( ObjectType.Element );
    Element cat = doc.GetElement( sel.ElementId );
    BuiltInCategory builtInCat = (BuiltInCategory) Enum.Parse( typeof( BuiltInCategory ), cat.Category.Id.ToString() );

    //get all views in document
    var views = new FilteredElementCollector( doc )
      .OfClass( typeof( ViewPlan ) )
      .ToElements()
      .ToList();

    //get all the views with same tag in it
    List<View> viewInclude = new List<View>();

    foreach( var view in views )
    {
      try
      {
        uiDoc.ActiveView = view as View;
        var e = new FilteredElementCollector( doc, doc.ActiveView.Id )
          .OfCategory( builtInCat )
          .ToList();

        if( e.Count != 0 )
        {
          viewInclude.Add( view as View );
        }
      }
      catch( Exception )
      {

        continue;
      }
    }

    //loop through each view and set color for tags
    foreach( var view in viewInclude )
    {
      uiDoc.ActiveView = view as View;

      //get list of tags in active view
      List<Element> Tags = new FilteredElementCollector( doc, doc.ActiveView.Id )
        .OfCategory( builtInCat )
        .WhereElementIsNotElementType()
        .ToElements()
        .ToList();

      //get list of tagged elements
      List<Element> taggedElements = new List<Element>();

      foreach( var e in Tags )
      {
        IndependentTag tag = doc.GetElement( e.Id ) as IndependentTag;
        Element taggedElem = tag.GetTaggedLocalElement();
        taggedElements.Add( taggedElem );
      }

      //get the color of the ductsystem
      List<Color> tagColor = new List<Color>();

      BuiltInParameter builtInParam 
        = (BuiltInParameter) Enum.Parse( 
          typeof( BuiltInParameter ), 
          taggedElements[ 0 ]
            .GetParameters( "System Type" )[ 0 ]
            .Id.ToString() );

      foreach( var e in taggedElements )
      {
        Element elem = doc.GetElement( e.Id );
        var param = elem.get_Parameter( builtInParam );
        if( param == null )
          return;
        var systemType = doc.GetElement( param.AsElementId() ) 
          as MEPSystemType;

        var c = systemType.LineColor;

        byte systemColorRed = c.Red;
        byte systemColorGreen = c.Green;
        byte systemColorblue = c.Blue;

        Color color = new Color( systemColorRed, 
          systemColorGreen, systemColorblue );
        tagColor.Add( color );
      }

      var overRide = new OverrideGraphicSettings();

      Transaction trans1 = new Transaction( doc );

      //change the color of the tags in revit
      trans1.Start( "change color tag" );

      int index = 0;

      foreach( var e in Tags )
      {
        doc.ActiveView.SetElementOverrides( e.Id, 
          overRide.SetProjectionLineColor(
            tagColor[ index ] ) );
        index += 1;
      }

      trans1.Commit();

      index = 0;
    }
  }

 

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

jeremy_tammik
Alumni
Alumni

There are a number of comments one could make on this.

 

The Enum.Parse calls are probably unnecessary, and the multiple calls to ToList definitely hurt performance and consume memory.

 

However, I am not yet quite clear what this code actually does.

 

According to its name, I would assume that it moves tags closer to the tagged elements.

 

However, I do not see this happening in the code.

 

So, please explain in detail each step that the code executes, and above all what your overall goal is.

 

It would also be interesting to know how many views and elements you are processing, and at what number performance degrades.

 

Thank you.

 

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

jeremy_tammik
Alumni
Alumni

If al it does is change the colour of certain elements according to their category, there are probably better ways to achieve this.

 

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

Gilles.Lagrilliere
Advocate
Advocate

Hello

 

it changes the color of the tags to the color of the tagged element system type.

 

I hope this makes it clear what my code does.

0 Likes
Message 6 of 13

jeremy_tammik
Alumni
Alumni
Accepted solution

Yup, that helps.

 

Here is your code with less calls to ToList:

 

    public void test( UIDocument uiDoc )
    {
      //current document
      //UIDocument uiDoc = new UIDocument( Document );
      //Document doc = this.Application.ActiveUIDocument.Document;

      Document doc = uiDoc.Document;

      //current view and open views
      View curView = doc.ActiveView;
      var openViews = uiDoc.GetOpenUIViews();
      List<ElementId> openV1 = new List<ElementId>();

      foreach( var view in openViews )
      {
        var i = view.ViewId;
        openV1.Add( i );
      }


      //get builtincategory of selected tag
      Reference sel = uiDoc.Selection.PickObject( ObjectType.Element );
      Element cat = doc.GetElement( sel.ElementId );
      BuiltInCategory builtInCat = (BuiltInCategory) Enum.Parse(
        typeof( BuiltInCategory ), cat.Category.Id.ToString() );

      //get all views in document
      var views = new FilteredElementCollector( doc )
        .OfClass( typeof( ViewPlan ) );

      //get all the views with same tag in it
      List<View> viewInclude = new List<View>();

      foreach( var view in views )
      {
        uiDoc.ActiveView = view as View;
        var e = new FilteredElementCollector( doc, doc.ActiveView.Id )
          .OfCategory( builtInCat );

        if( e.GetElementCount() != 0 )
        {
          viewInclude.Add( view as View );
        }
      }

      //loop through each view and set color for tags
      foreach( var view in viewInclude )
      {
        uiDoc.ActiveView = view as View;

        //get list of tags in active view
        var tags = new FilteredElementCollector( doc, doc.ActiveView.Id )
          .OfCategory( builtInCat )
          .WhereElementIsNotElementType();

        //get list of tagged elements
        List<Element> taggedElements = new List<Element>();

        foreach( var e in tags )
        {
          IndependentTag tag = doc.GetElement( e.Id ) as IndependentTag;
          Element taggedElem = tag.GetTaggedLocalElement();
          taggedElements.Add( taggedElem );
        }

        //get the color of the ductsystem
        List<Color> tagColor = new List<Color>();

        BuiltInParameter builtInParam
          = (BuiltInParameter) Enum.Parse(
            typeof( BuiltInParameter ),
            taggedElements[ 0 ]
              .GetParameters( "System Type" )[ 0 ]
              .Id.ToString() );

        foreach( var e in taggedElements )
        {
          Element elem = doc.GetElement( e.Id );
          var param = elem.get_Parameter( builtInParam );
          if( param == null )
            return;
          var systemType = doc.GetElement( param.AsElementId() )
            as MEPSystemType;

          var c = systemType.LineColor;

          byte systemColorRed = c.Red;
          byte systemColorGreen = c.Green;
          byte systemColorblue = c.Blue;

          Color color = new Color( systemColorRed,
            systemColorGreen, systemColorblue );
          tagColor.Add( color );
        }

        var overRide = new OverrideGraphicSettings();

        Transaction trans1 = new Transaction( doc );

        //change the color of the tags in revit
        trans1.Start( "change color tag" );

        int index = 0;

        foreach( var e in tags )
        {
          doc.ActiveView.SetElementOverrides( e.Id,
            overRide.SetProjectionLineColor(
              tagColor[ index ] ) );
          index += 1;
        }

        trans1.Commit();

        index = 0;
      }
    }

 

Does that help?

 

At what point do problems occur?

   

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

jeremy_tammik
Alumni
Alumni

It might help if you perform all the changes for all the views in one single transaction, instead of starting and committing a new transaction for each view.

  

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

Gilles.Lagrilliere
Advocate
Advocate
 

this is the error I get

 

Capture.PNG

 

but if I place a 'try/catch' block in my code it doesn't give any errors but it still doesn't work as it should on large projects.

 

  //get all the views with same tag in it
      List<View> viewInclude = new List<View>();

      foreach( var view in views )
      {
        try 
				{
					uiDoc.ActiveView = view as View;
					var e = new FilteredElementCollector(doc, doc.ActiveView.Id)
					.OfCategory(builtInCat)
					.ToList();
				
				if (e.Count != 0)
					{
						viewInclude.Add(view as View);
					}
				}
				catch (Exception)
				{
					continue;
				}	
      }

 

0 Likes
Message 9 of 13

jeremy_tammik
Alumni
Alumni

Aha. That is an important hint. Eliminate template views. Try this:

 

  // Get all non-template plan views in document
  var views = new FilteredElementCollector( doc )
    .OfClass( typeof( ViewPlan ) )
    .Cast<ViewPlan>()
    .Where<ViewPlan>( v => !v.IsTemplate );

  

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

jeremy_tammik
Alumni
Alumni

Oh, I notice another thing: for each view that you look at, you are setting it to be the active view in a loop.

 

There is no need for that, and that may be causing a problem.

 

You can run the filtered element collector on the specific view without explicitly making it the active view.

 

For instance, you can combine the loop filtering for views containing elements with the category `builtInCat` right into the filtered element collector like this:

 

  // Get all non-template plan views in document
  var views = new FilteredElementCollector( doc )
    .OfClass( typeof( ViewPlan ) )
    .Cast<ViewPlan>()
    .Where<ViewPlan>( v => !v.IsTemplate )
    .Where<ViewPlan>( v 
      => 0 < new FilteredElementCollector( doc, v.Id )
        .OfCategory( builtInCat )
        .GetElementCount() );

  // Get all the views with same tag in it
  //List<View> viewInclude = new List<View>();

  //foreach( var view in views )
  //{
  //  uiDoc.ActiveView = view as View;
  //  var e = new FilteredElementCollector( doc, doc.ActiveView.Id )
  //    .OfCategory( builtInCat );

  //  if( e.GetElementCount() != 0 )
  //  {
  //    viewInclude.Add( view as View );
  //  }
  //}

  //loop through each view and set color for tags
  foreach( var view in views )
  { 
    ...

 

 

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

jeremy_tammik
Alumni
Alumni

Oh, again.

 

I see that you are setting the active view in the second loop as well.

 

Try to skip that also, e.g., like this:

  

  //loop through each view and set color for tags
  foreach( var view in views )
  {
    //uiDoc.ActiveView = view as View;

    //get list of tags in active view
    var tags = new FilteredElementCollector( doc, view.Id )
      .OfCategory( builtInCat )
      .WhereElementIsNotElementType();

    ...

   

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

jeremy_tammik
Alumni
Alumni

You say you want to change the colour of the tags to the colour of the tagged element system type.

 

To achieve that, would it not be pretty simple to proceed as follows?

 

  • Filter for all tags in the model
  • For each tag, determine the tagged element, its system type and its colour
  • Set the tag colour to the system type colour

 

That would save about 96.38 % of your complexity and code, wouldn't it?

  

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

Gilles.Lagrilliere
Advocate
Advocate

thanks Jeremy

 

Now my macro works for large files and I learned a lot of new stuff!

I don't know which comment I need to accept as solution so I'll pick the first one that helped me.

 

and for my next challenge I try to make my code less complex 😄

0 Likes