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.