Where's my problem with the importing block from the external DWG file,I've already see the blog from
http://through-the-interface.typepad.com/through_the_interface/2006/08/import_blocks_f.html,and change the part of the code,Now I want click one button so that the program can insert the one of blocks in external DWG file. Where's my problem with the code? and how can i fix it ?and the filepath and blockname has been confirmed .I use the sidedatabase.and where's the problem?
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
Dim destDB As Database = acDoc.Database
Dim acEditor As Editor = acDoc.Editor
Dim pPtRes As PromptPointResult
Dim pPtOpts As PromptPointOptions = New PromptPointOptions("")
pPtOpts.Message = vbLf & "insert the point:"
pPtRes = acEditor.GetPoint(pPtOpts)
Dim InsertPt As Point3d = pPtRes.Value
If pPtRes.Status = PromptStatus.Cancel Then
Exit Sub
End If
Dim FilePath As String = "D:\2RD\PMDS\PMDS\Resources\PFD.dwg"
Dim FileName As String = " PFD.dwg"
Dim BlockName As String = "0920101"
Dim sourceDb As New Database(True, True)
sourceDb.ReadDwgFile(FilePath, System.IO.FileShare.Read, True, "")
Dim blockId As New ObjectIdCollection()
Using (acDoc.LockDocument)
Dim sourcetm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = sourceDb.TransactionManager
Dim desttm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = destDB.TransactionManager
Dim sourcemyT As Transaction = sourcetm.StartTransaction()
Dim sourcebt As BlockTable = DirectCast(sourcetm.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, False), BlockTable)
For Each btrId As ObjectId In sourcebt
Dim sourcebtc As BlockTableRecord = DirectCast(sourcetm.GetObject((sourcebt(BlockTableRecord.ModelSpace)), OpenMode.ForRead, False), BlockTableRecord)
If sourcebtc.Name = BlockName Then
blockId.Add(btrId)
Dim mapping As New IdMapping()
sourceDb.WblockCloneObjects(blockId, destDB.BlockTableId, mapping, DuplicateRecordCloning.Replace, False)
Using destmyT As Transaction = desttm.StartTransaction()
Dim destbt As BlockTable = DirectCast(desttm.GetObject(destDB.BlockTableId, OpenMode.ForWrite, True), BlockTable)
Dim destbtc As BlockTableRecord = DirectCast(desttm.GetObject((destbt(BlockTableRecord.ModelSpace)), OpenMode.ForRead, False), BlockTableRecord)
Dim Block As BlockReference = New BlockReference(InsertPt, destbt(BlockName))
Block.ScaleFactors = New Scale3d(1, 1, 1)
Block.Rotation = 0
Dim ModelSpace As BlockTableRecord = desttm.GetObject(destDB.CurrentSpaceId, OpenMode.ForWrite)
ModelSpace.AppendEntity(Block)
destmyT.AddNewlyCreatedDBObject(Block, True)
destmyT.Commit()
End Using
ElseIf Not sourcebtc.IsAnonymous AndAlso Not sourcebtc.IsLayout Then
End If
sourcebtc.Dispose()
Next
Me.Close()
End Using
End Sub
Solved! Go to Solution.
Solved by C_Witt. Go to Solution.
Solved by hgasty1001. Go to Solution.
Hi,
Why the documentlock?, try to separate distinct functionalities in distinct routines or subs: One for the import process, and one for the insert process, if the insert involve a modeless form or a tool palette you should lock the document (or send string to execute in order to Autocad take control of the locking procedure), but there is no need to lock if you are not using modeless or involve more than one document (a document it's not the same as a database).
I would program this in the following work flow:
1.- Import the blocks
Just declare a sub, or better, a function that returns the names of the imported blocks, with the Kean's code (translated properly to VB .NET)
2.-Insert the block
Declare a sub that can insert a block to the current document with some arguments like block name, layer, rotation, etc.
3.- Do your process
Either insert or import or both, now you have two reusable subs.
Gaston Nunez
I didn't look at your code.. but here is what I use for importing a block from another drawing (i don't remember where i got it).
SourceFileName - Obvious (full file path)
TargetBlock - The arraylist has the "name" as the first value, the other values are for other programs. You can change this to a string easy enough.
Public Sub GSS_ImportBlock2Database(ByVal sourceFileName As String, ByVal TargetBlock As ArrayList) Dim dm As DocumentCollection = ApplicationServices.Application.DocumentManager Dim ed As Editor = dm.MdiActiveDocument.Editor Dim destDb As Database = dm.MdiActiveDocument.Database Dim sourceDb As New Database(False, True) Try sourceDb.ReadDwgFile(sourceFileName, System.IO.FileShare.Read, True, "") Dim blockIds As New ObjectIdCollection() Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = sourceDb.TransactionManager Using myT As Transaction = tm.StartTransaction() Dim bt As BlockTable = DirectCast(tm.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, False), BlockTable) For Each btrId As ObjectId In bt Dim btr As BlockTableRecord = DirectCast(tm.GetObject(bt(TargetBlock(0)), OpenMode.ForRead), BlockTableRecord) blockIds.Add(btr.ObjectId) btr.Dispose() Next End Using Dim mapping As New IdMapping() sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Ignore, False) Catch End Try sourceDb.Dispose() End Sub
Then you can insert the block like any other.
from your OP, you want "importing block from the external DWG file". That is what the above code does.. So if that is not what you want, please clarify what you do want.
And you are correct, it was probably from Kean's site.
If you are really need an all-in-one solution.. for importing and inserting..
Public Sub ImportInsert() Dim sourceFileName As String = "your path here" Dim TargetBlock As String = "your name here" Dim dm As DocumentCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager Dim ed As Editor = dm.MdiActiveDocument.Editor Dim destDb As Database = dm.MdiActiveDocument.Database Dim sourceDb As New Database(False, True) Try sourceDb.ReadDwgFile(sourceFileName, System.IO.FileShare.Read, True, "") Dim blockIds As New ObjectIdCollection() Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = sourceDb.TransactionManager Using myT As Transaction = tm.StartTransaction() Dim bt As BlockTable = DirectCast(tm.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, False), BlockTable) Dim btr As BlockTableRecord = DirectCast(tm.GetObject(bt(TargetBlock), OpenMode.ForRead), BlockTableRecord) blockIds.Add(btr.ObjectId) btr.Dispose() End Using Dim mapping As New IdMapping() sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Ignore, False) Dim myDwg As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument Using myTrans As Autodesk.AutoCAD.DatabaseServices.Transaction = myDwg.TransactionManager.StartTransaction 'Open the database for Write Dim myBT As BlockTable = myDwg.Database.BlockTableId.GetObject(OpenMode.ForRead) Dim myBTR As BlockTableRecord myBTR = myBT(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForWrite) 'Insert the Block Dim pPtRes As PromptPointResult Dim pPtOpts As PromptPointOptions = New PromptPointOptions("") pPtOpts.Message = vbLf & "insert the point:" pPtRes = ed.GetPoint(pPtOpts) Dim InsertPt As Point3d = pPtRes.Value If pPtRes.Status = PromptStatus.Cancel Then Exit Sub End If Dim myBlockDef As BlockTableRecord = myBT(TargetBlock).GetObject(OpenMode.ForRead) Dim myBlockRef As New DatabaseServices.BlockReference(pPtRes.Value, myBT(TargetBlock)) myBlockRef.ScaleFactors = New Scale3d(0) myBTR.AppendEntity(myBlockRef) myTrans.AddNewlyCreatedDBObject(myBlockRef, True) Dim myAttColl As DatabaseServices.AttributeCollection Dim myEnt As DatabaseServices.Entity Dim myBTREnum As BlockTableRecordEnumerator myAttColl = myBlockRef.AttributeCollection myBTREnum = myBlockDef.GetEnumerator While myBTREnum.MoveNext myEnt = myBTREnum.Current.GetObject(OpenMode.ForWrite) If TypeOf myEnt Is DatabaseServices.AttributeDefinition Then Dim myAttDef As DatabaseServices.AttributeDefinition = myEnt Dim myAttRef As New DatabaseServices.AttributeReference myAttRef.SetAttributeFromBlock(myAttDef, myBlockRef.BlockTransform) myAttColl.AppendAttribute(myAttRef) myTrans.AddNewlyCreatedDBObject(myAttRef, True) End If End While myTrans.Commit() End Using Catch End Try sourceDb.Dispose() End Sub