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

problems with updating block attributes in each ps layout

7 REPLIES 7
Reply
Message 1 of 8
btmcad
453 Views, 7 Replies

problems with updating block attributes in each ps layout

I'm working on a program that cycles through each paperspace layout in a drawing and updates the sheet number and total quantity of sheets in the titleblock attributes. I've updated the block attributes in paperspace before, and it worked fine. Now that I'm trying to cycle through each layout, I cannot get it to work. I have attached my code. I beleive it starts to cycle through the layouts, but it fails when I try to grab the attribute collection.  I would greatly appreciate any suggestions.

 

 

 Public Sub UpdateSheetNumbers()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor
            Dim layoutCount As Integer = LayoutManager.Current.LayoutCount - 1

            Dim trans As Transaction = db.TransactionManager.StartTransaction()
            Try
                Dim myBT As BlockTable = db.BlockTableId.GetObject(OpenMode.ForRead)
                For Each btrid As ObjectId In myBT
                    Dim myBTR As BlockTableRecord = btrid.GetObject(OpenMode.ForRead)
                    If myBTR.IsLayout Then
                        Dim layOut As Layout = myBTR.LayoutId.GetObject(OpenMode.ForRead)

                        If layOut.LayoutName = "Model" Then
                            Continue For  ''skip remaining code, go to next iteration
                        End If

                        For Each id As ObjectId In myBTR

                            Dim acBref As BlockReference = id.GetObject(OpenMode.ForWrite)
                            If acBref.AttributeCollection.Count <> 0 Then
                                MsgBox(layOut.LayoutName)
                                Dim myAttColl As AttributeCollection = acBref.AttributeCollection


                                For Each myAttRefId2 As ObjectId In myAttColl
                                    Dim myAttRef As AttributeReference = myAttRefId2.GetObject(OpenMode.ForWrite)

                                    If myAttRef.Tag = "SHT" Then myAttRef.TextString = layOut.TabOrder.ToString()
                                    If myAttRef.Tag = "OF" Then myAttRef.TextString = layoutCount.ToString()
                                Next
                            End If

                        Next

                    End If
                Next
            Catch
                ed.WriteMessage("Error!")
            Finally
                trans.Commit()
            End Try
        End Sub

 

 

 

 

7 REPLIES 7
Message 2 of 8
norman.yuan
in reply to: btmcad

Well, it fails because your code is build on wrong concept:

 

For Each id As ObjectId In myBTR
    Dim acBref As BlockReference = id.GetObject(OpenMode.ForWrite)                            

    If acBref.AttributeCollection.Count <> 0 Then

...

 

myBTR is an BlockTableRecord (block definotion). Why do you loop through it to find a BlockReference of itself? Your next line of code may well return you a null (Nothing) object, because entities in a Block definition is very likely not a BlockReference, thus the error when you try to get to AttributeCollection in next line of code.

 

You should get all BlockReference of the myBRT by:

 

Dim brefIDs As ObjectIdCollection=myBRT.GetBlockReferenceIds()

 

Then you can open each BlockReference to see which layout it is on, then you can update its attribute accordingly.

 

As matter of fact, you do not even bother with BlockTableRecord at all, if you know the block name:

 

1. Use SelectionSet with filter (Block Name) to select all BlockReferences of the targeting title block.

2. For each BlockReference, check which layer it is on

3. Update attribute accordingly

 

Norman Yuan

Drive CAD With Code

EESignature

Message 3 of 8
Hallex
in reply to: btmcad

Here is my 2

       Public Sub UpdateSheetNumbers()
            Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor
            Try
                Using tr As Transaction = db.TransactionManager.StartTransaction
                    ' Open dictionary for reading 
                    Dim layoutDict As DBDictionary = DirectCast(tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead), DBDictionary)
                    ' Loop through dictionary entries
                    For Each entry As DictionaryEntry In layoutDict
                        Dim ltr As Layout = DirectCast(tr.GetObject(DirectCast(entry.Value, ObjectId), OpenMode.ForRead), Layout)

                        If ltr.LayoutName = "Model" Then
                            Continue For  ''skip remaining code, go to next iteration
                        End If

                        If Not ltr.IsWriteEnabled Then ltr.UpgradeOpen()

                        ed.WriteMessage(vbLf & "{0}" & vbTab & "{1}", ltr.TabOrder, ltr.LayoutName)
                        Dim btr As BlockTableRecord = DirectCast(tr.GetObject(ltr.BlockTableRecordId, OpenMode.ForRead), BlockTableRecord)

                        For Each id As ObjectId In btr
                            Dim ent As Entity = DirectCast(tr.GetObject(id, OpenMode.ForWrite), Entity)
                            Dim acBref As BlockReference = TryCast(ent, BlockReference)
                            If acBref IsNot Nothing Then

                                Dim titlebtr As BlockTableRecord = DirectCast(tr.GetObject(acBref.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
                                If titlebtr.Name = "TITLEBLOCK" Then

                                    If acBref.AttributeCollection.Count <> 0 Then

                                        Dim myAttColl As AttributeCollection = acBref.AttributeCollection

                                        For Each myAttRefId2 As ObjectId In myAttColl

                                            Dim myAttRef As AttributeReference = DirectCast(tr.GetObject(myAttRefId2, OpenMode.ForWrite), AttributeReference)

                                            Select Case myAttRef.Tag
                                                Case "SHT" : myAttRef.TextString = ltr.TabOrder.ToString()
                                                Case "OF" : myAttRef.TextString = ltr.LayoutName
                                            End Select

                                        Next
                                    End If
                                End If
                            End If
                        Next

                    Next
                    tr.Commit()
                End Using
                ed.Regen()
            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(ex.ToString & vbCr & ex.Message)
            End Try

        End Sub

 

~'J'~

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 4 of 8
btmcad
in reply to: Hallex

Thanks for the input.

 

Hallex,

I tried using your code, but I can't get it to work. It appears to fail at:

Dim ent As Entity = DirectCast(tr.GetObject(id, OpenMode.ForWrite), Entity)

 

also it fails at:

If Not ltr.IsWriteEnabled Then ltr.UpgradeOpen()

 

I'm curious why you are casting the objects in the block table record to an entity, then retrieveing the block reference from that.

 

I modified the code using getblockreferenceids, then retrieved the blockreference, but that failed also.

 

Any suggestions would be greatly appreciated.

 

thanks

btm

 

Message 5 of 8
Hallex
in reply to: btmcad

I tested code on A2009, perhaps on your Acad release it

could not work

Just a guess, try instead:

Dim ent As DBObject = DirectCast(tr.GetObject(id, OpenMode.ForWrite, False), DBObject)

 

But, you didn't answer me on my prior response here, I don't like this manner:

 

http://forums.autodesk.com/t5/NET/Creating-a-new-layout-from-a-template/td-p/3520808

 

 

~'J'~

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 6 of 8
btmcad
in reply to: Hallex

Thanks again for the fast feedback.

 

I tried changing Enitity to dbobject, but it still throws an exception at that line.

I'm using 2013, but it should still work. I'm going to keep experimenting with that area of the program to see if I can come up with something that works.

I'll get back to you on the other thread dealing with inserting new layouts. I'm trying to get this attribute issue fixed first.

 

Thanks

btm

Message 7 of 8
btmcad
in reply to: btmcad

Well, I've been playing with this code for hours, but can't seem to get it to work with 2013.

My latest code is posted below.

It fails at:

 

Dim AttRef AsAttributeReference = AttRefID.GetObject(OpenMode.ForWrite)

 

I also commented where it fails in the code below. I'm puzzled at this point. I've edited block attributes several times with VB.net and never had an issue. I'm probably overlooking something simple. If someone can take a look and make any suggestions, I would greatly appreciate it.

 

Thanks

btm

 

 

 

 

Public Sub MAIN()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor
            Dim layoutCount As Integer = LayoutManager.Current.LayoutCount - 1

            Dim trans As Transaction = db.TransactionManager.StartTransaction()
            Try
                Dim myBT As BlockTable = db.BlockTableId.GetObject(OpenMode.ForRead)
                For Each btrid As ObjectId In myBT
                    Dim myBTR As BlockTableRecord = btrid.GetObject(OpenMode.ForRead)
                    If myBTR.IsLayout Then
                        Dim layOut As Layout = myBTR.LayoutId.GetObject(OpenMode.ForRead)
                        If layOut.LayoutName = "Model" Then
                            Continue For
                        End If

                        For Each id As ObjectId In myBTR
                            Dim obj As DBObject = id.GetObject(OpenMode.ForRead)
                            If TypeOf obj Is BlockReference Then
                                Dim bref As BlockReference = DirectCast(obj, BlockReference)
                                If bref.AttributeCollection.Count <> 0 Then
                                    Dim AttColl As AttributeCollection = bref.AttributeCollection
                                    For Each AttRefID As ObjectId In AttColl
                                        Dim AttRef As AttributeReference = AttRefID.GetObject(OpenMode.ForWrite) ''fails here
                                        If AttRef.Tag = "OF" Then AttRef.TextString = layoutCount.ToString()
                                        If AttRef.Tag = "SHT" Then AttRef.TextString = layOut.TabOrder.ToString()
                                    Next
                                End If
                            End If
                        Next
                    End If
                Next



            Catch
                ed.WriteMessage("Error!")
            Finally
                trans.Commit()
            End Try
        End Sub

 

Message 8 of 8
btmcad
in reply to: btmcad

I finally found my problem. I forgot to use lockdocument.

 

After adding that, everything worked fine in the code I copied into my last post.

 

Thanks to those that offered some suggestions.

 

btm

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