Announcements

The Autodesk Community Forums has a new look. Read more about what's changed on the Community Announcements board.

Getting the multiple element IDs for materials in a wall

Anonymous

Getting the multiple element IDs for materials in a wall

Anonymous
Not applicable

I am trying to get a list of the materials that are contained within each wall type. Ideally I would like the names but as a start I am just trying to get the material IDs. I am using the following code (adapted from the Revit Intro Lab 1) where I iterate through the wall types and have a sub-routine to iterate through the materialIds of each WallType. Using this code it seems that the sub-foreach routine is not working and the string p that I create is left unfilled. Any advice would be much appreciated. 

 

 

        FilteredElementCollector wallTypes // 2014
          = new FilteredElementCollector(rvtDoc)
            .OfClass(typeof(WallType));

        string s = "";
        

        foreach (WallType wallType in wallTypes)
        {

string p = ""; foreach (ElementId mat3 in wallType.GetMaterialIds(false)) { p += mat3.ToString() + "\r\n"; } s += wallType.Name + p + "\r\n"; } // Show the result: TaskDialog.Show( "Revit Intro Lab", "Wall Types (in main instruction):\n\n" + s);
0 Likes
Reply
Accepted solutions (1)
1,509 Views
5 Replies
Replies (5)

GonçaloFeio1321
Enthusiast
Enthusiast

Try this:

 

 

public IEnumerable<Material> Get(WallType wallType)
{
if (wallType== null)
{
throw new ArgumentNullException(nameof(wallType));
}
var document = wallType.Document; var layers = wallType.GetCompoundStructure().GetLayers(); foreach (var layer in layers) { var materialId = layer.MaterialId; if (materialId != ElementId.InvalidElementId) { yield return document.GetElement(layer.MaterialId) as Material; } } }

 

 

 

The Element GetMaterialIds method works only for model instances, not their types.

 

Edit: Added a nice check for null

0 Likes

Anonymous
Not applicable

Thanks for your reply. I have tried implementing your Get() method as follows: 

 

 

FilteredElementCollector wallTypes // 2014
              = new FilteredElementCollector(rvtDoc)
                .OfClass(typeof(WallType));

string s = "";

foreach (WallType wallType in wallTypes)
{
s += Get(wallType) + "\r\n";
}

TaskDialog.Show(
          "Revit Intro Lab",
          "Wall Types (in main instruction):\n\n" + s);

However when I print the result to dialog I get the following message: 

 

"Material_Select_2 + <Get>d__0" for each instance 

 

Material_Select_2 is the name of my class, I am guessing this has something to do with the variable it is stored in, do you have any idea how I can convert this to a string? 

 

Thanks

0 Likes

GonçaloFeio1321
Enthusiast
Enthusiast

The Get method returns a IEnumerable<Material>, even duplicates. And you are just adding that to the string.

 

Try replacing the line s += Get(wallType) + "\r\n"; wih this:

 

 

 

foreach (var material in Get(wallType))
{
    builder.AppendLine($"Material: {material.Name}");
}

 

0 Likes

Anonymous
Not applicable

Thanks again for your reply. I incorporated this method and now the code is generating this error " System.NullReferenceException: Object reference not set to an instance of an object . at Material_Select_2.<Get>d__0.MoveNext()" 

 

I tried to incorporate an exception, as you can see below, but I am still getting the same error: 

 

 

StringBuilder builder = new StringBuilder();
        
        string s = "";
                
        foreach (WallType wallType in wallTypes)
        {
        
            foreach (var material in Get(wallType))
            {
                if (material == null)
                {
                    throw new ArgumentNullException(nameof(material));
                }
                
                builder.AppendLine($"Material: {material.Name}");
            }
        }
0 Likes

GonçaloFeio1321
Enthusiast
Enthusiast
Accepted solution

Allan, here is the refactored method.

 

public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
    var uiDoc = commandData.Application.ActiveUIDocument;
    var rvtDoc = uiDoc.Document;

    using (var collector = new FilteredElementCollector(rvtDoc))
    {
        using (var filtered = collector.OfClass(typeof(WallType)))
        {
            var builder = new StringBuilder();

            foreach (var wallType in filtered.OfType<WallType>())
            {
                if (wallType.Kind == WallKind.Basic)
                {
                    builder.AppendLine($"WallType: {wallType.Name}");

                    foreach (var material in Get(wallType))
                    {
                        builder.AppendLine($"Material: {material.Name}");
                    }
                }
            }

            TaskDialog.Show("Output", builder.ToString());
        }
    }            

    return Result.Succeeded; // Why Failed?
}