Insert block from block container file

Insert block from block container file

Rob.O
Collaborator Collaborator
3,869 Views
4 Replies
Message 1 of 5

Insert block from block container file

Rob.O
Collaborator
Collaborator

Hi All!

I know this question has been asked a hundred times and I have read all of the treads on the subject, but I cannot seem to find any code that actualy works as intended (or at least as I intend) 🙂

 

I am trying to pull a block "BlockA" from a seperate drawing file ("BlockFile") to insert into my current drawing file. The "BlockFile" drawing contains multiple other blocks; i.e. BlockA, BlockB, BlockC, etc...

 

I have pieced togeter the code below based on many threads covering this topic.  The code is working with three exceptions:

 

1) When I use the "BlockFile.dwg" as the blockFile variable and try to pull BlockA into my current file, I get an eSelfReference error, even though the drawing I am trying to insert BlockA into is completely empty.

 

2) If I change the blockName variable to say... "BlockAb" then It pulls in the entire contents of the external drawing file (BlockFile), adds a new blockinsertion called "BlockAb" that contains the entire contents of the "BlockFile.dwg" and maintains the original "BlockA".

 

3) If I create a seperate drawing that only contains "BlockA" and change the name of the blockFile variable in the code to point to "BlockA" rather than "BlockFile", then "BlockA" is inserted as expected.  This works great, but is not desired as I don't want to have thousands of individual files on the server for each of my blocks.

 

Am I doing something wrong???

 

 

Dim blockFile As String = "C:\BlockFile.dwg"
        Dim blockName As String = "BlockA"
        Dim db As Database = HostApplicationServices.WorkingDatabase
        Dim extDB As New Database(False, True)
        extDB.ReadDwgFile(blockFile, IO.FileShare.Read, True, "")
        Try
            Dim id As ObjectId = db.Insert(blockName, extDB, True)
        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            MsgBox(ex.Message & vbCr & ex.StackTrace)
        Finally
            extDB.CloseInput(True)
            extDB.Dispose()
        End Try

 TIA!

 

Accepted solutions (1)
3,870 Views
4 Replies
Replies (4)
Message 2 of 5

chiefbraincloud
Collaborator
Collaborator
Accepted solution

None of the overloads of Database.Insert will do what you want.  You'll need to use the WBlockCloneObjects approach demonstrated here:

 

http://through-the-interface.typepad.com/through_the_interface/2006/08/import_blocks_f.html

 

That will get the Block Definition (BlockTableRecord) into the current drawing, then you create a BlockReference after that.

Dave O.                                                                  Sig-Logos32.png
Message 3 of 5

Anonymous
Not applicable

I do use Insert, but it requires you to first do a WBlock out of the source drawing to a new, temporary database.

 

In pre-retrospect, the fact that I use GetAt here probably adds confusion...sorry.

 

 

Module SymbolTableExtensions
  <DllImport("acdb18.dll", CallingConvention:=CallingConvention.ThisCall, CharSet:=CharSet.Unicode, _
    EntryPoint:="?getAt@AcDbSymbolTable@@QBE?AW4ErrorStatus@Acad@@PB_WAAVAcDbObjectId@@_N@Z")>
  Private Function getAtx86(ByVal symbolTable As IntPtr, ByVal name As String,
    ByRef id As ObjectId, ByVal getErased As Boolean) As ErrorStatus
  End Function

  <DllImport("acdb18.dll", CallingConvention:=CallingConvention.ThisCall, CharSet:=CharSet.Unicode, _
    EntryPoint:="?getAt@AcDbSymbolTable@@QEBA?AW4ErrorStatus@Acad@@PEB_WAEAVAcDbObjectId@@_N@Z")>
  Private Function getAtx64(ByVal symbolTable As IntPtr, ByVal name As String,
    ByRef id As ObjectId, ByVal getErased As Boolean) As ErrorStatus
  End Function

  <Extension()>
  Public Function GetAt(ByVal st As SymbolTable, ByVal name As String, ByRef id As ObjectId) As Boolean
    If (IntPtr.Size = 8) Then
        Return (getAtx64(st.UnmanagedObject, name, id, False) = ErrorStatus.OK)
    Else
        Return (getAtx86(st.UnmanagedObject, name, id, False) = ErrorStatus.OK)
    End If
  End Function

  Public Function GetAt(ByVal stId As ObjectId, ByVal name As String, ByRef id As ObjectId) As Boolean
    If (Not stId.ObjectClass.IsDerivedFrom(RXClass.GetClass(GetType(SymbolTable)))) Then
        id = ObjectId.Null
        Return False
    End If

    Dim st As SymbolTable = stId.Open(OpenMode.ForRead)
    Dim has As Boolean = st.GetAt(name, id)
    st.Close()
    Return has
  End Function
End Module

Public Class ImportBlocks

  Public Function ImportBlock(ByVal srcFile As String, ByVal blockName As   String) As ObjectId
    Dim newBtrId As ObjectId = ObjectId.Null
    Dim destDb As Database = HostApplicationServices.WorkingDatabase
    Dim isAnnotative As Boolean = False

    Dim redefined As Boolean = False
    If (GetAt(destDb.BlockTableId, blockName, newBtrId)) Then

        '' Uncomment the Return if you'd like to reuse an existing 
        '' definition of blockName in the destination database
        'Return newBtrId
        redefined = True
    End If

    Using srcDb As New Database(False, True)
        srcDb.ReadDwgFile(srcFile, FileShare.ReadWrite, True, Nothing)

        Dim srcBtrId As ObjectId = ObjectId.Null
        If (GetAt(srcDb.BlockTableId, blockName, srcBtrId)) Then
            Using tmpDb As Database = srcDb.Wblock(srcBtrId)
                isAnnotative = tmpDb.AnnotativeDwg
                newBtrId = destDb.Insert(blockName, tmpDb, False)
            End Using
        End If
    End Using

    If (isAnnotative Or redefined) Then
        Using t As Transaction = destDb.TransactionManager.StartTransaction
            Dim newBtr As BlockTableRecord = t.GetObject(newBtrId, OpenMode.ForWrite)
            If (isAnnotative) Then
                newBtr.Annotative = AnnotativeStates.True
            End If
            '' you can comment this out if you're reusing an existing def
            If (redefined) Then
                newBtr.UpdateAnonymousBlocks()
            End If
            t.Commit()
        End Using
    End If

    Return newBtrId
  End Function
End Class

 

 

0 Likes
Message 4 of 5

Rob.O
Collaborator
Collaborator

Thanks Chief!

 

That is exactly what I was looking for!  Kean has some great solutions, but there is so much stuff on his blog, it's sometimes hard to find exactly what you are looking for!

0 Likes
Message 5 of 5

Rob.O
Collaborator
Collaborator

Thanks Dan!

 

A lot of what you have is over my head, but I can definately use the annotative portion of your code!

0 Likes