.NET

Reply
Member
Shannon.Edwards
Posts: 3
Registered: ‎06-25-2012
Message 1 of 7 (321 Views)

[VB.NET] Can't find blocks in drawing

321 Views, 6 Replies
03-10-2014 04:34 PM

I'm trying to migrate some old macros we have developed to VB.NET and I'm having some difficulties with what (I think) should be a fairly simple thing to do. I'm trying to open a specific block (I know the block name) and read the attributes, but I'm having trouble even getting the block. I've spent about a day now reading up on BlockTableRecords, searching the forums and following different examples, but I can't seem to load any objects in the drawing.

 

main.vb

Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices

Namespace CADPLUGIN

    Public Class Commands
        <CommandMethod("Welcon", CommandFlags.Session)>
        Public Shared Sub ShowForm()
            Dim frm As New Form1

            'Launch user form
            Application.ShowModelessDialog(frm)
        End Sub
    End Class

End Namespace

 

 Form1.vb

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices

Public Class Form1
    Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click
        Dim Path As String = "C:\Test\CADPLUGIN\dwgs\11-E-03436_SHT2_rB.dwg"
        Dim i As Integer

        'Set up AutoCAD and load drawing
        Dim acDocMgr As DocumentCollection = Application.DocumentManager
        Dim acDoc As Document = DocumentCollectionExtension.Open(acDocMgr, Path, False)
        Dim acDb As Database = acDocMgr.MdiActiveDocument.Database

        'Init transaction manager and get block table
        Using acTrans As Transaction = acDb.TransactionManager.StartTransaction()
	    Dim acBlkTbl As BlockTable = acTrans.GetObject(acDb.BlockTableId, OpenMode.ForRead)
            Dim acBlkTblRec As BlockTableRecord = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForRead)

            For Each acBlkId As ObjectId In acBlkTblRec
	        'DO SOMETHING
                i = i + 1
            Next

End Using End Sub End Class

The idea is that I'd loop through all the objects in the Model Space until the block I want is found, and then get it's attributes. I've just set up a simple counter to start off with, which should increment for each object. But when I debug the script it just skips the for loop completely and ends the sub.

 

What am I doing wrong? How do I access blocks using the ACAD .NET API?

Mentor
mzakiralam
Posts: 230
Registered: ‎11-09-2012
Message 2 of 7 (295 Views)

Re: [VB.NET] Can't find blocks in drawing

03-11-2014 01:10 AM in reply to: Shannon.Edwards

Hi ,

Try to lock the document before starting  transaction. As you are using modeless dialog so to access a document you have to lock it first. you can use something like below:

 

Using acLckDoc AsDocumentLock = acDoc.LockDocument()

Using acTrans AsTransaction = acCurDb.TransactionManager.StartTransaction()

'do as you like

EndUsing

EndUsing

*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 3 of 7 (293 Views)

Re: [VB.NET] Can't find blocks in drawing

03-11-2014 01:20 AM in reply to: Shannon.Edwards

See codes gathered from my old project, change to your suit

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Member
Shannon.Edwards
Posts: 3
Registered: ‎06-25-2012
Message 4 of 7 (261 Views)

Re: [VB.NET] Can't find blocks in drawing

03-11-2014 02:57 PM in reply to: Shannon.Edwards

Thanks for the replies, but I think I found the problem. I was pointing the database to DocumentManager.MdiActiveDocument.Database

 

Dim acDocMgr As DocumentCollection = Application.DocumentManager
Dim acDoc As Document = DocumentCollectionExtension.Open(acDocMgr, Path, False)
Dim acDb As Database = acDocMgr.MdiActiveDocument.Database

Changing it fo acDoc.Database seems to have solved the problem. Here's the final code I came up with. Instead of looping through the entire BlockTableRecord, I'm using a selection filter to create an array of all the blocks in the Model Space and then loop through them. If the block isn't found, it tries again in the Paper Space.

 

Private Function SelFilter(SearchElem As String, Optional ByVal Space As Integer = 0)
    'Create a selection filter to limit the number of iterations required when looping through drawing objects
    'Pass the element name as a string and a Model/Paper Space selection
    '(0=Model Space, 1=Paper Space)
    Dim acTypValAr(1) As TypedValue
    acTypValAr.SetValue(New TypedValue(67, Space), 0)
    acTypValAr.SetValue(New TypedValue(DxfCode.Start, SearchElem), 1)
    Dim acSelFtr As SelectionFilter = New SelectionFilter(acTypValAr)
    Return acSelFtr
End Function

Private Function ReadTitleblock(ByVal dwgPath As String, ByVal Index As Integer)
    Dim DwgAtts As New TransmittalData
    Dim bBlkFnd As Boolean = False

    'Set up AutoCAD and load drawing
    Dim acDocMgr As DocumentCollection = Application.DocumentManager
    Dim acDoc As Document = DocumentCollectionExtension.Open(acDocMgr, dwgPath, True)
    Dim acDb As Database = acDoc.Database
    Dim acEd As Editor = acDocMgr.MdiActiveDocument.Editor

    'Initialise transaction manager
    Using acTrans As Transaction = acDb.TransactionManager.StartTransaction()

        'Select all blocks in drawing and search for titleblock
        Dim acObjCol() As ObjectId
        For i As Integer = 0 To 1
            acObjCol = acEd.SelectAll(SelFilter("INSERT", i)).Value.GetObjectIds()
            For Each acObj As ObjectId In acObjCol
                Dim acBlkRef As BlockReference = acTrans.GetObject(acObj, OpenMode.ForRead)
                If acBlkRef.Name.ToUpper() Like gbl.Client(Index).titleblock Then
                    'Titleblock found, get attributes
                    Dim AcAttCol As AttributeCollection = acBlkRef.AttributeCollection
                    For Each acAtt As ObjectId In AcAttCol
                        Dim acAttRef As AttributeReference = acTrans.GetObject(acAtt, OpenMode.ForRead)
						
			    'EVALUATE ATTRIBUTES HERE

                    Next
                    bBlkFnd = True
                    Exit For
                End If
            Next

            'Titleblock attributes found
            'Do not attempt Paper Space search
            If bBlkFnd = True Then
                Exit For
            End If
        Next
    End Using

    'Close drawing
    DocumentExtension.CloseAndDiscard(acDoc)

    'Return drawing attributes
    Return DwgAtts
End Function

This seems to work fine. The function is returning a custom structure I've made that contains all the attribute values that I need. However now I'm having problems closing the documents. AutoCAD crashes after calling the function. If I remove the DocumentExtension.CloseAndDiscard(acDoc) line it is fine, except the documents obviously stay opened.

Member
Shannon.Edwards
Posts: 3
Registered: ‎06-25-2012
Message 5 of 7 (241 Views)

Re: [VB.NET] Can't find blocks in drawing

03-11-2014 04:44 PM in reply to: Shannon.Edwards

After some more debugging and investigation I have worked out the cause of the original problem. It seems that MdiActiveDocument is not updating when I load a new document.

 

Dim acDocMgr As DocumentCollection = Application.DocumentManager
Dim acDoc As Document = DocumentCollectionExtension.Open(acDocMgr, dwgPath, True)

When I load the new drawing using DocumentcollectionExtension.Open, acDogMgr.MdiActiveDocument is not updating to the newly opened document. That is why when I set the Database to acDocMgr.MdiActiveDocument.Database it wasn't finding any elements in the BlockTableRecord (it was loading the BlockTableRecord for the blank document that AutoCAD loads upon opening).

 

I'm now trying to close the document with:

 

DocumentExtension.CloseAndDiscard(acDocMgr.MdiActiveDocument)

 But obviously this isn't working because MdiActiveDocument isn't actually pointing to the open document. What is going on?

Mentor
mzakiralam
Posts: 230
Registered: ‎11-09-2012
Message 6 of 7 (235 Views)

Re: [VB.NET] Can't find blocks in drawing

03-12-2014 01:08 AM in reply to: Shannon.Edwards

Can you add below line after opening your drawing? As you did not make it active so you should not expect that it become active design automatically. Please add the below line and try once again

 

  acDocMgr.MdiActiveDocument = acDoc

 

*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 7 of 7 (224 Views)

Re: [VB.NET] Can't find blocks in drawing

03-12-2014 05:34 AM in reply to: Shannon.Edwards
Sorry, my code is tested in A2014, all is working good,
so I couldn't add any more
_____________________________________
C6309D9E0751D165D0934D0621DFF27919

You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

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 to get help installing your software.

Ask the Community