.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

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

6 REPLIES 6
Reply
Message 1 of 7
subscriptions
1665 Views, 6 Replies

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

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?

Tags (2)
6 REPLIES 6
Message 2 of 7
mzakiralam
in reply to: subscriptions

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

Message 3 of 7
Hallex
in reply to: subscriptions

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

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 4 of 7

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.

Message 5 of 7

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?

Message 6 of 7
mzakiralam
in reply to: subscriptions

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

 

Message 7 of 7
Hallex
in reply to: subscriptions

Sorry, my code is tested in A2014, all is working good,
so I couldn't add any more
_____________________________________
C6309D9E0751D165D0934D0621DFF27919

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost