This post is due to Joe Ye in our Beijing office. Many thanks, Joe! While proof reading my handouts for the Revit API tips and tricks session at AU, DE205-3 Enhancing Your Revit Add-In, Joe pointed out that creating a new type or family symbol is a hot topic often asked by developers. It is not obvious from the Revit API help documentation or samples how to achieve this. It is simple to solve, though: one can use the Duplicate() method to create a new type, and then modify the parameters or properties required.
Here is an example in VB duplicating a wall type by doubling the thickness of each layer in its compound layer structure:
Public Function Execute( _ ByVal commandData As ExternalCommandData, _ ByRef message As String, _ ByVal elements As ElementSet) _ As IExternalCommand.Result _ Implements IExternalCommand.Execute Try Dim app As Application = commandData.Application Dim doc As Document = app.ActiveDocument Dim els As ElementSet = doc.Selection.Elements Dim e As Element Dim newWallTypeName As String _ = "NewWallType_with_Width_doubled" For Each e In els If TypeOf e Is Wall Then Dim wall As Wall = e Dim wallType As WallType wallType = wall.WallType Dim newWallType As WallType newWallType = wallType.Duplicate(newWallTypeName) Dim layers As CompoundStructureLayerArray layers = newWallType.CompoundStructure.Layers Dim layer As CompoundStructureLayer For Each layer In layers layer.Thickness *= 2 Next wall.WallType = newWallType Exit For End If Next Return IExternalCommand.Result.Succeeded Catch ex As Exception message = ex.ToString() Return IExternalCommand.Result.Failed End Try End Function
This command iterates over the currently selected elements. If a wall has been selected, its wall type is retrieved and duplicated to create a new wall type. In its compound layer structure, the thickness of every layer is doubled, and the new wall type is assigned to the selected wall. The command terminates as soon as the first selected wall has been processed.
Here is a different example in C# duplicating a column type, setting a new fixed value for its radius:
public CmdResult Execute( ExternalCommandData commandData, ref string message, ElementSet elements ) { Application app = commandData.Application; Document doc = app.ActiveDocument; string familyName = "Concrete-Round-Column"; Filter f = app.Create.Filter.NewFamilyFilter( familyName ); List<RvtElement> families = new List<RvtElement>(); doc.get_Elements( f, families ); if( 1 > families.Count ) { message = "No suitable family found."; return CmdResult.Failed; } Family fam = families[0] as Family; FamilySymbol famSym = null; foreach( FamilySymbol fs in fam.Symbols ) { famSym = fs; break; } // create a new family symbol using Duplicate: string newFamilyName = "NewRoundColumn 3"; FamilySymbol newFamSym = famSym.Duplicate( newFamilyName ) as FamilySymbol; // set the radius to a new value: Parameter par = newFamSym.get_Parameter( "b" ); par.Set( 3 ); return CmdResult.Succeeded; }
Hi Jeremy,
I've been trying to adapt your wall code to enable a user to change a family symbol to another type (of the same family),
I can duplicate the selected symbol and change parameters etc; however I am unable to find a way to replace the selected symbol with the new one.
Regards
Anthony
Posted by: anthony | December 03, 2009 at 23:15
Dear Anthony,
There is a very useful sample demonstrating exactly what you are asking for in the Revit API introduction labs:
http://thebuildingcoder.typepad.com/files/rac_labs_2009-11-24.zip
Look at Lab3_4_ChangeSelectedInstanceType. I should actually describe this command in detail in a separate blog post some day ...
Cheers, Jeremy.
Posted by: Jeremy Tammik | December 04, 2009 at 00:22
Hi Jeremy,
This is brilliant, Thanks for your help
Regards
Anthony.
Posted by: Anthony Forlong | December 04, 2009 at 14:31
Dear Anthony,
Prompted by another similar question, I finally got around to publishing a more detailed description of Lab3_4_ChangeSelectedInstanceType:
http://thebuildingcoder.typepad.com/blog/2010/07/change-element-type.html
Cheers, Jeremy.
Posted by: Jeremy Tammik | July 19, 2010 at 01:34