In this lab, we explore the Revit document elements,
and implement a class Lab2_1_Elements
derived from IExternalCommand
in the Labs2 module.
For the Revit element exploration, we will require the use of
some additional namespaces,
so we add statements to include these as well.
using System; using System.IO; using Autodesk.Revit; using Autodesk.Revit.Elements; using Geo = Autodesk.Revit.Geometry; using Autodesk.Revit.Parameters; using Autodesk.Revit.Symbols; using XYZ = Autodesk.Revit.Geometry.XYZ; using XYZArray = Autodesk.Revit.Geometry.XYZArray; namespace Labs { /// <summary> /// List all document elements. /// </summary< public class Lab2_1_Elements : IExternalCommand { public IExternalCommand.Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements ) { return IExternalCommand.Result.Succeeded; } } }
Imports System.IO Imports Autodesk.Revit.Symbols Imports Autodesk.Revit.Collections Imports Autodesk.Revit.Geometry Public Class Lab2_1_Elements Implements IExternalCommand Public Function Execute( _ ByVal commandData As ExternalCommandData, _ ByRef message As String, _ ByVal elements As ElementSet) _ As IExternalCommand.Result _ Implements IExternalCommand.Execute Return IExternalCommand.Result.Succeeded End Function End Class
Since the output will be too big for a message box, we will redirect it to a text file.
We define the file pathname in a string constant and implement a separate class to
manage all the constants, strings and similar resources of our project.
Add a new class LabConstants
to the project by right clicking on the project
and selecting Add > Class... and then add the following string constant to it:
namespace Labs { class LabConstants { public const string gsFilePathLab2_1 = @"c:\tmp\RevitElements.txt"; } }
Namespace Labs Module LabConstants Public gsFilePathLab2_1 As String = "c:\tmp\RevitElements.txt" End Module End Namespace
Returning to the Lab2_1_Elements
command,
start by opening the file to write to:
// Typical .NET error-checking (should be done everywhere, // but will be omitted for clarity in some of the following // labs unless we expect exceptions) StreamWriter sw; try { sw = new StreamWriter( LabConstants.gsFilePathLab2_1 ); } catch( Exception e ) { LabUtils.ErrorMsg( "Cannot open " + LabConstants.gsFilePathLab2_1 + "; Exception=" + e.Message ); return IExternalCommand.Result.Failed; }
' Typical .NET error-checking (should be done everywhere, but will be omitted ' for clarity in some of the following labs unless we expect exceptions) Dim sw As StreamWriter Try sw = New StreamWriter(gsFilePathLab2_1) Catch e As Exception MsgBox("Cannot open " & gsFilePathLab2_1 & "; Exception=" & e.Message) Return IExternalCommand.Result.Failed End Try
Finally, here is standard way of looping all document elements and writing some of their properties to the stream. Please note that this kind of loop is extremely time-consuming and should generally be avoided in an application. Further on, we will explore how to use filters to avoid it:
try { // *ALL* elements are bundled together and accessible via Document's ElementIterator WaitCursor waitCursor = new WaitCursor(); string line; Element elem; ElementIterator iter = commandData.Application.ActiveDocument.Elements; while( iter.MoveNext() ) { elem = iter.Current as Element; line = "Id=" + elem.Id.Value.ToString(); // Element Id line += "; Class=" + elem.GetType().Name; // Element class (System.Type) //Debug.WriteLine( line ); // The element category is not implemented for all classes, // it may return null; for Family elements, one can sometimes // use the FamilyCategory property instead. string s = string.Empty; if( elem is Family && null != ((Family) elem).FamilyCategory ) { s = ((Family) elem).FamilyCategory.Name; } if( 0 == s.Length && null != elem.Category ) { s = elem.Category.Name; } if( 0 == s.Length ) { s = "?"; } line += "; Category=" + s; // Element Name (different meaning for different classes, but mostly implemented "logically") // Later, we'll see that more precise info on elements can be obtained in class-specific ways... line += "; Name=" + elem.Name; sw.WriteLine( line ); } } catch( Exception e ) { message = e.Message; return CmdResult.Failed; }
' *ALL* elements are bundled together and accessible via Document's ElementIterator Dim sLine As String Dim elem As Revit.Element Dim iter As ElementIterator = commandData.Application.ActiveDocument.Elements Do While (iter.MoveNext) ' current Element elem = iter.Current ' Element Id sLine = "Id=" & elem.Id.Value.ToString ' Element class (System.Type) sLine += "; Class=" & elem.GetType.Name ' Element Category (not implemented for all classes!) Dim sCatName As String = "" If TypeOf elem Is Family Then Dim f As Family = elem If Not f.FamilyCategory Is Nothing Then sCatName = f.FamilyCategory.Name End If End If If 0 = sCatName.Length And Not elem.Category Is Nothing Then sCatName = elem.Category.Name End If If 0 = sCatName.Length Then sCatName = "?" End If sLine += "; Category=" & sCatName ' Element Name (different meaning for different classes, but mostly implemented "logically") ' Later, we'll see that more precise info on elements can be obtained in class-specific ways... Dim sName As String sName = elem.Name sLine += "; Name=" & sName ' write the Line sw.WriteLine(sLine) Loop
Don't forget to close the file and return a valid result to Revit:
sw.Close(); LabUtils.InfoMsg( "Element list has been written to " + LabConstants.gsFilePathLab2_1 + "." );
sw.Close() MsgBox("Elements list has been created in " & gsFilePathLab2_1 & "!")
Compile and link the project and update the Revit.ini file accordingly. Or load and run the command with the help of Add-in Manager.
Run the command and examine and discuss the contents of the created file with the course instructor and your peers.
next previous home copyright © 2007-2009 jeremy tammik, autodesk inc. all rights reserved.