1

I need to change an attribute of drawing with the ObjectDBX method using AutoLISP. this routine run properly but not change the attribute,can you suggest any change in code or any other method to achieve this task? Thank you.

;;;;;;;;;;;;;;;;;;;

(defun DBX_ATT_CHANGE (f)
  (vl-load-com)
  (setq cadver (substr (getvar "acadver") 1 2))
  (setq id (strcat "objectdbx.AxDbDocument." cadver))
  (setq dbx (vlax-create-object id))
  (vla-open dbx f)

  (vlax-for n_object (vla-get-modelspace dbx)
    (setq dbx_en (vlax-vla-object->ename n_object))


    (setq upc_blkobj (vlax-ename->vla-object dbx_en))



    (if (vlax-method-applicable-p upc_blkobj 'GetAttributes)

      (progn
    (setq upc_attlist

           (vlax-invoke upc_blkobj 'GetAttributes)
    )

    (foreach upc_att upc_attlist
      (progn
        (if (= (vla-get-tagstring upc_att) (strcase "P_TAG1"))
          (vlax-put-property
        upc_att
        'TextString
        "555"
          )
        )
      )
    )
      )
    )
    (vlax-release-object upc_blkobj)


  )



  (vla-saveas dbx dwgfile)
  (vlax-release-object dbx)
  (prin1)
)
(defun c:test ()
  (DBX_ATT_CHANGE
    "D:/6. R&D/Delet Group LispDBXapi/7-EU-FE-48-AC-CIOC-SA - Copy.dwg"

  )
)

;;;;;;;;;;;;;;;

Dinesh Vilas Pawar
  • 493
  • 2
  • 5
  • 18

1 Answers1

2

There are a couple of oddities present in your current code:


  1. (setq dbx_en (vlax-vla-object->ename n_object))
    (setq upc_blkobj (vlax-ename->vla-object dbx_en))
    

    You are converting the vla-object n_object into an entity name dbx_en, and then converting this entity name back into a vla-object upc_blkobj. These two lines are redundant, as you can work with the n_object variable directly.


  1. (= (vla-get-tagstring upc_att) (strcase "P_TAG1"))
    

    You are using strcase to convert a literal uppercase string P_TAG1 to uppercase, and then comparing this uppercase string to a string which may or may not be uppercase - I believe this line should be:

    (= (strcase (vla-get-tagstring upc_att)) "P_TAG1")
    

To offer you an alternative for this task, you could make use of my ObjectDBX Wrapper function, which provides a way to evaluate a given function on another drawing or set of drawings, without opening such drawings in the AutoCAD Editor.

I would personally write your code in the following way:

(defun c:test ( )
    (LM:DBXAttChange
        "D:\\6. R&D\\Delet Group LispDBXapi\\7-EU-FE-48-AC-CIOC-SA - Copy.dwg"
        '(("P_TAG1" . "555"))
    )
    (princ)
)       

(defun LM:DBXAttChange ( dwg lst / doc flg val )
    (if (setq doc (LM:GetDocumentObject dwg))
        (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 (and (setq val (cdr (assoc (strcase (vla-get-tagstring att)) lst)))
                                     (vlax-write-enabled-p att)
                                )
                                (progn
                                    (vla-put-textstring att val)
                                    (setq flg t)
                                )
                            )
                        )
                    )
                )
            )
            (if flg (vla-saveas doc dwg))
            (vlax-release-object doc)
            flg
        )
        (prompt (strcat "\nThe drawing \"" dwg "\" was not found or could not be accessed."))
    )
)

;; Get Document Object  -  Lee Mac
;; Retrieves the VLA Document Object for the supplied filename.
;; The Document Object may be present in the Documents collection, or obtained through ObjectDBX.
;; It is the callers responsibility to release such object.

(defun LM:GetDocumentObject ( dwg / app dbx dwl err vrs )
    (cond
        (   (not (setq dwg (findfile dwg))) nil)
        (   (cdr
                (assoc (strcase dwg)
                    (vlax-for doc (vla-get-documents (setq app (vlax-get-acad-object)))
                        (setq dwl (cons (cons (strcase (vla-get-fullname doc)) doc) dwl))
                    )
                )
            )
        )
        (   (progn
                (setq dbx
                    (vl-catch-all-apply 'vla-getinterfaceobject
                        (list app
                            (if (< (setq vrs (atoi (getvar 'acadver))) 16)
                                "objectdbx.axdbdocument" (strcat "objectdbx.axdbdocument." (itoa vrs))
                            )
                        )
                    )
                )
                (or (null dbx) (vl-catch-all-error-p dbx))
            )
            (prompt "\nUnable to interface with ObjectDBX.")
        )
        (   (vl-catch-all-error-p (setq err (vl-catch-all-apply 'vla-open (list dbx dwg))))
            (prompt (strcat "\n" (vl-catch-all-error-message err)))
        )
        (   dbx   )
    )
)

(vl-load-com) (princ)
Lee Mac
  • 15,615
  • 6
  • 32
  • 80
  • Thank you very much, I made those improvements in my code, Also use your ObjectDBX Wrapper function it works perfectly in my case. – Dinesh Vilas Pawar Mar 22 '18 at 04:53
  • I try to understood what is difference between "vla-get-block" and "vla-get-blocks" ? where those methods are use – Dinesh Vilas Pawar Mar 22 '18 at 09:35
  • 1
    @DineshPawar You're most welcome. `vla-get-blocks` returns the Block Collection of the supplied Document Object, whereas `vla-get-block` returns the block container associated with the layout, which contains all objects created in the layout. – Lee Mac Mar 22 '18 at 12:59
  • @ lee mac, Is it possible to create a table with ObjectDBX.? (if not then can we update, modified or delete a table using ObjectDBX) – Dinesh Vilas Pawar Mar 23 '18 at 12:04