Ohnoto Posted April 21, 2012 Posted April 21, 2012 (edited) I have modified a LISP program from the thread of, Area of a polyline. What I am trying to do is: - Obtain the square foot of a single polyline area. - Obtain the acad handle of the polyline. Within an attribute block containing many different attribute tags: - Put the value of the square foot into the tag of "NET_SQ_FEET" - Put the acad handle value into the tag of "ACAD_HANDLE" Currently, from the code below, I am getting an error "VLA-OBJECT ". The code is only attempting to place the value of the square footage. I don't even know where to begin to get the value for the polyline acad handle. (defun c:test ( / area en nm pt ) (while (progn (setvar 'ERRNO 0) (setq en (car (entsel))) (cond ( (= 7 (getvar 'ERRNO)) (princ "\nMissed, try again.") ) ( (eq 'ENAME (type en)) (if (vl-catch-all-error-p (setq area (vl-catch-all-apply 'vlax-curve-getarea (list en))) ) (princ "\nInvalid Object.") ) ) ( (setq area nil) ) ) ) ) (setq area (rtos (/ area 144.0) 2 2)) (if (setq block (ssget "_:S")) (progn (setq block (ssname block 0)) (LM:vl-SetAttributeValue (vlax-ename->vla-object block) "NET_SQ_FEET" area) ) ) (princ) ) (vl-load-com) (princ) ;;----------------=={ Set Attribute Value }==-----------------;; ;; ;; ;; Populates the first attribute matching the tag specified ;; ;; found within the block supplied with the value specified, ;; ;; if present. ;; ;;------------------------------------------------------------;; ;; Author: Lee Mac, Copyright © 2010 - www.lee-mac.com ;; ;;------------------------------------------------------------;; ;; Arguments: ;; ;; block - VLA Block Reference Object ;; ;; tag - Attribute TagString ;; ;; value - Value to which the Attribute will be set ;; ;;------------------------------------------------------------;; ;; Returns: Value the attribute was set to, else nil ;; ;;------------------------------------------------------------;; (defun LM:vl-SetAttributeValue ( block tag value ) (setq tag (strcase tag)) (vl-some (function (lambda ( attrib ) (if (eq tag (strcase (vla-get-TagString attrib))) (progn (vla-put-TextString attrib value) value ) ) ) ) (vlax-invoke block 'GetAttributes) ) ) Edited April 21, 2012 by Ohnoto Quote
MSasu Posted April 21, 2012 Posted April 21, 2012 The SSGET function will return a selection set, not an entity; the code below will validate if user selected something and extract the first (and only) item from selection set. Also, seems that Lee's code is expecting a VLA object. [color=red](if [/color](setq block (ssget "_:S")) [color=red] (progn (setq block (ssname block 0))[/color] (LM:vl-SetAttributeValue [color=red](vlax-ename->vla-object[/color] block[color=red])[/color] "NET_SQ_FEET" area) [color=red] ) )[/color] To list an entity, check the ENTGET function: (entget block) The handle is stored on DXF code 5. Quote
Ohnoto Posted April 21, 2012 Author Posted April 21, 2012 Thanks. I updated the original code. I'll look into where the handle is stored. Quote
MSasu Posted April 21, 2012 Posted April 21, 2012 (edited) May be better to use filters to selections. 1. Instead of ENTSEL, this will prevent the user to select nothing but a closed polyline: (if (setq en (ssget "_:S" '((0 . "LWPOLYLINE") (70 . 1)))[color=red])[/color] (setq en (ssname en 0)) ) 2. For block: (setq block (ssget "_:S" '((0 . "INSERT")))) Edited April 21, 2012 by MSasu Fixed code example Quote
Ohnoto Posted April 21, 2012 Author Posted April 21, 2012 I'm getting too few arguments errors when putting in the first code you provided. Could you demonstrate how exactly that should be placed? Quote
MSasu Posted April 21, 2012 Posted April 21, 2012 You are right, I missed a paranthesis - please check the fixed code. Sorry for inconvenience. Quote
Ohnoto Posted April 21, 2012 Author Posted April 21, 2012 Placing this where the ENTSEL is located gives me a "bad argument type: consp " error when selecting the polyline. Quote
MSasu Posted April 21, 2012 Posted April 21, 2012 Can you post please how you modified that part? Quote
Ohnoto Posted April 21, 2012 Author Posted April 21, 2012 (defun c:test ( / area en nm pt ) (while (progn (setvar 'ERRNO 0) (setq en (car (if (setq en (ssget "_:S" '((0 . "LWPOLYLINE") (70 . 1)))) (setq en (ssname en 0)) ))) (cond ( (= 7 (getvar 'ERRNO)) (princ "\nMissed, try again.") ) ( (eq 'ENAME (type en)) (if (vl-catch-all-error-p (setq area (vl-catch-all-apply 'vlax-curve-getarea (list en))) ) (princ "\nInvalid Object.") ) ) ( (setq area nil) ) ) ) ) Quote
MSasu Posted April 21, 2012 Posted April 21, 2012 This is how you should have changed that part: [color=red][s](setq en (car[/s][/color] [color=black](if [/color](setq en (ssget "_:S" '((0 . "LWPOLYLINE") (70 . 1)))) (setq en (ssname en 0)) [color=red][color=black])[/color][s]))[/s][/color] You may write it much simple: (defun c:test ( / area en nm pt) (if (setq en (ssget "_:S" '((0 . "LWPOLYLINE") (70 . 1)))) (if (vl-catch-all-error-p (setq area (vl-catch-all-apply 'vlax-curve-getarea (list (ssname en 0)))) ) (princ "\nInvalid Object.") ) ) (setq area (rtos (/ area 144.0) 2 2)) [color=magenta]...[/color] Quote
Ohnoto Posted April 21, 2012 Author Posted April 21, 2012 Simpler is better Moving on to the acad handle. What I have found is to get the information using a line code like: (setq handle (cdr (assoc 5 (entget en)))) However, the setq variable isn't working when trying to place it into the attribute block. (defun c:test ( / area en nm pt ) (if (setq en (ssget "_:S" '((0 . "LWPOLYLINE") (70 . 1)))) (if (vl-catch-all-error-p (setq area (vl-catch-all-apply 'vlax-curve-getarea (list (ssname en 0)))) ) (princ "\nInvalid Object.") ) (setq handle (cdr (assoc 5 (entget en)))) ) (setq area (rtos (/ area 144.0) 2 2)) (if (setq block (ssget "_:S" '((0 . "INSERT")))) (progn (setq block (ssname block 0)) (LM:vl-SetAttributeValue (vlax-ename->vla-object block) "NET_SQ_FEET" area) (LM:vl-SetAttributeValue (vlax-ename->vla-object block) "ACAD_HANDLE" handle) ) ) (princ) ) (vl-load-com) (princ) ;;----------------=={ Set Attribute Value }==-----------------;; ;; ;; ;; Populates the first attribute matching the tag specified ;; ;; found within the block supplied with the value specified, ;; ;; if present. ;; ;;------------------------------------------------------------;; ;; Author: Lee Mac, Copyright © 2010 - www.lee-mac.com ;; ;;------------------------------------------------------------;; ;; Arguments: ;; ;; block - VLA Block Reference Object ;; ;; tag - Attribute TagString ;; ;; value - Value to which the Attribute will be set ;; ;;------------------------------------------------------------;; ;; Returns: Value the attribute was set to, else nil ;; ;;------------------------------------------------------------;; (defun LM:vl-SetAttributeValue ( block tag value ) (setq tag (strcase tag)) (vl-some (function (lambda ( attrib ) (if (eq tag (strcase (vla-get-TagString attrib))) (progn (vla-put-TextString attrib value) value ) ) ) ) (vlax-invoke block 'GetAttributes) ) ) Quote
MSasu Posted April 21, 2012 Posted April 21, 2012 Please take care that en variable is storing a selection set, not an entity; also to enclose more than one statement in an IF test, check the use of PROGN. (if (setq en (ssget "_:S" '((0 . "LWPOLYLINE") (70 . 1)))) [color=red] (progn (setq thePline (ssname en 0))[/color] (if (vl-catch-all-error-p (setq area (vl-catch-all-apply 'vlax-curve-getarea (list [color=red]thePline[/color]))) ) (princ "\nInvalid Object.") ) (setq handle (cdr (assoc 5 (entget [color=red]thePline[/color])))) [color=red] ) ;< PROGN[/color] ) Quote
Ohnoto Posted April 21, 2012 Author Posted April 21, 2012 Awesome! Thank you for your assistance. This is setup just how I need it. Quote
MSasu Posted April 21, 2012 Posted April 21, 2012 Sound that you have finished your code, that's very good. Glad I could help you! You're entirely welcomed! Quote
Lee Mac Posted April 21, 2012 Posted April 21, 2012 I'm pleased that you are able to make use of my functions Ohnoto For this particular task, you may want to consider using my 'Set Attribute Values' function, which could be called in the following way: (LM:vl-SetAttributeValues (vlax-ename->vla-object block) (list (cons "NET_SQ_FEET" area) (cons "ACAD_HANDLE" handle))) @Mircea: some very detailed and informative advice, well done Quote
GP_ Posted April 22, 2012 Posted April 22, 2012 '((0 . "LWPOLYLINE") (70 . 1)) Perhaps it is better to use Vlax-curve-isClosed, or consider Plinegen. Quote
MSasu Posted April 22, 2012 Posted April 22, 2012 I will appreciate if you can detail how that function will improve the selection process. Second, the PLINEGEN system variable had nothing to do with OP’s task - select closed polylines. Quote
Lee Mac Posted April 22, 2012 Posted April 22, 2012 Second, the PLINEGEN system variable had nothing to do with OP’s task - select closed polylines. Consider the case in which a Closed LWPolyline has Linetype Generation set to ON '((0 . "LWPOLYLINE") (-4 . "&=") (70 . 1)) Quote
MSasu Posted April 23, 2012 Posted April 23, 2012 You are right; I understand now the issue; that may come also from overriding the system variable in Properties or by PEDIT command. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.