.NET

Reply
Valued Contributor
cncah
Posts: 77
Registered: ‎01-15-2014
Message 1 of 6 (186 Views)
Accepted Solution

Need help getting an existing table using vb in .net

186 Views, 5 Replies
08-01-2014 08:12 AM

Hello, I've hit a wall trying to access an existing table by layer name in vb.net. I've seen in the help documents how to play around with tables when creating a new one, but I can't find an example online that gets me access to one without user input. I have only one table in the drawing and it is on layer "BOMTable". I figured this would be enough to filter through the entities in the drawing and get me access to the table. I'm still learning the Autocad API, and I'm willing to go through the motions with trial and error to get certain cell contents via the help documents. But I just need to know how to iterate through all entities in a drawing, then if that entity is on layer "BOMTable", assign my acTable variable to that entity. I'll stumble on from there. Any help would be GREATLY appreciated. Thank You.

I got it.

 

Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
Dim acDB As Database = acDoc.Database
Dim acBlkTbl As BlockTable
Dim acBlkTblRec As BlockTableRecord
Dim acTable As Table = Nothing
Using acTrans As Transaction = acDB.TransactionManager.StartTransaction
acBlkTbl = acTrans.GetObject(acDB.BlockTableId,
OpenMode.ForRead)
acBlkTblRec =
acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _
OpenMode.ForWrite)
For Each acObjId As ObjectId In acBlkTblRec
Dim ent As Entity = acTrans.GetObject(acObjId, OpenMode.ForRead)
If TypeOf ent Is Table And CStr(ent.Layer) = "BOMTable" Then
acTable = ent
Exit For
End If
Next
End Using

 

It is better to have a generic method to get entities from a give type (table, line...), then use it to retrieve any information you want. Here is the code:

 

C#

public class Test
{
[CommandMethod("GetEntitiesByType")]
public static void GetEntitiesByType()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
IEnumerable<Table> list = GetAllEntitiesInModelSpace<Table>(db);
foreach (Table table in list)
{
string layer = table.Layer;
}
}
public static IEnumerable<T> GetAllEntitiesInModelSpace<T>(Database db, OpenMode openMode = OpenMode.ForRead, bool openErased = false)
{
using (Transaction trans = db.TransactionManager.StartTransaction())
{
var blockTable = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
var model = (BlockTableRecord)trans.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead);
var list = new List<T>();
foreach (ObjectId id in model)
{
var entity = trans.GetObject(id, openMode, openErased) as Entity;
if ((entity != null) && (entity is T))
{
object obj2 = entity;
list.Add((T)obj2);
}
}
return list;
}
}
}

 

VB.NET

Public Class Test
<CommandMethod("GetEntitiesByType")> _
Public Shared Sub GetEntitiesByType()
Dim doc = Application.DocumentManager.MdiActiveDocument
Dim db = doc.Database
Dim list As IEnumerable(Of Table) = GetAllEntitiesInModelSpace(Of Table)(db)
For Each table As Table In list
Dim layer As String = table.Layer
Next
End Sub
Public Shared Function GetAllEntitiesInModelSpace(Of T)(db As Database, Optional openMode__1 As OpenMode = OpenMode.ForRead, Optional openErased As Boolean = False) As IEnumerable(Of T)
Using trans As Transaction = db.TransactionManager.StartTransaction()
Dim blockTable = DirectCast(trans.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
Dim model = DirectCast(trans.GetObject(blockTable(BlockTableRecord.ModelSpace), OpenMode.ForRead), BlockTableRecord)
Dim list = New List(Of T)()
For Each id As ObjectId In model
Dim entity = TryCast(trans.GetObject(id, openMode__1, openErased), Entity)
If (entity IsNot Nothing) AndAlso (TypeOf entity Is T) Then
Dim obj2 As Object = entity
list.Add(DirectCast(obj2, T))
End If
Next
Return list
End Using
End Function
End Class

 

We can use all LINQ for IEnumerable type classes to have shorter code, but it will make it difficult to understand than longer code.

 

Valued Contributor
cncah
Posts: 77
Registered: ‎01-15-2014
Message 2 of 6 (171 Views)

Re: Need help getting an existing table using vb in .net

08-01-2014 10:25 AM in reply to: cncah

I got it.

 

Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument

Dim acDB As Database = acDoc.Database

Dim acBlkTbl As BlockTable
Dim acBlkTblRec As BlockTableRecord

Dim acTable As Table = Nothing

Using acTrans As Transaction = acDB.TransactionManager.StartTransaction

   acBlkTbl = acTrans.GetObject(acDB.BlockTableId,
               OpenMode.ForRead)
            acBlkTblRec =
               acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _
               OpenMode.ForWrite)

For Each acObjId As ObjectId In acBlkTblRec

     Dim ent As Entity = acTrans.GetObject(acObjId, OpenMode.ForRead)

     If TypeOf ent Is Table And CStr(ent.Layer) = "BOMTable" Then

        acTable = ent

        Exit For

     End If

Next

End Using

 

Mentor
khoa.ho
Posts: 213
Registered: ‎09-15-2011
Message 3 of 6 (169 Views)

Re: Need help getting an existing table using vb in .net

08-01-2014 10:37 AM in reply to: cncah

It is better to have a generic method to get entities from a give type (table, line...), then use it to retrieve any information you want. Here is the code:

 

C#

public class Test
{
    [CommandMethod("GetEntitiesByType")]
    public static void GetEntitiesByType()
    {
        var doc = Application.DocumentManager.MdiActiveDocument;
        var db = doc.Database;
        IEnumerable<Table> list = GetAllEntitiesInModelSpace<Table>(db);
        foreach (Table table in list)
        {
            string layer = table.Layer;

        }
    }

    public static IEnumerable<T> GetAllEntitiesInModelSpace<T>(Database db, OpenMode openMode = OpenMode.ForRead, bool openErased = false)
    {
        using (Transaction trans = db.TransactionManager.StartTransaction())
        {
            var blockTable = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
            var model = (BlockTableRecord)trans.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead);
            var list = new List<T>();
            foreach (ObjectId id in model)
            {
                var entity = trans.GetObject(id, openMode, openErased) as Entity;
                if ((entity != null) && (entity is T))
                {
                    object obj2 = entity;
                    list.Add((T)obj2);
                }
            }
            return list;
        }
    }
}

 

VB.NET

Public Class Test
    <CommandMethod("GetEntitiesByType")> _
    Public Shared Sub GetEntitiesByType()
        Dim doc = Application.DocumentManager.MdiActiveDocument
        Dim db = doc.Database
        Dim list As IEnumerable(Of Table) = GetAllEntitiesInModelSpace(Of Table)(db)
        For Each table As Table In list

            Dim layer As String = table.Layer
        Next
    End Sub

    Public Shared Function GetAllEntitiesInModelSpace(Of T)(db As Database, Optional openMode__1 As OpenMode = OpenMode.ForRead, Optional openErased As Boolean = False) As IEnumerable(Of T)
        Using trans As Transaction = db.TransactionManager.StartTransaction()
            Dim blockTable = DirectCast(trans.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
            Dim model = DirectCast(trans.GetObject(blockTable(BlockTableRecord.ModelSpace), OpenMode.ForRead), BlockTableRecord)
            Dim list = New List(Of T)()
            For Each id As ObjectId In model
                Dim entity = TryCast(trans.GetObject(id, openMode__1, openErased), Entity)
                If (entity IsNot Nothing) AndAlso (TypeOf entity Is T) Then
                    Dim obj2 As Object = entity
                    list.Add(DirectCast(obj2, T))
                End If
            Next
            Return list
        End Using
    End Function
End Class

 

We can use all LINQ for IEnumerable type classes to have shorter code, but it will make it difficult to understand than longer code.

 

Valued Contributor
cncah
Posts: 77
Registered: ‎01-15-2014
Message 4 of 6 (153 Views)

Re: Need help getting an existing table using vb in .net

08-01-2014 12:43 PM in reply to: khoa.ho

Thank You!

Valued Mentor
KerryBrown
Posts: 269
Registered: ‎11-29-2008
Message 5 of 6 (131 Views)

Re: Need help getting an existing table using vb in .net

08-01-2014 07:20 PM in reply to: khoa.ho

khoa.ho,

Why do you include optional parameters to  GetAllEntitiesInModelSpace ??  

 

 

I can understand perhaps using openErased  but not not openMode .

 

//-------------------------------------------------------

class keyThumper<T> : Lazy<T>;      another  Swamper

Mentor
khoa.ho
Posts: 213
Registered: ‎09-15-2011
Message 6 of 6 (125 Views)

Re: Need help getting an existing table using vb in .net

08-01-2014 09:03 PM in reply to: KerryBrown

I use optional parameters in GetAllEntitiesInModelSpace to get more options of the entity type to read or write. Here is the modified version which is better for faster performance, and presents both OpenMode.ForRead and .ForWrite

 

Instead of using Transaction.GetObject for every objects in model space during the loop, which costs memory and time, we can check class of an ObjectId for a given type.

 

C#

[CommandMethod("ReadEntities")]
public static void ReadEntities()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Editor editor = doc.Editor;
    Database db = doc.Database;
    using (Transaction trans = db.TransactionManager.StartTransaction())
    {
        // Get all lines in model space for read
        IEnumerable<Line> list = GetAllEntitiesInModelSpace<Line>(db);
        foreach (Line line in list)
        {
            // Display line info
            editor.WriteMessage(line.StartPoint.ToString() + "," + line.EndPoint.ToString());
        }
    }
}

[CommandMethod("WriteEntities")]
public static void WriteEntities()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Editor editor = doc.Editor;
    Database db = doc.Database;
    using (Transaction trans = db.TransactionManager.StartTransaction())
    {
        // Get all circles in model space for write
        IEnumerable<Circle> list = GetAllEntitiesInModelSpace<Circle>(db, OpenMode.ForWrite);
        foreach (Circle circle in list)
        {
            // Change circle radius by multiply 2
            circle.Radius *= 2;
            // Downgrade this entity to read before transaction commit
            circle.DowngradeOpen();
        }
        trans.Commit();
    }
}

public static IEnumerable<T> GetAllEntitiesInModelSpace<T>(Database db, OpenMode openMode = OpenMode.ForRead, bool openErased = false) where T : DBObject
{
    var list = new List<T>();
    using (Transaction trans = db.TransactionManager.TopTransaction ?? db.TransactionManager.StartTransaction())
    {
        var blockTable = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
        var model = (BlockTableRecord)trans.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead);
        foreach (ObjectId id in model)
        {
            if (id.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(T))))
            {
                DBObject entity = trans.GetObject(id, openMode, openErased);
                list.Add((T)entity);
            }
        }
    }
    return list;
}

 

VB.NET

<CommandMethod("ReadEntities")> _
Public Shared Sub ReadEntities()
    Dim doc As Document = Application.DocumentManager.MdiActiveDocument
    Dim editor As Editor = doc.Editor
    Dim db As Database = doc.Database
    Using trans As Transaction = db.TransactionManager.StartTransaction()
        ' Get all lines in model space for read
        Dim list As IEnumerable(Of Line) = GetAllEntitiesInModelSpace(Of Line)(db)
        For Each line As Line In list
            ' Display line info
            editor.WriteMessage(line.StartPoint.ToString() + "," + line.EndPoint.ToString())
        Next
    End Using
End Sub

<CommandMethod("WriteEntities")> _
Public Shared Sub WriteEntities()
    Dim doc As Document = Application.DocumentManager.MdiActiveDocument
    Dim editor As Editor = doc.Editor
    Dim db As Database = doc.Database
    Using trans As Transaction = db.TransactionManager.StartTransaction()
        ' Get all circles in model space for write
        Dim list As IEnumerable(Of Circle) = GetAllEntitiesInModelSpace(Of Circle)(db, OpenMode.ForWrite)
        For Each circle As Circle In list
            ' Change circle radius by multiply 2
            circle.Radius *= 2
            ' Downgrade this entity to read before transaction commit
            circle.DowngradeOpen()
        Next
        trans.Commit()
    End Using
End Sub

Public Shared Function GetAllEntitiesInModelSpace(Of T As DBObject)(db As Database, Optional openMode1 As OpenMode = OpenMode.ForRead, Optional openErased As Boolean = False) As IEnumerable(Of T)
    Dim list = New List(Of T)()
    Using trans As Transaction = If(db.TransactionManager.TopTransaction, db.TransactionManager.StartTransaction())
        Dim blockTable = DirectCast(trans.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
        Dim model = DirectCast(trans.GetObject(blockTable(BlockTableRecord.ModelSpace), OpenMode.ForRead), BlockTableRecord)
        For Each id As ObjectId In model
            If id.ObjectClass.IsDerivedFrom(RXClass.GetClass(GetType(T))) Then
                Dim entity As DBObject = trans.GetObject(id, openMode1, openErased)
                list.Add(DirectCast(entity, T))
            End If
        Next
    End Using
    Return list
End Function

 

Khoa

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.