lispautocadautocad-pluginautolispautocad-scripts

How to delete all Attributes from all Blocks with AutoLISP using ObjectDBX


I want to delete all attribute of block inside drawing using AutoLISP ObjectDBX method.

The below program works well: it deletes the attributes of all blocks inside the drawing, but when I edit this block in the Block Editor, I see all the attributes are still there.

I think I need to delete this attribute from definition of block.

;[dwgin]--input drawing file
;[dwgout]-- Output drawing fath with name
;function 'LM:GetDocumentObject' lee mac function to open drawing in ObjectDBX method
(defun DBXAttDelete ( dwgin dwgout / doc flg val )
    (if (setq doc (LM:GetDocumentObject dwgin))
        (progn
            (vlax-for lyt (vla-get-layouts doc)
                (vlax-for obj (vla-get-block lyt)
                    (if (and (= "AcDbBlockReference" (vla-get-objectname obj))
                             (= :vlax-true (vla-get-hasattributes obj))
                        )
                        (foreach att (vlax-invoke obj 'getattributes)              

                    (if (vl-catch-all-error-p (setq err (vl-catch-all-apply 'vla-delete (list att))))
                      (princ (strcat "\nERROR: " (vl-catch-all-error-message err)))

                    )
                        )
                    )
                )
            )
           (vla-saveas doc dwgout)
            (vlax-release-object doc)
            flg
        )
        (prompt (strcat "\nThe drawing \"" dwgin "\" was not found or could not be accessed."))
    )
)

Can you help to find where I need to improve/correct this program.


Solution

  • Consider that the Block Definition is essentially the "blueprint" for the block, and each Block Reference is an instance displaying the objects found within the block definition, at a specific position, scale, rotation & orientation in the drawing.

    Attributes also have Attribute Definitions within the Block Definition, and corresponding Attribute References attached to each Block Reference. Such attribute references may then hold different text content for each block reference inserted in the drawing.

    Aside, interestingly, attribute references may also be programmatically attached to a block reference independently of the block definition, however, this is not permitted when operating AutoCAD using the standard out-of-the-box front end.

    As such, to remove all attributes from the drawing, you'll need to delete the attribute references associated with all block references, and the attribute definitions from the corresponding block definitions.

    You may also want to unlock locked layers prior to performing the delete operation, and relock the previously locked layers following this operation.

    Since layouts are merely a type of block, iterating over the blocks collection will be sufficient to process all layouts, blocks, and nested blocks (excluding xrefs):

    (defun DBXAttDelete ( dwgin dwgout / doc lck )
        (if (setq doc (LM:GetDocumentObject dwgin))
            (progn
                (vlax-for lay (vla-get-layers doc)
                    (if (= :vlax-true (vla-get-lock lay))
                        (progn
                            (setq lck (cons lay lck))
                            (vla-put-lock lay :vlax-false)
                        )
                    )
                )
                (vlax-for blk (vla-get-blocks doc)
                    (if (= :vlax-false (vla-get-isxref blk))
                        (vlax-for obj blk
                            (cond
                                (   (= "AcDbBlockReference" (vla-get-objectname obj))
                                    (if (= :vlax-true (vla-get-hasattributes obj))
                                        (foreach att (vlax-invoke obj 'getattributes)
                                            (vla-delete att)
                                        )
                                    )
                                )
                                (   (= "AcDbAttributeDefinition" (vla-get-objectname obj))
                                    (vla-delete obj)
                                )
                            )
                        )
                    )
                )
                (foreach lay lck
                    (vla-put-lock lay :vlax-true)
                )
                (vla-saveas doc dwgout)
                (vlax-release-object doc)
                t
            )
            (prompt (strcat "\nThe drawing \"" dwgin "\" was not found or could not be accessed."))
        )
    )