Results 1 to 6 of 6

Thread: InsertBlock

  1. #1
    Member
    Join Date
    2012-01
    Posts
    12
    Login to Give a bone
    0

    Default InsertBlock

    I'm working on porting my VBA macros to VB.Net and I'm getting hung up on one particular item. I can't seem to figure how to insert a existing drawing as a block (with attributes) into another drawing.

    Basically, what I'm trying to do is to read a text file that contains three columns. An name column, X coordinate position and Y coordinate position. My program reads the text file, places this block with attributes into my drawing at the X and Y coordinates with the ID as the attribute. Reading the file is not an issue. It's getting this block into my drawing that I'm having trouble with. I'm getting confused I guess with the transaction, blocktable record, etc...stuff that now is required in the code.

    In my VBA program the code looked something like:

    Public Sub InsertBlocks(Id, Xcord, Ycord)

    'varaible used to store attributes
    Dim varAttributes As Variant

    insertionPnt(0) = Xcord: insertionPnt(1) = Ycord: insertionPnt(2) = 0

    Set blockRefObj = ThisDrawing.ModelSpace.InsertBlock(insertionPnt,
    "xyz.DWG", Size1, Size2, Size3, 0)

    'get attributes from xyc
    varAttributes = blockRefObj.GetAttributes
    'set text label to be equal to id value
    varAttributes(0).TextString = Id

    End Sub

    I'm trying to do this same exact thing with VB.Net but I haven't quite figured it out. Does anyone have any (simplified) sample code that can do what I'm trying to do?

    Thanks,
    Rob

  2. #2
    Active Member
    Join Date
    2009-08
    Posts
    93
    Login to Give a bone
    0

    Default Re: InsertBlock

    This has a VB example
    http://www.theswamp.org/index.php?to...7562#msg427562
    Thanks again Kerry

  3. #3
    Member
    Join Date
    2012-01
    Posts
    12
    Login to Give a bone
    0

    Default Re: InsertBlock

    Thanks for the link.

    I'm tried playing around with the code on this link and I'm having problems with the line:

    1. ActiveDoc = AcadApp.DocumentManager.MdiActiveDocument
    It prevents my windows form from appearing when I run the macro for some reason. If I remove the line the windows form appears, but of course I can't draw anything in autocad...ugh.

    Rob

  4. #4
    Active Member
    Join Date
    2006-08
    Location
    Brisbane : GMT+10
    Posts
    87
    Login to Give a bone
    0

    Default Re: InsertBlock

    The thread Jeff referenced has a LOT of code in it ... which bit are you referring to.

    It would be best if you post ALL the exact code that is giving you trouble.

    I don't understand your comment about 'running a Macro' ; which macro are you talking about ?

    I only come past here every 2 or 3 weeks, you may be better served posting in a new thread at theSwamp.

  5. #5
    100 Club
    Join Date
    2002-10
    Posts
    154
    Login to Give a bone
    0

    Default Re: InsertBlock

    I did a few things to make this easier. I tried to keep this short and simple. (I will have to send this in two Posts)

    BrAs.ThisDrawing.RedefineBlocks ("TitleBlock" , "C:\DrawingName.dwg") - this uses some other features listed below but I use this for redefining Title Blocks. It does a little more than that. It redefines it from the other drawing but it also reInserts the existing blocks and resets the attributes and dynamic properties. I did this because when we redefine our title block, we may add or remove attributes. Even change some of the dynamic properties. This function alllows you to update every title block with out having to reinsert each one because you changed modified the block.

    acObject - I did not include this because it is my own class object that holds a lot of information and contains other custom class objects that gets real indepth. but in this case, it holds basic information like Filename, ObjectID, ObjectTypes, InsertionPoints, Values(attributes and dynamic), ect... So when you see it, I am just using it as one object to hold multi settings.

    BlockValue - allows you to get and set both attributes and dynamic properties including a DeepScan option for searching blocks within blocks.

    Code:
    Imports Autodesk.AutoCAD.ApplicationServices
    Imports Autodesk.AutoCAD.DatabaseServices
    Imports Autodesk.AutoCAD.EditorInput
    Imports Autodesk.AutoCAD.Geometry
    Namespace BrAs
        Public Class Utilities
            Public Const NotSet = "<<NoTseTStriNg>>"
            Public Shared Function BlockValue(ByRef acDoc As Document, ByRef acTrans As Transaction, ByRef mBR As BlockReference, _
                                          ByVal valName As String, Optional ByVal PreformDeepScan As Boolean = False, _
                                          Optional ByRef setValue As String = NotSet, Optional ByRef resultValue As String = "") As Boolean
                Dim mBTR As BlockTableRecord
                If mBR.IsDynamicBlock Then
                    mBTR = acTrans.GetObject(CType(acTrans.GetObject(mBR.DynamicBlockTableRecord, OpenMode.ForRead),  _
                                            BlockTableRecord).ObjectId, OpenMode.ForRead)
                Else
                    mBTR = acTrans.GetObject(CType(acTrans.GetObject(mBR.BlockTableRecord, OpenMode.ForRead),  _
                                            BlockTableRecord).ObjectId, OpenMode.ForRead)
                End If
    
                'Find the attribute for this value
                Dim attIDs As AttributeCollection = mBR.AttributeCollection
                If attIDs.Count > 0 Then
                    For Each aID As ObjectId In attIDs
                        Dim attRef As AttributeReference = acTrans.GetObject(aID, OpenMode.ForRead)
                        If attRef.Tag.Trim.ToUpper = valName.Trim.ToUpper Then
                            If setValue = NotSet Then
                                resultValue = attRef.TextString
                            Else
                                Using acDocLock As DocumentLock = acDoc.LockDocument
                                    attRef.UpgradeOpen()
                                    attRef.TextString = setValue
                                    resultValue = setValue
                                End Using
                                acTrans.Commit()
                            End If
                            Return True
                        End If
                    Next
                End If
    
                'Attribute was not found, now try to find the dynamic property
                If mBR.IsDynamicBlock Then
                    'If setValue = NotSet Then mBR.UpgradeOpen()
                    If setValue = NotSet Then
                        mBR = CType(acTrans.GetObject(mBR.ObjectId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite),  _
                                    Autodesk.AutoCAD.DatabaseServices.BlockReference)
                    End If
                    Dim dBrPcol As DynamicBlockReferencePropertyCollection = mBR.DynamicBlockReferencePropertyCollection
                    If Not dBrPcol Is Nothing Then
                        If dBrPcol.Count > 0 Then
                            For Each DynProp As DynamicBlockReferenceProperty In dBrPcol
                                If DynProp.PropertyName.Trim.ToUpper = valName.Trim.ToUpper Then
                                    If setValue = NotSet Then
                                        resultValue = DynProp.Value
                                    Else
                                        Using acDocLock As DocumentLock = acDoc.LockDocument
                                            SetDynamicValue(DynProp, setValue)
                                        End Using
                                        acTrans.Commit()
                                    End If
                                    Return True
                                End If
                            Next
                        End If
                    End If
                End If
    
                'attribute and dynamic property was not found, search sub entities
                If PreformDeepScan Then
                    If PreformDeepScan Then
                        For Each mSubObjID As ObjectId In mBTR
                            Dim mEnt = acTrans.GetObject(mSubObjID, OpenMode.ForRead)
                            If TypeOf mEnt Is Autodesk.AutoCAD.DatabaseServices.BlockReference Then
                                If BlockValue(acDoc, acTrans, CType(mEnt, Autodesk.AutoCAD.DatabaseServices.BlockReference), _
                                              valName, PreformDeepScan, setValue, resultValue) Then Return True
                            End If
                        Next
                    End If
                End If
                Return False
            End Function
            Public Shared Sub SetDynamicValue(ByRef mDynProp As DynamicBlockReferenceProperty, ByVal setValue As Object)
                'I am still working on this portion but it does OK so far
                Try
                    Dim mvs As String = mDynProp.Value.GetType.ToString
                    Select Case mDynProp.Value.GetType.ToString
                        Case "System.Double"
                            mDynProp.Value = CDbl(setValue)
                            Exit Sub
                        Case "System.String"
                            mDynProp.Value = CStr(setValue)
                            Exit Sub
                        Case "System.Short"
                            mDynProp.Value = CShort(setValue)
                            Exit Sub
                        Case "Autodesk.AutoCAD.Geometry.Point3d"
                            'This does not work all of the time for some reason
                            Dim pntStr As String = setValue.ToString.Trim("(", ")")
                            Dim mPoint As New Point3d(CDbl(pntStr.Split(",")(0)), CDbl(pntStr.Split(",")(1)), CDbl(pntStr.Split(",")(2)))
                            mDynProp.Value = mPoint
                            Exit Sub
                    End Select
                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                    Exit Sub
                End Try
    
                Try
                    mDynProp.Value = CDbl(setValue)
                    Exit Sub
                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                End Try
    
                Try
                    mDynProp.Value = CShort(setValue)
                    Exit Sub
                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                End Try
    
                Try
                    mDynProp.Value = setValue
                    Exit Sub
                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                End Try
            End Sub
            Public Shared Function GetAllBlockRefIDs(ByRef acDoc As Document, Optional ByVal BlockName As String = "<<Select All>>") As ObjectIdCollection
                Dim BlockList As ObjectIdCollection = GetEntities(acDoc, New SelectionFilter({New TypedValue(CInt(DxfCode.Start), "INSERT")}))
    
                If BlockList.Count = 0 Then Return BlockList
                Dim ResultCol As New ObjectIdCollection
                If BlockName = "<<Select All>>" Then BlockName = NotSet
    
                Using acTrans As Transaction = acDoc.TransactionManager.StartTransaction()
                    Try
                        For Each blkID As ObjectId In BlockList
                            Dim acBR As BlockReference = CType(acTrans.GetObject(blkID, OpenMode.ForRead), BlockReference)
                            Dim blockBTR As BlockTableRecord
    
                            If acBR.IsDynamicBlock Then
                                blockBTR = CType(acTrans.GetObject(acBR.DynamicBlockTableRecord, OpenMode.ForRead), BlockTableRecord)
                            Else
                                blockBTR = CType(acTrans.GetObject(acBR.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
                            End If
    
                            If BlockName = NotSet Then
                                ResultCol.Add(blkID)
                            Else
                                If blockBTR.Name = BlockName Then ResultCol.Add(blkID)
                            End If
                        Next
                    Catch ex As Autodesk.AutoCAD.Runtime.Exception
                    End Try
                End Using
                Return ResultCol
            End Function
    Last edited by jluker; 2012-02-06 at 02:29 PM.

  6. #6
    100 Club
    Join Date
    2002-10
    Posts
    154
    Login to Give a bone
    0

    Default Re: InsertBlock

    Code:
    Public Shared Function GetEntities(ByRef acDoc As Document, Optional ByVal Filter As SelectionFilter = Nothing, Optional ByVal SelectOnScreen As Boolean = False, _
                              Optional ByVal Prompt As String = "Select Objects: ") As ObjectIdCollection
                'Filter can be filled out with multaple filters
                '    Filter = new SelectionFilter(FilterList)
                '       This is filled with a FilterList
                '       FilterList = TypedValue() array filled with TypedValue
                '          TypedValue is a TypedValue (Value Types can be found under the DXFCode)
                '              Select Blocks = New TypedValue(CInt(DxfCode.Start), "INSERT"
                '              Select by Layer = New TypedValue(CInt(DxfCode.LayerName), "layerName")
                '    To Select all, do not add a Filter
                '
                '   'OneLine Filter example to get all blocks
                '       GetEntities(New SelectionFilter(New TypedValue(0) {New TypedValue(CInt(DxfCode.Start), "INSERT")}) )
                Dim acEd As Editor = acDoc.Editor
    
                Dim acPSR As PromptSelectionResult
                If SelectOnScreen Then
                    Dim opts As New PromptSelectionOptions()
                    opts.MessageForAdding = Prompt
                    If Filter Is Nothing Then acPSR = acEd.GetSelection(opts) Else acPSR = acEd.GetSelection(opts, Filter)
                Else
                    If Filter Is Nothing Then acPSR = acEd.SelectAll() Else acPSR = acEd.SelectAll(Filter)
                End If
    
                If acPSR.Status = PromptStatus.OK Then Return New ObjectIdCollection(acPSR.Value.GetObjectIds()) Else Return New ObjectIdCollection()
            End Function
            Public Shared Function CloneBlock(ByVal SourceBlock As acObject, Optional ByVal ReplaceMe As Boolean = False) As ObjectId
                SourceBlock.GetInformationFromDrawing()
    
                Dim acObj As New acObject(InsertBlock(SourceBlock.InsertionPoint, SourceBlock.Name, SourceBlock.Xscale, SourceBlock.Yscale, SourceBlock.Zscale, SourceBlock.Layer, , True, SourceBlock.SpaceID))
    
                If SourceBlock.HasMemoryValues Then
                    For i As Integer = 0 To SourceBlock.MemoryValueNames.Count - 1
                        acObj.acRefValue(SourceBlock.MemoryValueNames(i), True) = SourceBlock.MemoryValueSettings(i)
                    Next
                End If
                If SourceBlock.Name = "TitleBlock" Then
                    Try
                        acObj.SystemBlockVersion_acRefValue = "1.00"
                    Catch ex As Autodesk.AutoCAD.Runtime.Exception
                    End Try
                    Try
                        acObj.SystemBlockType_acRefValue = "brTitleBlock"
                    Catch ex As Autodesk.AutoCAD.Runtime.Exception
                    End Try
                End If
                If ReplaceMe Then SourceBlock.DeleteMyAcObject()
    
            End Function
        End Class
        Public Class ThisDrawing
            Public Shared Sub RedefineBlocks(ByVal BlockName As String, ByVal FromFile As String)
                Try
                    Dim BlockList As ObjectIdCollection = ThisDrawing.GetAllBlockRefIDs(BlockName)
    
                    If Not BlockList Is Nothing Then
                        If BlockList.Count > 0 Then
                            ThisDrawing.DefineBlockFromFile(BlockName, FromFile, True)
    
                            For Each blkID As ObjectId In BlockList
                                Dim mObj As New acObject
                                mObj.acObjectID = blkID
                                Utilities.CloneBlock(mObj, True)
                            Next
                        End If
                    End If
                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                End Try
            End Sub
    
            Public Shared Function GetAllBlockRefIDs(Optional ByVal BlockName As String = "<<Select All>>") As ObjectIdCollection
                Return Utilities.GetAllBlockRefIDs(Application.DocumentManager.MdiActiveDocument, BlockName)
            End Function
    
            Public Shared Function DefineBlockFromFile(ByVal BlockName As String, ByVal FromFile As String, Optional ByVal Redefine As Boolean = False) As Boolean
                If ThisDrawing.HasBlock(BlockName) And Not Redefine Then Return False
                Dim acDm As DocumentCollection = Application.DocumentManager
                Dim acEd As Editor = acDm.MdiActiveDocument.Editor
                Dim DestDoc As Document = acDm.MdiActiveDocument
                Dim DestDb As Database = DestDoc.Database
                Dim sourceDb As New Database(False, True)
                Dim ResultMsg As String = ""
                Try
                    ' Read the DWG into a side database
                    sourceDb.ReadDwgFile(FromFile, System.IO.FileShare.Read, True, "")
                    ' Create a variable to store the list of block identifiers
                    Dim blockIds As New ObjectIdCollection()
                    Using SourceTM As Autodesk.AutoCAD.DatabaseServices.TransactionManager = sourceDb.TransactionManager
                        Using SourceTM.StartTransaction
                            Dim bt As BlockTable = DirectCast(SourceTM.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, False), BlockTable)
                            ' Check each block in the block table
                            blockIds.Add(FindMyBlockID(BlockName, bt, SourceTM))
                        End Using
                    End Using
    
                    ' Copy blocks from source to destination database
                    If blockIds.Count > 0 Then
                        Dim mapping As New IdMapping()
                        Using DestDoc.LockDocument
                            sourceDb.WblockCloneObjects(blockIds, DestDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, False)
                        End Using
                    End If
                    ' ResultMsg = vbLf & "Copied block definitions from " + mBlockItem.FileName + " to the current drawing."
                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                    ResultMsg = vbLf & "Error during copy: " + ex.Message
                End Try
                sourceDb.Dispose()
                '' Set the new document current (very important)
                acDm.MdiActiveDocument = DestDoc
                acEd.WriteMessage(ResultMsg)
                Return True
            End Function
            Public Shared Function FindMyBlockID(ByVal BlockName As String, ByRef aBlockTable As BlockTable, ByVal Trans As Autodesk.AutoCAD.DatabaseServices.TransactionManager) As ObjectId
                For Each btrId As ObjectId In aBlockTable
                    Dim btr As BlockTableRecord = DirectCast(Trans.GetObject(btrId, OpenMode.ForRead, False), BlockTableRecord)
                    ' Only add named & non-layout blocks to the copy list
                    If Not btr.IsAnonymous AndAlso Not btr.IsLayout Then
                        If btr.Name = BlockName Then
                            Dim ObjID As ObjectId = btr.ObjectId
                            btr.Dispose()
                            Return ObjID
                        End If
                    End If
                    btr.Dispose()
                Next
                Return Nothing
            End Function
            Public Shared Function HasBlock(ByVal BlockName As String) As Boolean
                Dim ReturnVal As Boolean = False
                Dim acDoc As Autodesk.AutoCAD.ApplicationServices.Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
                Dim acDB As Autodesk.AutoCAD.DatabaseServices.Database = acDoc.Database
    
                Using acTrans As Autodesk.AutoCAD.DatabaseServices.Transaction = acDoc.TransactionManager.StartTransaction
                    Try
                        ' Then open the block table and check the
                        ' block definition exists
                        Dim bt As Autodesk.AutoCAD.DatabaseServices.BlockTable = _
                            DirectCast(acTrans.GetObject(acDB.BlockTableId, _
                                                         Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead), Autodesk.AutoCAD.DatabaseServices.BlockTable)
                        If bt.Has(BlockName) Then ReturnVal = True
                    Catch ex As Autodesk.AutoCAD.Runtime.Exception
    
                    End Try
                    acTrans.Commit()
                End Using
                Return ReturnVal
            End Function
        End Class
    End Namespace
    Last edited by jluker; 2012-02-06 at 02:29 PM.

Similar Threads

  1. VBA InsertBlock Problem
    By mulyadi_ibrahim in forum VBA/COM Interop
    Replies: 3
    Last Post: 2008-04-01, 05:39 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •