Author Topic: vlr-object-reactor to update one attribute after others have been modified  (Read 4375 times)

0 Members and 1 Guest are viewing this topic.

Cawaugh

  • Guest
I need to update a visible attribute when the other attributes have had there values changed.
I need to only to enter text into several attributes (which are hidden and used only in reports)
then I contatenate them into a visible attribute which is for show on a dwg.
I have the routine to gather the info then update the visible attribute but it is only when you do the initial insertion.
If someone edits the component later, i need to update the visible attribute as well.

Any suggestions?

Thanks in advance.

ronjonp

  • Needs a day job
  • Posts: 7531
Re: vlr-object-reactor to update one attribute after others have been modified
« Reply #1 on: February 07, 2011, 05:58:08 PM »
See if this gives you any ideas. You can link attribute values using fields.

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Lee Mac

  • Seagull
  • Posts: 12922
  • London, England
Re: vlr-object-reactor to update one attribute after others have been modified
« Reply #2 on: February 07, 2011, 06:04:47 PM »
Here's a quick example:

Code: [Select]
(defun c:test nil
  (vl-load-com)

  ;;----------------------------------------------;;
  ;; Example © Lee Mac 2011  -  www.lee-mac.com   ;;
  ;;----------------------------------------------;;
 
  (
    (lambda ( data callback / reactor att )
      (if
        (setq reactor
          (vl-some
            (function
              (lambda ( _reactor )
                (if (eq data (vlr-data _reactor))
                  _reactor
                )
              )
            )
            (cdar (vlr-reactors :vlr-object-reactor))
          )
        )
        (vlr-remove reactor)
        (if
          (and
            (setq att (car (nentsel "\nSelect Attribute to Monitor: ")))
            (eq "ATTRIB" (cdr (assoc 0 (entget att))))
          )
          (setq reactor
            (vlr-object-reactor (list (vlax-ename->vla-object att)) data
              (list
                (cons :vlr-modified callback)
              )
            )
          )
        )
      )
      reactor
    )
    "AttributeObjectReactor"
    'AttributeObjectReactorCallback
  )

  (princ)
)


(defun AttributeObjectReactorCallback ( object reactor parameters )
  (vl-load-com)

  (if (not (vlax-erased-p object))
    (progn
      (setq *ReactorData* (cons object reactor))
      (vlr-command-reactor "AttributeCommandReactor"
        (list
          (cons :vlr-commandended 'AttributeCommandReactorCallback)
        )
      )
    )
  )
  (vlr-remove reactor)
 
  (princ)
)

(defun AttributeCommandReactorCallback ( reactor parameters )
  (vl-load-com)
 
  (vlr-remove reactor)

  (if (and *ReactorData* (not (wcmatch (strcase (car parameters)) "*UNDO")))
    (progn
      (
        (lambda ( tagstring )
          (mapcar
            (function
              (lambda ( attrib )
                (if (not (eq (vla-get-TagString attrib) tagstring))
                  (vla-put-TextString attrib "ABC")
                )
              )
            )
            (vlax-invoke
              (vla-objectidtoobject
                (setq *acdoc*
                  (cond ( *acdoc* ) ( (vla-get-ActiveDocument (vlax-get-acad-object)) ))
                )
                (vla-get-ownerid (car *ReactorData*))
              )
              'GetAttributes
            )
          )
        )
        (vla-get-TagString (car *ReactorData*))
      )
      (vlr-add (cdr *ReactorData*))
      (setq *ReactorData* nil)
    )
  )

  (princ)
)

Type 'test' to enable and disable the reactor (coded as a toggle).

Select an attribute to 'monitor': when its value is changed, the values of the other attributes in the block (should there be any) are changed to "ABC" (just as an example - it could be modified to only update a single attribute of a specific tag of course with arbitrary data).

This example uses the attribute object itself as the owner of the object reactor - however it could be modified to monitor all attributes in the block (using the :vlr-subobjmodified event).

Lee
« Last Edit: February 07, 2011, 06:14:51 PM by Lee Mac »

Lee Mac

  • Seagull
  • Posts: 12922
  • London, England
Re: vlr-object-reactor to update one attribute after others have been modified
« Reply #3 on: February 07, 2011, 06:05:55 PM »
You can link attribute values using fields.

Thinking outside of the box - I like it  :-) My tunnel-vision led me to reactors immediately...  :|

ronjonp

  • Needs a day job
  • Posts: 7531
Re: vlr-object-reactor to update one attribute after others have been modified
« Reply #4 on: February 07, 2011, 06:18:26 PM »
You can link attribute values using fields.

Thinking outside of the box - I like it  :-) My tunnel-vision led me to reactors immediately...  :|

:)   Nice code Lee (as usual).

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Lee Mac

  • Seagull
  • Posts: 12922
  • London, England
Re: vlr-object-reactor to update one attribute after others have been modified
« Reply #5 on: February 07, 2011, 06:21:09 PM »
You can link attribute values using fields.

Thinking outside of the box - I like it  :-) My tunnel-vision led me to reactors immediately...  :|

:)   Nice code Lee (as usual).

Thanks Ron!  :-)

T.Willey

  • Needs a day job
  • Posts: 5251
Re: vlr-object-reactor to update one attribute after others have been modified
« Reply #6 on: February 07, 2011, 06:28:23 PM »
Here is a way to use fields with multiple strings to gather information from.  Will put a space between each string.

Code: [Select]
(defun c:Test ( / Sel Data Str )
   
    (setvar 'ErrNo 0)
    (while (not (equal (getvar 'ErrNo) 52))
        (if
            (and
                (setq Sel (nentsel "\n Select text entity: "))
                (setq Data (entget (car Sel)))
                (member (cdr (assoc 0 Data)) '("TEXT" "MTEXT" "ATTRIB"))
            )
            (setq Str
                (if Str
                    (strcat Str " " "%<\\AcObjProp Object(%<\\_ObjId " (itoa (vla-get-ObjectId (vlax-ename->vla-object (car Sel)))) ">%).TextString >%")
                    (strcat "%<\\AcObjProp Object(%<\\_ObjId " (itoa (vla-get-ObjectId (vlax-ename->vla-object (car Sel)))) ">%).TextString>%")
                )
            )
        )
    )
    (if
        (and
            (setq Sel (nentsel "\n Select text entity to place field: "))
            (setq Data (entget (car Sel)))
            (member (cdr (assoc 0 Data)) '("TEXT" "MTEXT" "ATTRIB"))
        )
        (vla-put-TextString (vlax-ename->vla-object (car Sel)) Str)
    )
    (princ)
)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

ronjonp

  • Needs a day job
  • Posts: 7531
Re: vlr-object-reactor to update one attribute after others have been modified
« Reply #7 on: February 07, 2011, 07:07:39 PM »
Here's some code to add the fields:

Code: [Select]
(defun c:nameit (/ att atts e obj string x)
  ;;Places the linked field values of all invisible attributes into the visible attribute
  (and (setq e (car (entsel (strcat "Select attributed block: "))))
       (vlax-property-available-p (setq obj (vlax-ename->vla-object e)) 'hasattributes)
       (setq atts (vlax-invoke obj 'getattributes))
       (setq att (car (vl-remove-if '(lambda (x) (minusp (vlax-get x 'invisible))) atts)))
       (setq string (mapcar '(lambda (x)
       (if (minusp (vlax-get x 'invisible))
(strcat "%<\\AcObjProp Object(%<\\_ObjId "
(itoa (vla-get-objectid x))
">%).TextString >%"
" "
)
""
       )
     )
    atts
    )
       )
       (vla-put-textstring att (apply 'strcat string))
  )
  (princ)
)

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

T.Willey

  • Needs a day job
  • Posts: 5251
Re: vlr-object-reactor to update one attribute after others have been modified
« Reply #8 on: February 09, 2011, 01:52:55 PM »
Decided to update my code that will add the fields using regular Lisp.

Code: [Select]
(defun AddObjectField (AddToEname objPropList / EntData ExDict FDict cnt str len )
    
    ; AddToEname = value ename that the field(s) will be added to.
    ; objPropList = list of lists, that have a valid vla object and property,
    ;   ie: ((#<VLA-OBJECT IAcadText 0ee928cc> . "TextString") (#<VLA-OBJECT IAcadText 0ee92764> . "TextString"))
    
    (if
        (and
            (setq EntData (entget AddToEname))
            (vl-position (value 0 EntData) '("TEXT" "MTEXT" "ATTRIB" "ATTDEF"))
            (setq ExDict
                (vlax-vla-object->ename
                    (vla-GetExtensionDictionary
                        (vlax-ename->vla-object AddToEname)
                    )
                )
            )
            (setq cnt -1)
            (setq str "")
            (setq len (length objPropList))
        )
        (progn
            (dictremove ExDict "ACAD_FIELD")
            (setq FDict
                (dictadd ExDict "ACAD_FIELD"
                    (entmakex
                        '(
                            (0 . "DICTIONARY")
                            (100 . "AcDbDictionary")
                            (280 . 1)
                            (281 . 1)
                        )
                    )
                )
            )
            (dictadd FDict "TEXT"
                (entmakex
                    (append
                        (list
                            '(0 . "FIELD")
                            '(100 . "AcDbField")
                            '(1 . "_text")
                            (cons 2 (repeat len (setq str (strcat str "%<\\_FldIdx " (itoa (setq cnt (1+ cnt))) ">%" (if (equal (1+ cnt) len) "" " ")))))
                            ;'(2 . "%<\\_FldIdx 0>%")
                            (cons 90 (length objPropList)) ;Number of child fields
                        )
                        (mapcar
                            (function
                                (lambda ( x / LinkObj PropName PropType PropValue )
                                    (setq LinkObj (car x))
                                    (setq PropName (cdr x))
                                    (setq PropType
                                        (type
                                            (setq PropValue
                                                (vlax-get LinkObj PropName)
                                            )
                                        )
                                    )
                                    (cons 360 ;Child field ID
                                        (entmakex
                                            (list
                                                '(0 . "FIELD")
                                                '(100 . "AcDbField")
                                                '(1 . "AcObjProp") ; Field type
                                                (cons
                                                    2
                                                    (strcat
                                                        "\\AcObjProp Object(%<\\_ObjIdx 0>%)."
                                                        PropName
                                                    )
                                                )
                                                '(90 . 0) ; Number of child fields
                                                '(97 . 1) ; Number of object ids
                                                (cons 331 (vlax-vla-object->ename LinkObj)) ; Object id
                                                '(4 . "") ; format string
                                                '(91 . 63) ; evaluation option
                                                '(92 . 0) ; filling option
                                                ;'(94 . 59) ; field state flag
                                                ;'(95 . 2) ; evaluation status
                                                ;'(96 . 0) ; evaluation error code
                                                ;'(300 . "") ; evaluation error message
                                                '(6 . "ObjectPropertyId")
                                                '(90 . 64)
                                                (cons 330 (vlax-vla-object->ename LinkObj))
                                                '(6 . "ObjectPropertyName") ; key string for the field data
                                                '(90 . 4) ; data type of field
                                                (cons 1 PropName) ; name of property
                                                '(7 . "ACAD_FIELD_VALUE") ; key string for the evaluated cache
                                                (cons
                                                    90 ;data type of field
                                                    (cond
                                                        ((equal PropType 'STR)
                                                            4
                                                        )
                                                        ((equal PropType 'INT)
                                                            1
                                                        )
                                                        ((equal PropType 'REAL)
                                                            2
                                                        )
                                                        ((equal PropType 'LIST)
                                                            32
                                                        )
                                                    )
                                                )
                                                (cond ; field value
                                                    ((equal PropType 'STR)
                                                        (cons 1 PropValue)
                                                    )
                                                    ((equal PropType 'INT)
                                                        (cons 91 PropValue)
                                                    )
                                                    ((equal PropType 'REAL)
                                                        (cons 140 PropValue)
                                                    )
                                                    ((equal PropType 'LIST)
                                                        (cons 11 Propvalue)
                                                    )
                                                )
                                                '(300 . "") ; format string for '08
                                                '(301 . "") ; format string
                                                '(98 . 0) ; length of format string
                                            )
                                        )
                                    )
                                )
                            )
                            objPropList
                        )
                        (list
                            '(97 . 0) ; Number of object IDs used in the field code
                            '(4 . "") ; Format string
                            '(91 . 63) ; Evaluation option
                                ;kDisable 0 Disable evaluation.
                                ;kOnOpen (0x1 << 0) Evaluate during drawing load.
                                ;kOnSave (0x1 << 1) Evaluate during drawing save.
                                ;kOnPlot (0x1 << 2) Evaluate during drawing plot.
                                ;kOnEtransmit (0x1 << 3) Evaluate during eTransmit.
                                ;kOnRegen (0x1 << 4) Evaluate during regen.
                                ;kOnDemand (0x1 << 5) Evaluate only on demand by the user or the API.
                                ;kAutomatic (kOnOpen | kOnSave | kOnPlot | kOnEtransmit | kOnRegen | kOnDemand) Automatically evaluate fields during all the operations.
                            '(92 . 0) ;Filling option
                                ;kSkipFilingResult (0x1 << 0) Do not file out the cached evaluation result with the field.
                            ;'(94 . 5) ;Field state flag
                                ;kInitialized (0x1 << 0) Field is not yet intitalized with any field code or data.
                                ;kCompiled (0x1 << 1) Field has been compiled.
                                ;kModified (0x1 << 2) Field has been modified and not yet evaluated.
                                ;kEvaluated (0x1 << 3) Field has been evaluated. Use evaluationStatus() to get the evaluation status.
                                ;kHasCache (0x1 << 4) The field has a cache of the evaluated result.
                                ;'(95 . 1) ;Evaluation status
                                ;kNotYetEvaluated (0x1 << 0) Field is not yet evaluated.
                                ;kSuccess (0x1 << 1) Field is evaluated successfully.
                                ;kEvaluatorNotFound (0x1 << 2) Evaluator was not found.
                                ;kSyntaxError (0x1 << 3) Syntax error in the field expression.
                                ;kInvalidCode (0x1 << 4) Invalid field code or expression.
                                ;kInvalidContext (0x1 << 5) Current context is invalid for evaluating the field.
                                ;kOtherError (0x1 << 6) Evaluation has failed.
                            ;'(96 . 0) ;Evaluation error code
                            ;'(300 . "") ;Evaluation error message
                            '(93 . 1) ;Number of the data set in the field
                            '(6 . "ACFD_FIELDTEXT_CHECKSUM") ;Key string for field data
                            '(90 . 2) ;Data type of field value
                            '(140 . 33.0) ;Double value
                            '(7 . "ACFD_FIELD_VALUE") ;Key string from the evaluated cache, hard coded as is shown here
                            '(90 . 0) ;Data type of field value
                            '(91 . 0) ;Long value
                            '(301 . "") ; format string
                            '(98 . 0) ; format string length
                        )
                    )
                )
            )
            (entupd AddToEname)
        )
    )
)
Test function below.
Code: [Select]
(defun c:Test ( / Sel Data Str lst Ent )
    
    (setvar 'ErrNo 0)
    (while (not (equal (getvar 'ErrNo) 52))
        (if
            (and
                (setq Sel (nentsel "\n Select text entity: "))
                (setq Data (entget (setq Ent (car Sel))))
                (member (cdr (assoc 0 Data)) '("TEXT" "MTEXT" "ATTRIB"))
                (not (redraw Ent 3))
            )
            (setq lst (cons Ent lst))
        )
    )
    (foreach i lst (redraw i 4))
    (if
        (and
            (setq Sel (nentsel "\n Select text entity to place field: "))
            (setq Data (entget (car Sel)))
            (member (cdr (assoc 0 Data)) '("TEXT" "MTEXT" "ATTRIB"))
        )
        (AddObjectField (car Sel) (mapcar (function (lambda ( x ) (cons (vlax-ename->vla-object x) "TextString"))) (reverse lst)))
    )
    (princ)
)

Edit:  Another example.
Code: [Select]
(setq ob2 (vlax-ename->vla-object (car (entsel))))
(addobjectfield (car (entsel)) (list (cons ob2 "textstring") (cons ob2 "insertionpoint")))
« Last Edit: February 09, 2011, 02:04:43 PM by T.Willey »
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.