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: 

FilteredElementCollector - Unreferenced Sections Only

10 REPLIES 10
Reply
Message 1 of 11
62BJW
904 Views, 10 Replies

FilteredElementCollector - Unreferenced Sections Only

I have a FilteredElementCollector for sections (ViewSection). Can it be modified to get only sections that are not referenced? Thanks

 

var secIds = new FilteredElementCollector(doc)
.OfClass(typeof(ViewSection))
.ToElementIds();
f.Refresh();
10 REPLIES 10
Message 2 of 11
recepagah12
in reply to: 62BJW

I don't know what referenced section means but you can search Revit Lookup for this. If that means section view depend on another view you can check the dependent views of the element. Here is the code snippet.

This collector collects if section view has no dependent view.

var viewSections = new FilteredElementCollector(doc)
    .OfClass(typeof(ViewSection))
    .Cast<ViewSection>()
    .Where(q => q.GetDependentViewIds().Count == 0);

I hope this helps,

Recep.

Message 3 of 11
62BJW
in reply to: recepagah12

Thanks for the reply. I may be using the wrong terminology. I'm trying to get Sections that are not on sheets.

Message 4 of 11
recepagah12
in reply to: 62BJW

Sorry, I misunderstood your question. Here is a code snippet that shows which building section views didn't add to sheets. You can restrict to the specified sheet to as you wish. I tried myself this code in Visual Studio 2019 and Revit 2020 and it worked.

// Collect all building section views
var sectionViews = new FilteredElementCollector(doc) .OfClass(typeof(ViewSection)) .Cast<ViewSection>() // This filter restrict the filter for only building sections. // You can obtain parameter and value from Revit LookUp. .Where(q => q.get_Parameter(BuiltInParameter.ELEM_FAMILY_AND_TYPE_PARAM).AsValueString() == "Section: Building Section") .GetEnumerator(); // Collect all sheets var sheets = new FilteredElementCollector(doc) .OfClass(typeof(ViewSheet)) .Cast<ViewSheet>() .GetEnumerator(); while (sheets.MoveNext()) { var sheet = sheets.Current; foreach (var viewId in sheet.GetAllPlacedViews()) { var view = doc.GetElement(viewId) as View;
// Check if view is section view if (view.ViewType == ViewType.Section) { while (sectionViews.MoveNext()) { ViewSection sectionView = sectionViews.Current; // If views in sheet don't contain if (sectionView.Id != viewId) { TaskDialog.Show("Missing Section View", sectionView.Name + " isn't added"); }
// If sheet contains nothing if (viewId == null) TaskDialog.Show("Missing Section View", sectionView.Name + " isn't added"); } } } }

I hope this helps,

Recep.

Message 5 of 11
jeremytammik
in reply to: 62BJW

Dear Bernie,

 

Thank you for your query, and many thanks to Recep for his very helpful answers.

 

I have a suggestion based on a slightly more abstract view of the task which may help implement a more optimised solution for both this and other purging tasks.

 

By the way, looking back at your original question: What is `f`, that you call `Refresh` on? I guess that does not matter?

 

I believe this can indeed be easily solved.

 

The trick is to find some characteristic feature to test on the ViewSection class that let us determine whether it is referenced or not, or how many references to it exist.

 

What is a reference to a section view, and where can it be determined?

 

Is it always a reference from a sheet view?

 

Can it always be determined by calling the ViewSheet GetAllPlacedViews method?

 

http://www.revitapidocs.com/2020/af2ee879-173d-df3a-9793-8d5750a17b49.htm

 

If so, then here is my suggestion:

 

The Revit API GetAllPlacedViews method defines a relationship mapping a ViewSheet to all views placed on it, including ViewSection objects.

 

This relationship can easily be inverted to map the ViewSection objects (or all placed views) to all ViewSheet objects referencing it.

 

I discussed a simple relationship inverter in one of the first blog posts, number 16, in 2008:

 

http://thebuildingcoder.typepad.com/blog/2008/10/relationship-in.html

 

It is maintained as part of The Building Coder samples, in the module CmdRelationshipInverter.cs.

 

Later, in 2009, The Building Coder also discussed the relationship between viewports and sheets:

 

http://thebuildingcoder.typepad.com/blog/2009/01/viewports-and-sheets.html

 

The discussion there and the command that it implements is too convoluted and gets into too much detail for me to understand fully right here and now. I am either too lazy, busy or obtuse. So, instead, I'll start again from scratch.

 

Implement map_sheet_to_placed_views like this:

 

  •   Dictionary<int, List<int>> map_sheet_to_placed_views
  •   For each sheet, call GetAllPlacedViews
  •   Add the integer values of the sheet and placed views element ids as key and value

 

To invert the relationship:

 

  •   Dictionary<int, List<int>> map_placed_view_to_sheets
  •   Iterate over all the placed sheet entries in the values in map_sheet_to_placed_views
  •   For each placed sheet, add its element id integer value as key to map_placed_view_to_sheets if it does not already exist, and the associated sheet int key to the associated list of int value

 

With that reverse relationship set up, you know that every placed view has an entry in map_placed_view_to_sheets pointing to the sheets it has been placed on.

 

An unplaced view has no such entry.

 

Therefore, you can simply add a post-processing step to the filtered element collector above to eliminate the placed views from the filter results and retain only unplaced views:

 

  var secIds = new FilteredElementCollector(doc)
    .OfClass(typeof(ViewSection))
    .ToElementIds()
    .Where<ElementId>( id => 
      !map_placed_view_to_sheets.ContainsKey(id.IntegerValue) );

 

One big advantage of this approach is that you know exactly what you are doing, and that each step is performant:

 

  • One single filtered element collector call to retrieve all the sheets and create map_sheet_to_placed_views
  • The relationship inversion, a pretty fast operation
  • One single filtered element collector call to retrieve all section views

 

I hope this helps.

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 6 of 11
62BJW
in reply to: jeremytammik

Thanks for the reply Jeremy, The "f' that I'm refreshing is a progress dialog. Something so the user doesn't think it's stalled. I'm attempting to delete various kinds of user selected (checkBox) annotations from all views. Here's the Section portion of the code.

 

        // Sections
        void DeleteSections(Document doc)
        {
            ProcessingForm f = new ProcessingForm();
            f.lblProcessing.Text = "Deleting sections... ";
            f.Show();
            f.Refresh();

            var secIds = new FilteredElementCollector(doc)
            .OfClass(typeof(ViewSection))
            .ToElementIds();
            f.Refresh();
            foreach (var sec_id in secIds)
            {
                try
                {
                    doc.Delete(sec_id);
                    secCount++;
                }
                catch
                {
                    f.Refresh();
                    f.lblProcessing.Text = "Deleting sections... " + secCount.ToString() + " deleted.";
                    f.Refresh();
                }
            }
            f.Close();
        }
Message 7 of 11
jeremytammik
in reply to: 62BJW

You can probably speed it up significantly by not deleting the sections one at a time, but all at once, in one single call to Delete, passing in the whole list of element ids.

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 8 of 11
jeremytammik
in reply to: 62BJW

Looking forward to hearing how it goes with the filtered retrieval of unplaced section views!

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 9 of 11
62BJW
in reply to: jeremytammik

Hi Jeremy,

I'm getting some errors when I use the snipit you sent me. I've added two attachments. Thanks for the help!

 

        // Sections
        void DeleteSections(Document doc)
        {
            ProcessingForm f = new ProcessingForm();
            f.lblProcessing.Text = "Deleting sections... ";
            f.Show();
            f.Refresh();

            var secIds = new FilteredElementCollector(doc)
              .OfClass(typeof(ViewSection))
              .ToElementIds()
              .Where<ElementId>(id =>
              !map_placed_view_to_sheets.ContainsKey(id.IntegerValue));

            f.Refresh();
            foreach (var sec_id in secIds)
            {
                try
                {
                    doc.Delete(sec_id);
                    secCount++;
                }
                catch
                {
                    f.Refresh();
                    f.lblProcessing.Text = "Deleting sections... " + secCount.ToString() + " deleted.";
                    f.Refresh();
                }
            }
            f.Close();
        }

 

 

Message 10 of 11
jeremytammik
in reply to: 62BJW

Dear Bernie,

 

Thank you for your update.

 

Yes, of course.

 

I provided instructions explaining how to:

 

  • Implement the dictionary map_sheet_to_placed_views by iterating over the sheets and collecting the results from calling GetAllPlacedViews on each of them
  • Invert the relationship to define and populate map_placed_view_to_sheets

 

I tried to explain exactly how to achieve that. The blog post on inverting a relationship explains the second step, and the first is really trivial.

 

If you have not implemented those two steps, these dictionaries will not exist.

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 11 of 11
62BJW
in reply to: jeremytammik

Thanks Jeremy,

I'm not sure I understand how to do that but will investigate further. Thanks for pointing me in the right direction.

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