Not Skipping Attribute

Not Skipping Attribute

Anonymous
Not applicable
2,504 Views
30 Replies
Message 1 of 31

Not Skipping Attribute

Anonymous
Not applicable

I have the below code as a means of transferring attribute values from one place to another.  Within it I'm trying to make it skip a specific attribute with a tag "INITIALS".  The message box within the code is there to test the If/Else/EndIf.  It works.  The message only pops up when it hits that attribute.  Yet the result is the attribute with the tag "INITIALS" is still added to the list.  Any ideas as to why it works but doesn't?

 

            Using AcTrans As Transaction = AcDb.TransactionManager.StartTransaction()
                Dim bt As BlockTable = AcTrans.GetObject(AcDb.BlockTableId, OpenMode.ForRead, False, True)
                For Each id As ObjectId In bt
                    Dim btr As BlockTableRecord = DirectCast(AcTrans.GetObject(id, OpenMode.ForRead), BlockTableRecord)
                    If btr.Name.ToUpper = BlkName.ToUpper Then
                        For Each ObjId As ObjectId In btr.GetBlockReferenceIds(False, False)
                            Dim br As BlockReference = AcTrans.GetObject(ObjId, OpenMode.ForRead)
                            If br.Name = BlkName Then
                                Dim z As Integer = 0
                                For Each obj1 As ObjectId In btr
                                    obj = AcTrans.GetObject(obj1, OpenMode.ForRead)
                                    If TypeOf obj Is AttributeDefinition Then
                                        Dim AttDef As AttributeDefinition = obj
                                        Dim AttRef As AttributeReference = CType(AcTrans.GetObject(br.AttributeCollection(z), OpenMode.ForRead), AttributeReference)
                                        If AttDef.Tag = "INITIALS" Then
                                            MsgBox("Skipping INITIALS")
                                        ElseIf AttDef.Tag = "INITIALS" = False Then
                                            taglist.Add(AttDef.Tag)
                                            txtlist.Add(AttRef.TextString)
                                            z = z + 1
                                        End If
                                    End If
                                Next
                            End If
                        Next
                    End If
                Next
                AcTrans.Commit()
            End Using
0 Likes
Accepted solutions (1)
2,505 Views
30 Replies
Replies (30)
Message 2 of 31

jabowabo
Mentor
Mentor

I'm not very familiar with VB.net but two equal signs in your condition looks wonky. Try changing:

ElseIf AttDef.Tag = "INITIALS" = False Then

to this:

ElseIf AttDef.Tag <> "INITIALS" Then

https://msdn.microsoft.com/en-us/library/cey92b0t.aspx?f=255&MSPPError=-2147217396

0 Likes
Message 3 of 31

fieldguy
Advisor
Advisor

I think what you want is this (not sure about VB syntax):

If AttDef.Tag = "INITIALS" Then
  MsgBox("Skipping INITIALS")
Else          <--------------  means AttDef.Tag is not = "INITIALS" - no need for "ElseIf"
taglist.Add(AttDef.Tag) txtlist.Add(AttRef.TextString) z = z + 1 End If

 

0 Likes
Message 4 of 31

_gile
Consultant
Consultant

Hi,

 

If: skip a specific attribute with a tag "INITIALS" means process all attributes which tag is not "INITIALS", instead of this ugly and verbose statement:

 

 

If AttDef.Tag = "INITIALS" Then
    MsgBox("Skipping INITIALS")
ElseIf AttDef.Tag = "INITIALS" = False Then
    taglist.Add(AttDef.Tag)
    txtlist.Add(AttRef.TextString)
    z = z + 1
End If

 

simply do:

 

 

 

If AttDef.Tag <> "INITIALS" Then
    taglist.Add(AttDef.Tag)
    txtlist.Add(AttRef.TextString)
    z += 1
End If

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 31

Anonymous
Not applicable

No go on all provided suggestions.  The attdef.tag of INITIALS is still brought forward.  That's what I don't understand because using the msgbox to test which IF is being run it runs as correct but it still grabs the INITIALS attribute.

0 Likes
Message 6 of 31

ActivistInvestor
Mentor
Mentor

Hi Ron.

 

In your code, I don't see the purpose of opening AttributeDefinitions at all.

 

The AttributeReference.TagString property holds the attribute's tag.

 

 

0 Likes
Message 7 of 31

_gile
Consultant
Consultant

Hi

 

Here's your code after some cleanup and optimization.

It should work if there's no type in "INITIALS".

 

C#

 

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (bt.Has(blockName))
                {
                    var btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
                    foreach (ObjectId id in btr)
                    {
                        if (id.ObjectClass.DxfName == "ATTDEF")
                        {
                            var attDef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);
                            if (attDef.Tag != "INITIALS")
                            {
                                var attRef = (AttributeReference)tr.GetObject(br.AttributeCollection[z], OpenMode.ForRead);
                                tagList.Add(attDef.Tag);
                                textList.Add(attRef.TextString);
                            }
                        }
                    }
                }
                tr.Commit();
            }

VB automatic conversion with Telerik

 

 

 

Using tr As Transaction = db.TransactionManager.StartTransaction()
    Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
    If bt.Has(blockName) Then
	Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(blockName), OpenMode.ForRead), BlockTableRecord)
	For Each id As ObjectId In btr
	    If id.ObjectClass.DxfName = "ATTDEF" Then
		Dim attDef As AttributeDefinition = DirectCast(tr.GetObject(id, OpenMode.ForRead), AttributeDefinition)
		If attDef.Tag <> "INITIALS" Then
		    Dim attRef As AttributeReference = DirectCast(tr.GetObject(br.AttributeCollection(z), OpenMode.ForRead), AttributeReference)
		    tagList.Add(attDef.Tag)
		    textList.Add(attRef.TextString)
		End If
	    End If
	Next
    End If
    tr.Commit()
End Using

'=======================================================
'Service provided by Telerik (www.telerik.com)
'Conversion powered by NRefactory.
'Twitter: @telerik
'Facebook: facebook.com/telerik
'=======================================================

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 8 of 31

_gile
Consultant
Consultant

Another little optimization: we do not know anything about 'br' and 'z', but it looks like you could open the attribute reference only once instead of  each loop.

You can also upper case the attribute definition tag before comparing it to "INITIALS"

 

Using tr As Transaction = db.TransactionManager.StartTransaction()
    Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
    If bt.Has(blockName) Then
        Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(blockName), OpenMode.ForRead), BlockTableRecord)
        Dim attRef As AttributeReference = DirectCast(tr.GetObject(br.AttributeCollection(z), OpenMode.ForRead), AttributeReference)
        For Each id As ObjectId In btr
            If id.ObjectClass.DxfName = "ATTDEF" Then
                Dim attDef As AttributeDefinition = DirectCast(tr.GetObject(id, OpenMode.ForRead), AttributeDefinition)
                If attDef.Tag.ToUpper() <> "INITIALS" Then
                    tagList.Add(attDef.Tag)
                    textList.Add(attRef.TextString)
                End If
            End If
        Next
    End If
    tr.Commit()
End Using


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 9 of 31

Anonymous
Not applicable

There are about 40 attributes that I'm iterating from one block to another minus the attribute with the tag INITIALS.  "br" is the blockreference, z is a list count used later.

0 Likes
Message 10 of 31

_gile
Consultant
Consultant

What I wanted to say is that as 'z' is not incremented in the For Each loop the attribute is the same every time, so it's more efficient to open it before the loop.

 

Anyway, did you try it? the attribute tagged "INITIALS" should be skipped, if not, it's a typo issue (case or non-printable characters) in the attribute tag.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 11 of 31

Anonymous
Not applicable

I tried it.  In it you referenced br without defining it.  Working on it now.  And thank you.

0 Likes
Message 12 of 31

Anonymous
Not applicable

Removed reference AttRef (Attribute Reference) completely.  Works.  Thank you all for help.  Partial solution to all as I combined some suggestions that were outside the question.  Thank you all.

 

            Using AcTrans As Transaction = AcDb.TransactionManager.StartTransaction()
                Dim bt As BlockTable = DirectCast(AcTrans.GetObject(AcDb.BlockTableId, OpenMode.ForRead), BlockTable)
                If bt.Has(BlkName) Then
                    Dim btr As BlockTableRecord = DirectCast(AcTrans.GetObject(bt(BlkName), OpenMode.ForRead), BlockTableRecord)
                    'Dim attRef As AttributeReference = DirectCast(AcTrans.GetObject(br.AttributeCollection(z), OpenMode.ForRead), AttributeReference)
                    For Each id As ObjectId In btr
                        If id.ObjectClass.DxfName = "ATTDEF" Then
                            Dim attDef As AttributeDefinition = DirectCast(AcTrans.GetObject(id, OpenMode.ForRead), AttributeDefinition)
                            If attDef.Tag.ToUpper() <> "INITIALS" Then
                                taglist.Add(attDef.Tag)
                                txtlist.Add(attDef.TextString)
                            End If
                        End If
                    Next
                End If
                AcTrans.Commit()
            End Using
0 Likes
Message 13 of 31

_gile
Consultant
Consultant

Oops!...

 

this one should work:

 

Using tr As Transaction = db.TransactionManager.StartTransaction()
    Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
    If bt.Has(blockName) Then
        Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(blockName), OpenMode.ForRead), BlockTableRecord)
	Dim br As BlockReference = tr.GetObject(ObjId, OpenMode.ForRead)
        For Each id As ObjectId In btr
            If id.ObjectClass.DxfName = "ATTDEF" Then
                Dim attDef As AttributeDefinition = DirectCast(tr.GetObject(id, OpenMode.ForRead), AttributeDefinition)
                If attDef.Tag.ToUpper() <> "INITIALS" Then
		    Dim attRef As AttributeReference = DirectCast(tr.GetObject(br.AttributeCollection(z), OpenMode.ForRead), AttributeReference)
                    tagList.Add(attDef.Tag)
                    textList.Add(attRef.TextString)
		    z += 1
                End If
            End If
        Next
    End If
    tr.Commit()
End Using

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 14 of 31

Anonymous
Not applicable

**** I jumped too quick.  Without the block reference it grabs no attributes.  Back into it.

0 Likes
Message 15 of 31

Anonymous
Not applicable

Doesn't declare ObjID.  I think what might be missing from my explanation is that I have to first iterate through all blocks to find the specific one, then pull the attributes out of that one.  Starting with my original it does just that except it doesn't skip the attribute with the tag 'INITIALS'.

0 Likes
Message 16 of 31

_gile
Consultant
Consultant

Ron_M a écrit :

Doesn't declare ObjID.


I cannot know more about your code than what you posted in the original post (where ObjectId is not declared)...

The code I provided is just to replace the code you posted.

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 17 of 31

_gile
Consultant
Consultant

Ron_M a écrit :

I have to first iterate through all blocks to find the specific one, then pull the attributes out of that one..


No, you do not need to iterate all the block table to find a specific bloc.

SymbolTable derived types (as BlockTable) have an indexor which allows to directly get a SymbolTableRecord from uts name.

 

Please, attentively compare the code of your first post with the last one I provided, it exactly does the same but in a more efficient and logical way.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 18 of 31

Anonymous
Not applicable

I directly copy/paste your code in and it shows error in that it doesn't define br or the block reference which leads to not having the object id.  We're getting way off track anyway.  I didn't and still don't have an issue with getting the block.  Your suggestions, and those of others, directly copied or modify does not skip the attribute when pulling lists of tags and text strings.

0 Likes
Message 19 of 31

_gile
Consultant
Consultant

Try this one (ObjId is supposed to be assign to some block reference you want to get the attribute values):

 

Using tr As Transaction = db.TransactionManager.StartTransaction()
    Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
    If bt.Has(blockName) Then
        Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(blockName), OpenMode.ForRead), BlockTableRecord)
	Dim br As BlockReference = DirectCast(tr.GetObject(ObjId, OpenMode.ForRead), BlockReference)
        For Each id As ObjectId In btr
            If id.ObjectClass.DxfName = "ATTDEF" Then
                Dim attDef As AttributeDefinition = DirectCast(tr.GetObject(id, OpenMode.ForRead), AttributeDefinition)
		If System.Text.RegularExpressions.Regex.Match(attDef.Tag, "initials", RegexOptions.IgnoreCase) Then
		    MsgBox("Skipping " & attDef.Tag)
                Else
		    Dim attRef As AttributeReference = DirectCast(tr.GetObject(br.AttributeCollection(z), OpenMode.ForRead), AttributeReference)
                    tagList.Add(attDef.Tag)
                    textList.Add(attRef.TextString)
		    z += 1
                End If
            End If
        Next
Else
MsgBox("Block " & blockName & " not found.") End If tr.Commit() End Using

it would be easier for those who are trying to help you if provide some drawing with the block.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 20 of 31

Anonymous
Not applicable

Attached is a test block. I need to get all text strings from the block into a list so that they can then be placed back in an updated block without the INITIALS attribute.

 

 

Your latest still takes out the ObjId which I already have. Please move past that. My original post and code works EXCEPT, and ONLY EXCEPT that it does not skip the attribute with a tag of INITIALS. That is the ONLY thing not working. The msgbox fires as it is supposed to when it hits the attribute to be skipped.  Debug shows that the msgbox fires when it is supposed to. 

0 Likes