LT2024 Autolisp Help (is this possible?)

LT2024 Autolisp Help (is this possible?)

malcolmi
Contributor Contributor
1,084 Views
19 Replies
Message 1 of 20

LT2024 Autolisp Help (is this possible?)

malcolmi
Contributor
Contributor

Hi don't know anything about autolisp, so before i start trying to learn it, can i achieve the follow with one:-

 

(we use a block with a text attribute, which has the following info "product code/product length", to measure lengths of cable, normally this is edited manually after we read the total length of a polyline representing that cable product)

 

is there a way i can write a command that would do the following

1. place the block at cursor click (assume i would have a block set for each different product code)

2. select object > length > Round up > +1000mm (select the polyline the above block relates too)

3. pass the final length back to the block in the text attribute

 

typically we have 100+ of these cable products on a layout, so being able to place the product block and simply clicking on the relevant polyline to automate the measuring would be amazing

 

Is this achievable with autolisp, or is there no way for it to pass the rounded field to the block attribute?

 

Cheers

 

 

 

[ The subject line of this post has been edited for clarity by @pendean Original: Autolisp Help (is this possible?)]

0 Likes
1,085 Views
19 Replies
Replies (19)
Message 2 of 20

johnyDFFXO
Advocate
Advocate

There is no round-up function for the fields. But you can use a trick to add 0.49999... then round it regularly.

So yes. If you post a dwg with examples, it could be an easy task.

 

The question is - do you really need/want to place the block manually or would be possible to automate that process too (say place it in the middle of pline).

0 Likes
Message 3 of 20

malcolmi
Contributor
Contributor

Manual placement would be best, as its part of a HL electrical schematic the block needs to be placed so it doesn't obstruct any other text or info shown on our customers drawings.

 

I've attached an example dwg, the red spurs show the two services that are on the same circuit, along with the polyline and the block (which is set at .../05, meaning 5m long)

 

if i can round with the field expression, can the program set the measurement conversion factor to 0.001 (turning the mm to m) and then +1?

 

There is another step to this where i would like to the limit the finial measurements to the following ranges 1-10,12,15 & 20m, but i'm sure this is far to complex to code?

 

Cheers

0 Likes
Message 4 of 20

johnyDFFXO
Advocate
Advocate

There is another step to this where i would like to the limit the finial measurements to the following ranges 1-10,12,15 & 20m, but i'm sure this is far to complex to code?

 

Doable but not with dynamic fields. Just a regular text, the same as you have.

0 Likes
Message 5 of 20

Sea-Haven
Mentor
Mentor

Not sure what LT supports so try this as a start.

 

(setq obj (vlax-ename->vla-object (car  (entsel "Pick pline "))))
(setq len (rtos (+ 1.499999(/ (vlax-get obj 'length) 1000.0)) 2 0))

This should return "5" then can add the "0" for less than 10 etc. Just copy and paste 1 line at a time to command line.

 

Let us know

0 Likes
Message 6 of 20

Moshe-A
Mentor
Mentor

@malcolmi  hi,

 

Check CABTAG (Cable Tag) command.

 

before creating lsp file from it, please do me a favor 😀 

1. give your working block a meaningful name "test" is bad practice, rename it to cabtag.

2. you are working in mm units - yes?! your test block is built in inches, change it to mm.

3. if a block need to have two pieces of data, use two attributes in this case product code & cable length (instead of combining them in one)

 

Attached your dwg fixed so you can test the lisp on. without these changes the lisp will not work on yours.

 

enjoy

Moshe

 

 

(vl-load-com) ; load activex support

; insert cable tag
(defun c:cabtag (/ get_cable_length _grade format_length ; local functions
		   savAttdia savAttreq pick ename elist)

 (defun get_cable_length (/ len)
  (setq len (+ (vlax-curve-getDistAtParam ename (vlax-curve-getEndParam ename)) 1e3))
  (1+ (* (- len (rem len 1e3)) 1e-3))
 )

 ; anonymous function 
 (setq _grade (lambda (L) (vl-some (function (lambda (n0 n1) (cond ((> L n0) n0) ((and (<= L n0) (> g n1)) n0)))) '(20 15 12 10) '(15 12 10 9))))
  
 (defun format_length (/ len)
  (setq len (get_cable_length))

  (cond
   ((<= len 9)
    (strcat "0" (rtos len 2 0))
   ); case
   (t
    (rtos (_grade len) 2 0)
   ); case
  ); cond
 ); format_length

 ; here start c:cabtag 
 (setvar "cmdecho" 0)
 (command "._undo" "_begin") 
 (setq savAttdia (getvar "attdia"))
 (setq savAttreq (getvar "attreq"))

 (setvar "attdia" 0)
 (setvar "attreq" 1)
  
 (if (and
       (setq pick (entsel "\nPick cable: "))
       (setq ename (car pick))
       (wcmatch (strcase (cdr (assoc '0 (entget ename)))) "POLYLINE,LWPOLYLINE")
     )
  (progn
   (setvar "cmdecho" 1) 
   (command "._-insert" "cabtag" "_scale" 1 pause pause "HLNNNN" (format_length))
   (setvar "cmdecho" 0) 
  ); progn
 ); if

 (setvar "attreq" savAttreq)
 (setvar "attdia" savAttdia)

 (command "._undo" "_end")
 (setvar "cmdecho" 1)
   
 (princ)
); c:cabtag

 

 

 

 

 

 

 

 

 

 

Message 7 of 20

malcolmi
Contributor
Contributor

this is amazing thank you, work very well, just trying to understand all the code
thank you for this!!

0 Likes
Message 8 of 20

malcolmi
Contributor
Contributor

so i've managed to alter this so i now have two lsp's, which are the common product on most of our projects

there are some more features i'd like to add to the code but not sure where to look for this

 

1. when the pline length exceeds 20m, could the length result comeback as "20+" (that way the user will know they need to manually add another product with excess length (e.g a 26m length would be a 20+6)

how would that be added?

 

0 Likes
Message 9 of 20

Moshe-A
Mentor
Mentor

@malcolmi ,

 

replace (format_length) with this new - untested 😀

 

Moshe

 

 

(defun format_length (/ len)
  (setq len (get_cable_length))

  (cond
   ((<= len 9)
    (strcat "0" (rtos len 2 0))
   ); case
   ((<= len 20)
    (rtos (_grade len) 2 0)
   )
   ( t
    (strcat (rtos (_grade len) 2 0) "+" (rtos (- len 20) 2 0))
   ); case
  ); cond
 ); format_length

 

Message 10 of 20

malcolmi
Contributor
Contributor

awesome, works like a charm

what would the code be to force the measurement into 5m increments?

0 Likes
Message 11 of 20

Moshe-A
Mentor
Mentor

@malcolmi ,

 

up to 50

 

; anonymous function 
(setq _grade (lambda (L) (vl-some (function (lambda (n0 n1) (cond ((> L n0) n0) ((and (<= L n0) (> g n1)) n0))))
'(20 15 12 10) '(15 12 10 9))))
'(50 45 40 35 30 25 20 15 10 5) '(45 40 35 30 25 20 15 10 5 0))))

 

 

Message 12 of 20

malcolmi
Contributor
Contributor

thank you for all your help, i haven't tried the code above but have been trying to add a user string for the product code, this is what i have ... it seems to work but forces the length to "NN" not sure what i've done incorrectly can you help?

 

 

(vl-load-com) ; load activex support

; insert product code
(defun c:blk (/ get_cable_length _grade format_length ; local functions
		   savAttdia savAttreq pick ename elist)

 (defun get_cable_length (/ len)
  (setq len (+ (vlax-curve-getDistAtParam ename (vlax-curve-getEndParam ename)) 1e3))
  (1+ (* (- len (rem len 1e3)) 1e-3))
 )

  ; anonymous function 
 (setq _grade (lambda (L) (vl-some (function (lambda (n0 n1) (cond ((> L n0) n0) ((and (<= L n0) (> g n1)) n0)))) '(20 15 12 10) '(15 12 10 9))))
  
 (defun format_length (/ len)
  (setq len (get_cable_length))

  (cond
   ((<= len 9)
    (strcat "0" (rtos len 2 0))
   ); case
   ((<= len 20)
    (rtos (_grade len) 2 0)
   )
   ( t
    (strcat (rtos (_grade len) 2 0) "+" )
   ); case
  ); cond
 ); format_length

(defun c:product_code ( / cod)
  (setq cod (getstring T "\nEnter Product Code: "))
)

 ; here start c:blk
 (setvar "cmdecho" 0)
 (command "._undo" "_begin") 
 (setq savAttdia (getvar "attdia"))
 (setq savAttreq (getvar "attreq"))

 (setvar "attdia" 0)
 (setvar "attreq" 1)
  
 (if (and
       (setq pick (entsel "\nPick Extender: "))
       (setq ename (car pick))
       (wcmatch (strcase (cdr (assoc '0 (entget ename)))) "POLYLINE,LWPOLYLINE")
     )
  (progn
   (setvar "cmdecho" 1) 
   (command "._-insert" "HL91004" "_scale" 1 pause "0" (product_code) (format_length))
   (setvar "cmdecho" 0) 
  ); progn
 ); if

 (setvar "attreq" savAttreq)
 (setvar "attdia" savAttdia)

 (command "._undo" "_end")
 (setvar "cmdecho" 1)
   
 (princ)
); c:blk

 

 

0 Likes
Message 13 of 20

malcolmi
Contributor
Contributor

think i have found my error, dont need the "c:" after the defun for product_code

0 Likes
Message 14 of 20

Moshe-A
Mentor
Mentor

@malcolmi ,

 

You almost getting there 😀  check the following:

 

A well structured program for user input (getting a number or a string) must be first checked for its validity 

and only than get to the real job which in our case insert the block - agree?!

cause if user supply an invalid value, you do not want to continue your program - right?!

 

 

(vl-load-com) ; load activex support

; insert cable tag
(defun c:cabtag (/ get_cable_length _grade format_length ; local functions
		   savAttdia savAttreq pick ename elist cod)

 (defun get_cable_length (/ len)
  (setq len (+ (vlax-curve-getDistAtParam ename (vlax-curve-getEndParam ename)) 1e3))
  (1+ (* (- len (rem len 1e3)) 1e-3))
 )

 ; anonymous function 
 (setq _grade (lambda (L) (vl-some (function (lambda (n0 n1) (cond ((> L n0) n0) ((and (<= L n0) (> g n1)) n0)))) '(20 15 12 10) '(15 12 10 9))))
  
;| (defun format_length (/ len)
  (setq len (get_cable_length))

  (cond
   ((<= len 9)
    (strcat "0" (rtos len 2 0))
   ); case
   (t
    (rtos (_grade len) 2 0)
   ); case
  ); cond
 ); format_length |;

  
 (defun format_length (/ len)
  (setq len (get_cable_length))

  (cond
   ((<= len 9)
    (strcat "0" (rtos len 2 0))
   ); case
   ((<= len 20)
    (rtos (_grade len) 2 0)
   )
   ( t
    (strcat (rtos (_grade len) 2 0) "+" (rtos (- len 20) 2 0))
   ); case
  ); cond
 ); format_length

  
 ; here start c:cabtag 
 (setvar "cmdecho" 0)
 (command "._undo" "_begin") 
 (setq savAttdia (getvar "attdia"))
 (setq savAttreq (getvar "attreq"))

 (setvar "attdia" 0)
 (setvar "attreq" 1)
  
 (if (and
       (setq pick (entsel "\nPick cable: "))
       (setq ename (car pick))
       (/= (setq cod (getstring "\nEnter product code: ")) "")
       (wcmatch (strcase (cdr (assoc '0 (entget ename)))) "POLYLINE,LWPOLYLINE")
     )
  (progn
   (setvar "cmdecho" 1) 
   (command "._-insert" "HL91004" "_scale" 1 pause 0 cod (format_length))
   (setvar "cmdecho" 0) 
  ); progn
 ); if

 (setvar "attreq" savAttreq)
 (setvar "attdia" savAttdia)

 (command "._undo" "_end")
 (setvar "cmdecho" 1)
   
 (princ)
); c:cabtag

 

 

0 Likes
Message 15 of 20

Sea-Haven
Mentor
Mentor

Like Moshe-A (setq cod (getstring "\nEnter product code: ")) , 1st suggestion add T 

(setq cod (getstring "\nEnter product code: " T)) this allows spaces in product code as a space can be returned in getstring as an Enter, read that today thanks Kent.

 

The other, this is you can force a user to only use preselected values for the string. You can use (initget, look up Help. For me I use a pop radio button dcl, please choose, its library code so you can use in any code, the other is as the radio button has a maximum of about 20, screen dependant, then you can use a listbox that can have way more than 20. You can daisy chain DCL's so have choose type then product code, you may have 100's of product code but grouped by type, yep no Part No Typo's.

 

Happy to provide more info. Moshe-A has you well underway.

0 Likes
Message 16 of 20

malcolmi
Contributor
Contributor

Thank you for the help

 

We use attribute extraction to get a takeoff of all the products, once a drawing is approved.  Is there away to combine the length into the Prod# attribute, so when i open the text file in excel i can subtotal all the products with their lengths?

 

I've tried subtotaling the two columns that PROD# and LENGTH creates, but it never tallies them correctly

0 Likes
Message 17 of 20

malcolmi
Contributor
Contributor

would it be something like

(command "._-insert" "HLBLANK" "_scale" 1 pause "0" (product_code "/" format_length))

??

0 Likes
Message 18 of 20

malcolmi
Contributor
Contributor

this seem to do the trick

(command "._-insert" "HLGOO" "_scale" 1 pause "0" (strcat (product_code) "/" (format_length)))

0 Likes
Message 19 of 20

malcolmi
Contributor
Contributor

on another note, i have a polyline that is 10113.9mm long, the format length calculates this as "10"
i don't understand how the format length works
it doesn't seem to be rounding up and adding 1, or forcing the "11" into a "12"
does this need tweeking?

0 Likes
Message 20 of 20

Sea-Haven
Mentor
Mentor

"subtotal all the products with their lengths" answer is yes think cost is Beer money. Done in CAD not excel. Needs to be custom programmed.

0 Likes