November 15, 2019

ACA-AMEP: Edit Property Data Via AutoLISP, Part 3

First article in the series.
Previous article in the series.

In the previous article, we used a while loop to examine each Property Set in the collection of Property Sets attached to the object of interest, comparing each Property Set's Name to the name of the Property Set that holds the Property whose value is to be changed. At this point, there are two possible conditions:
  1. A matching Property Set was found. The value in the Property Set counter variable, iPSet, was set to one more than the number of Property Sets in the collection (variable iPSets).
  2. A matching Property Set was not found. The value in the Property Set counter variable, iPSet, will be equal to the number of Property Sets in the collection (variable iPSets).
(cond    ; Cond A.
  ((= iPSet iPSets)
   ;; If the Property Set is not found after processing all attached property sets, issue prompt.
   (prompt
     (strcat
       "\nProperty Set "
       sPSet
       " not found on object passed to argument obj. "
     ) ;_ End strcat.
   ) ;_ End prompt.
   nil    ; Return nil.
  ) ;_ End condition A1.
  (T    ; Else, continue.
   (setq oProps (vlax-get-property oPSet 'Properties)
          ; Get Properties object of the Property Set.
         iProps (vlax-get-property oProps 'Count)
    ; Get number of Properties in the Property Set.
         iProp  0  ; Initialize Property counter.
   ) ;_ End setq.

   (while (< iProp iProps) ; While unprocessed Properties remain...
     (setq oProp   (vlax-invoke-method oProps 'Item iProp)
    ; Get current Property object.
    sPropNm (vlax-get-property oProp 'Name)
    ; Get Property name.
     ) ;_ End setq.
     (if (= (strcase sPropNm) (strcase sProp))
        ; If target Property found...
       (setq iProp (1+ iProps)) ; ...exit while loop.
       (setq iProp (1+ iProp)) ; ...else, increment Property counter.
     ) ;_ End if.
   ) ;_ End while.

   (cond   ; Cond A2B.
     ((= iProp iProps)
      ;; If the Property is not found after processing all Properties in the Property Set, issue prompt.
      (prompt
        (strcat
          "\nProperty "
          sProp
          " not found in Property Set "
          sPSet
          " attached to the object passed to argument obj. "
        ) ;_ End strcat.
      ) ;_ End prompt.
      nil   ; Return nil.
     ) ;_ End condition A2B1.
     (T    ; Else, update Property value with processed value.
      (setq varPropValOld (vlax-get-property oProp 'Value))

      ***** ADD CODE HERE TO GENERATE THE DESIRED NEW VALUE   *****
      ***** SET VARIABLE sPropValNew to the NEW DESIRED VALUE *****

      (vlax-put-property oProp 'Value sPropValNew)
      sPropValNew   ; Return new string value.
     ) ;_ End condition A2B2.
   ) ;_ End cond A2B.

  ) ;_ End condition A2.
) ;_ End cond A.

Here is what is happening in that code:
  • A cond statement is used to determine which of the two conditions noted above is active. The first test checks to see if iPSet and iPSets are equal. If this is true, then the target Property Set was not found, and there is nothing to process. A prompt is written to the command line to inform the user. I have a separate subroutine to hold this code, so after issuing the prompt, this condition returns nil to the calling routine, to indicate that the requested Property Set was not found. The calling routine can then choose how to handle that situation.
  • If iPSet and iPSets are not equal, then the target Property Set was found and we can continue on. The test for this condition is T (True), because if the first test is false, no further test is required, and the code to process will be contained within this condition.
  • Variable oPSet holds the Property Set object whose name matched the target Property Set name. The Properties property of the Property Set object is used to obtain the Properties collection of that Property Set. The Properties collection contains all of the individual Property objects that are defined in that Property Set Definition.
  • The Count property of the Properties collection is used to determine the total number of Properties in the collection (variable iProps). A variable to hold the Property counter, iProp is initialized to 0, the index of the first Property in the collection.
  • Similar to the way we iterated over the Property Set collection, a while loop is used to iterate over the Properties collection, looking for a Property whose name matches the target property name, which is held in variable sProp. If a match is found, iProp is set to one more than the total number of Properties in the collection. If a match is not found, then iProp is incremented by 1, so that the next Property in the collection will be processed on the next pass of the loop, if at least one unprocessed Proeprty remains.
  • At this point, there are two possible conditions:
    1. A matching Property was found, and the value of iProp is one more than the value of iProps
    2. A matching Property was not found, and the values of iProp and iProps are equal.
  • Once again, a cond statement is used to run the appropriate code. If a matching Property was not found, the first condition writes a prompt to the command line to inform the user that the Property was not found, and returns nil to the calling routine, to indicate that the requested Property was not found in the requested Property Set. The calling routine can then choose how to handle that situation.
  • If the target Property was found, then the first condition will not be executed, and the second condition will be executed, as the test is set to T.
  • The Value property of the Property object is used to obtain the current value, storing it in variable varPropValOld.
  • At this point, you will need to add the code that generates the new value for the target Property, saving that value to variable varPropValNew
  • The vlax-put-property function is used to push the new value onto the Value property of the Property Object. This condition then returns the new value to the calling routine.
  • All of the currently open conditions and cond functions are then ended.

If you choose to have all your code in a single AutoLISP command function, then instead of returning nil or varPropValNew at the end of the A1, A2B1 and A2B2 conditions, you would add whatever additional code you may feel appropriate to run prior to the end of your command function.

No comments: