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

redefining blocks with VB

33 REPLIES 33
Reply
Message 1 of 34
Anonymous
1745 Views, 33 Replies

redefining blocks with VB

Hi, i need some help getting started with vb development for autocad 2007.
First I am fairly confused about objectARX, VB.net etc, but i think i understand it enough to know that I can use vb to write code that i can load with the NETLOAD command from AutoCAD and execute it providing the commands i defined. so far so good.
Problem is that I am now trying to access/retrieve the list of all blocks that are defined in a drawing and I can't figure out how.

this is how i open the file:

Dim file as autodesk,autocad.applicationservices.document
file = application.documentmanager.open("myfile.dwg",false)

now that i have that file open i need to figure out how to get the blocks, find the one i am looking for (title block) and insert a new title block with the same name as the existing one so that i can redefine it.

any help will be appreciated, since the api docs are not offering a lot of help at this point since they don't show any examples.

thank you
33 REPLIES 33
Message 21 of 34
cadMeUp
in reply to: Anonymous

Why are you calling dispose on these two objects?:
bref.Dispose()
btr.Dispose()
Message 22 of 34
Anonymous
in reply to: Anonymous

not sure as i have not written the code. i am just trying to understand it and use it (modified if needed)
i found the code on this board. but it chokes before those lines anyway
Message 23 of 34
Anonymous
in reply to: Anonymous

You have created a new block reference. Before you can use AddNewlyCreatedDBObject you have to add the block reference to the database. The link I posted shows how to do it.
Message 24 of 34
Anonymous
in reply to: Anonymous

ok, now that makes sense. i will try it and post results. thanks for babysitting me
Message 25 of 34
Anonymous
in reply to: Anonymous

hey, where can i find the INSPECTOR app that is mentioned in the video. with the code as i have it now something weird is happening and i could use the inspector to see if my suspicion is correct.
Message 26 of 34
Anonymous
in reply to: Anonymous

ok guys, i really appreciate you helping me but so far it has barely worked. if i may ask you to look at the following code that i found on this board and may help me out figure out how to do this properly.

the code works fine in a sense, it will open the drawing i indicate and it will insert the new block which i get from another drawing.

my problem is this: the open dwg already has a block called TITLE-SQL, so by inserting another block with the same name should not work without redefining the block. However the new block is simply inserted without a name even though it is set in the code as you can see....

_
Public Sub blkTest()
Dim file As Autodesk.AutoCAD.ApplicationServices.Document
file = Application.DocumentManager.Open("C:\66535D.dwg", False)
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim ed As Editor = doc.Editor
Dim tr As Transaction = doc.TransactionManager.StartTransaction
Try
Dim dwgName As String = HostApplicationServices.Current.FindFile("C:\title-sql.dwg", _
Application.DocumentManager.MdiActiveDocument.Database, FindFileHint.Default)
Dim db As Database = New Database(False, False)
db.ReadDwgFile(dwgName, IO.FileShare.Read, True, "")
Dim NewBlkId As ObjectId
NewBlkId = doc.Database.Insert(dwgName, db, False)
Dim bt As BlockTable = tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead, True)
Dim btr As BlockTableRecord = tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite, True)
Dim bref As BlockReference = New BlockReference(New Point3d(0.0, 0.0, 0.0), NewBlkId)
btr.AppendEntity(bref)
tr.AddNewlyCreatedDBObject(bref, True)
tr.Commit()
Catch ex As Exception
ed.WriteMessage(ex.ToString)
End Try
End Sub
Message 27 of 34
Anonymous
in reply to: Anonymous

The method I use (may not be the best way) is to:

get existing block references
delete existing block definition
create new block definition
assign new block definition to existing block references
insert new block reference


Heres the code:

Public Sub Insert()

Dim strBlock As String = "Your Block/DWG Name"
Dim strBlockPath As String = "Your Path to Block/DWG"

Dim objDB As Database = HostApplicationServices.WorkingDatabase
Dim objTrans As Transaction = objDB.TransactionManager.StartTransaction

Dim objBlockDefId As ObjectId = GetTableRecordId(objDB.BlockTableId, strBlock) 'Function Defined Below
Dim objBlockDef As BlockTableRecord
Dim objBlockRefs2Update As New ObjectIdCollection

'If BlockDef Exists Get All Block References To Be Updated And Then Delete BlockDef
If objBlockDefId <> ObjectId.Null Then
objBlockDef = CType(objTrans.GetObject(objBlockDefId, DatabaseServices.OpenMode.ForWrite, False), BlockTableRecord)
objBlockRefs2Update = objBlockDef.GetBlockReferenceIds(True, False)
objBlockDef.Erase()
End If

'Create New BlockDef From DWG
Dim objBlockDefDB As Database = New Database
objBlockDefDB.ReadDwgFile(strBlockPath, IO.FileShare.ReadWrite, False, "")
objBlockDefId = objDB.Insert(strBlock, objBlockDefDB, True)
objBlockDefDB.Dispose()

'Update Block References With New BlockDef
For Each objBlockRef2UpdateId As ObjectId In objBlockRefs2Update
Dim objBlockRef2Update As BlockReference = CType(objTrans.GetObject(objBlockRef2UpdateId, DatabaseServices.OpenMode.ForWrite, False), BlockReference)
objBlockRef2Update.BlockTableRecord = objBlockDefId
Next objBlockRef2UpdateId

objTrans.Commit()
objTrans.Dispose()

'Insert Block Reference At 0,0,0
objTrans = objDB.TransactionManager.StartTransaction
Dim objBlockRef As BlockReference = New BlockReference(New Point3d(0, 0, 0), objBlockDefId)
Dim objBT As BlockTable = CType(objTrans.GetObject(objDB.BlockTableId, DatabaseServices.OpenMode.ForWrite, False), BlockTable)
Dim objBTR As BlockTableRecord = CType(objTrans.GetObject(objBT(BlockTableRecord.ModelSpace), DatabaseServices.OpenMode.ForWrite, False), BlockTableRecord)
objBTR.AppendEntity(objBlockRef)
objTrans.AddNewlyCreatedDBObject(objBlockRef, True)
objTrans.Commit()
objTrans.Dispose()

End Sub

' This is a workaround for getting a non-erased SymbolTableRecord, when there are also erased ones with the same name
Public Function GetTableRecordId(ByVal objTableId As ObjectId, ByVal strName As String) As ObjectId
GetTableRecordId = ObjectId.Null
Dim objDB As Database = objTableId.Database
Dim objTrans As Transaction = objDB.TransactionManager.StartTransaction
Dim objTable As SymbolTable = CType(objTrans.GetObject(objTableId, DatabaseServices.OpenMode.ForRead, False), SymbolTable)
If objTable.Has(strName) Then
Dim objID As ObjectId
objID = objTable(strName)
If objID.IsErased Then
For Each objID In objTable
If Not objID.IsErased Then
Dim objSTR As SymbolTableRecord = CType(objTrans.GetObject(objID, DatabaseServices.OpenMode.ForRead, False), SymbolTableRecord)
If String.Compare(objSTR.Name, strName, True) = 0 Then
GetTableRecordId = objID
Exit For
End If
End If
Next
Else
GetTableRecordId = objID
End If
End If
objTrans.Commit()
objTrans.Dispose()
End Function
Message 28 of 34
Anonymous
in reply to: Anonymous

Nathan, this is exactly what I needed. Thank you so much.
There is only one issue left and I need a little more help. The block that I am looking for is called "TITLE-SQL" and it is the title block of the dwg.
your code does a wonderful job of replacing the existing one with the new one, however a warning comes up after your code executes that now I have more than one "*-SQL" block.
which is true because the existing one has been replaced, but there is also a new one inserted at 0,0,0.
When I type rename in AutoCAD and look at the blocks, i only see one TITLE-SQL listed though.

any ideas? since the current one is replaced. i really don't need to insert one at 0.0.0
Message 29 of 34
Anonymous
in reply to: Anonymous

never mind. I am blind as a bat. been dealing with this too long and cant even see the obvious any more

I just saw where you insert the block ref.
commented it out and all good
I truly appreciate all your help and larry's as well
Message 30 of 34
Anonymous
in reply to: Anonymous

hey nathan, is there any way to do this without having to open the dwg file(s)?

reason being is that I am having problems opening up dwg recursively. The code will open the first file and process it and then open the second one and just seemingly freeze. i can still interact with AutoCAD manually, but for some reason the code stops executing.

If I use the same code to recursively JUST list the file names, it works without any problems..

Thanks

_
Public Sub recreplace()
Recursion("C:\temp")
MsgBox("DONE")
End Sub

Sub Recursion(ByVal strFolder As String)
Try
Dim dirs As String() = Directory.GetDirectories(strFolder)
'Console.WriteLine("The number of directories is {0}.", dirs.Length)
Dim dir As String
For Each dir In dirs
'Debug.WriteLine(dir)
Dim f As String() = Directory.GetFiles(dir)
WriteDataToFile(f)
Recursion(dir)
Next
Dim filesCur As String() = Directory.GetFiles(strFolder)
WriteDataToFile(filesCur)

Catch ex As Exception
Console.WriteLine("The process failed: {0}", ex.ToString)
End Try
End Sub


Function WriteDataToFile(ByVal data() As String) As Boolean
Try
Dim en As System.Collections.IEnumerator
en = data.GetEnumerator
While en.MoveNext
If UCase(en.Current.Substring(en.Current.Length - 3)) = "DWG" Then
Debug.WriteLine(CStr(en.Current))
'Dim file As Autodesk.AutoCAD.ApplicationServices.Document
'file = Application.DocumentManager.Open(CStr(en.Current), False)
'file.LockDocument()
'Insert()
'file.CloseAndSave(CStr(en.Current))
'Debug.WriteLine(CStr(en.Current) & "," & Replace(UCase(en.Current.Substring(en.Current.lastindexof("\") + 1, 5)), ".DWG", ""))
End If
End While
Return True
Catch ex As Exception
MsgBox(ex.Message)
Return False
End Try

End Function
Message 31 of 34
Anonymous
in reply to: Anonymous

You need to run the command in application context.

Public Sub YourSubName()

After you have opened the document you need to create a DocumentLock using the LockDocument method of the document. Before you close the document you must call the Dispose method of the DocumentLock.
Message 32 of 34
Anonymous
in reply to: Anonymous

My post isn't displaying correctly. Read attached text file.
Message 33 of 34
Anonymous
in reply to: Anonymous

file = Application.DocumentManager.Open(CStr(en.Current), False)
file.LockDocument()
Insert()
file.CloseAndSave(CStr(en.Current))
file.Dispose()

i already have this, but it makes no difference

what do you mean by "application context"? is that achieved by CommandFlag.Session
Message 34 of 34
Anonymous
in reply to: Anonymous

Nathan,

I have finalized my code based on your suggestions, and it does work but every once in a while AutoCAD throws a fatal error. it is never at the same file and it appears quite random.

do you have any suggestions?

It will run for a while and do what it is supposed to do, but then it bombs out.

Thanks

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

Post to forums  

Forma Design Contest


Autodesk Design & Make Report