Low angle view of steel network cable trunking box.

Setting IFC Material Overrides for Cable Tray and Conduit

Digital By Aug 07, 2025 No Comments

In a previous post, we looked at how to set IFC material overrides for pipe fittings. But when it comes to cable tray and conduit, things get a bit trickier. Unlike pipe and duct, cable tray and conduit don’t belong to a system in Revit, so there’s no MEP System parameter to piggyback off.

That’s why most teams colour them using the Service Type parameter instead. And if you don’t do anything else? You’ll get dull, grey IFC exports. Every time.

Here’s how to fix that — properly..

The Problem With Cable Tray and Conduit

Electrical teams often rely on filters to colour tray and conduit in Revit which is driven by the Service Type parameter. But filters don’t carry through to IFC exports. Without materials applied directly to the elements, your exports stay grey.

To solve this, we need to generate materials based on the Service Type, then apply them via the IfcSingleMaterialOverride parameter.

The most reliable approach is to set the Service Type at the type level, using predefined conduit and tray types in your template. This means the parameter applied automatically as you model, just set the view filters in your template and voila! No manual intervention. No forgotten elements.

A caveat — this will mean duplicating cable tray and conduit fitting types (one for each service type) and updating routing settings to use those fittings for each cable tray and conduit service. While some people don’t love the idea of duplication or growing the template size, the overhead is minimal, and it’s a one-time job that pays off every time you get stuck into actual modelling work.

Common Pitfalls to Avoid

While we’re on the topic, let’s be real. A lot of teams make working with electrical services harder than it needs to be by.

  • Using shared parameters instead of native ones.
  • Manually updating Service Type on every tray run.
  • Using worksets to override colours (yuck!).

These hacks might seem faster, but they break your data consistency and create more rework later. Especially when IFC or asset data is part of the deliverable.

The Solution

Update your materials, collect your elements, and push the correct override — all based on Service Type.

🧠 Pro tip: watch out for inconsistent abbreviations, in the example below, both “E” and “LV” refer to Low Voltage. Either clean them up in your current file or template or handle them in the mapping of your code.


public void SetElectricalMaterialOverrides()
  {
   UIDocument uidoc = this.ActiveUIDocument;
   Document doc = uidoc.Document;

   // Define service type to material name mapping
   Dictionary<string, string> serviceToMaterial = new Dictionary<string, string>
   {
    { "LV", "EL_LV" },
    { "E", "EL_LV" }, // No consistency! E is also LV!
    { "HV", "EL_HV" },
    { "S", "EL_Security" },
    { "C", "EL_Comms" },
    { "F", "EL_Fire" }
    // Add more mappings as needed
   };

   // Define material colors (RGB)
   Dictionary<string, Color> materialColors = new Dictionary<string, Color>
   {
    { "EL_LV", new Color(255, 128, 0) },     // Orange
    { "EL_HV", new Color(128, 0, 0) },     // Brown/Maroon
    { "EL_Security", new Color(0, 128, 255) },     // Blue
    { "EL_Comms", new Color(0, 128, 0) },    // Green
    { "EL_Fire", new Color(128, 0, 255) }     // Purple
   };
   
   int updatedCount = 0;

   using (Transaction tx = new Transaction(doc, "Set Electrical Material Overrides"))
   {
    tx.Start();

    // Step 1: Ensure materials exist
    foreach (var kvp in materialColors)
    {
     string matName = kvp.Key;
     Color color = kvp.Value;

     Material existingMat = new FilteredElementCollector(doc)
      .OfClass(typeof(Material))
      .Cast<Material>()
      .FirstOrDefault(m => m.Name == matName);

     if (existingMat == null)
     {
      ElementId newMatId = Material.Create(doc, matName);
      Material newMat = doc.GetElement(newMatId) as Material;

      if (newMat != null)
      {
       newMat.Color = color;
      }
     }
    }

    // Step 2: Collect cable trays and conduits

    FilteredElementCollector elements = new FilteredElementCollector(doc)
     .WherePasses(new LogicalOrFilter(new List<ElementFilter>
                                      {
                                       new ElementCategoryFilter(BuiltInCategory.OST_CableTray),
                                       new ElementCategoryFilter(BuiltInCategory.OST_CableTrayFitting),
                                       new ElementCategoryFilter(BuiltInCategory.OST_Conduit),
                                       new ElementCategoryFilter(BuiltInCategory.OST_ConduitFitting)
                                      }))
     .WhereElementIsNotElementType();

    // Step 3: Apply material override
    foreach (Element elem in elements)
    {
     Parameter serviceParam = elem.LookupParameter("Service Type");
     if (serviceParam == null || !serviceParam.HasValue)
      continue;

     string serviceType = serviceParam.AsString();
     if (string.IsNullOrEmpty(serviceType))
      continue;

     if (!serviceToMaterial.ContainsKey(serviceType))
      continue;

     string materialName = serviceToMaterial[serviceType];

     Parameter overrideParam = elem.LookupParameter("IfcSingleMaterialOverride");
     if (overrideParam != null && !overrideParam.IsReadOnly)
     {
      overrideParam.Set(materialName);
      updatedCount++;
     }
    }

    tx.Commit();
   }

   TaskDialog.Show("Done", "Electrical material overrides applied to "+updatedCount+" elements.");
  }Code language: C# (cs)

How It Works

  1. Define mappings for Service Type → Material name and colour
  2. Create missing materials automatically
  3. Collect tray and conduit elements
  4. Apply the override to IfcSingleMaterialOverride

This method ensures your IFC exports look how they should — with accurate colours, clean data, and zero manual effort once it’s set up.

Have you run into the same grey export issue? Let me know how you solved it, or didn’t, in the comments.

No Comments

Leave a comment

Your email address will not be published. Required fields are marked *