Starting in December, we will archive content from the community that is 10 years and older. This FAQ provides more information.
I found this Lisp at www.cadtutor.net
https://www.cadtutor.net/forum/topic/66001-move-objects-specific-distance/
(defun c:up50 (/ ss)
(if (setq ss (ssget "_:L-I"))
(command "_.MOVE" ss "" "_non" '(0. 0.) "_non" '(0. 5000.))
)
(princ)
)
Is there any way to upgrade this lisp with the following features:
Step 1. Type the command: move/copy in X or Y direction
For example:
- Move in X direction: Move_X
- Move in Y direction: Move_Y
- Copy in X direction: Copy_X
- Copy in Y direction: Copy_Y
Step 2. Type the distance to move/copy (mm) and enter or enter to skip with default distance is 1000mm).
Step 3. Select objects -> enter to execute.
Step 4. When repeat the command, the distance entered in step 2 will be replaced the default distance (1000mm) for the next steps.
Solved! Go to Solution.
Solved by Kent1Cooper. Go to Solution.
Solved by Sea-Haven. Go to Solution.
Solved by paullimapa. Go to Solution.
Try this written like 30 years ago.
(defun C:CHX ()
(SETVAR "CMDECHO" 0)
(setq sn (getvar "osmode"))
(command "osnap" "near")
(setq x 0)
(princ "\nalters object in X direction")
(setq ht (getstring "\n What is amount of change: "))
(setq newht (strcat ht ",0"))
(while (= x 0)
(setq newobj (entsel "\nPoint to object: "))
(if (/= newobj nil)
(progn
(command "move" newobj "" "0,0" newht)
))
(if (= newobj nil)(setq x 1))
)
)
;
(defun C:CHY ()
(SETVAR "CMDECHO" 0)
(setq sn (getvar "osmode"))
(command "osnap" "near")
(setq x 0)
(princ "alters object in Y direction")
(setq ht (getstring "\n What is amount of change: "))
(setq newht (strcat "0," ht))
(while (= x 0)
(SETQ NEWobj (entsel "\nPoint to object: "))
(if (/= newobj nil)
(progn
(command "move" newobj "" "0,0" newht)
))
(if (= newobj nil)(setq x 1))
)
)
Thanks Sea-Haven,
Is there a way to modify this lisp so that the "Point to object" section becomes "Select objects" (Drag to select multiple objects at the same time). And add copy function instead of just move.
Thank for your code @Sea-Haven.
I use AI to modify your code to create the lisp which I need and share it with anyone who needs it as below.
But if anyone has any other and more optimal ideas, please still share them with us
;;;; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/move-or-copy-objects-in-the-x-or-y-direction-with-a-specific/td-p/12690641
(defun C:CHY ( / sn ht newobj)
(SETVAR "CMDECHO" 0)
(setq sn (getvar "osmode"))
(command "osnap" "near")
(princ "alters object in Y direction")
(setq ht (getstring "\n What is the amount of change: "))
(setq newht (strcat "0," ht))
(while (setq newobj (ssget '((0 . "*")))) ; Select objects
(command "copy" newobj "" "0,0" newht) ; Copy objects
)
(setvar 'osmode sn)
(princ)
)
(defun C:CHX ( / sn ht newobj)
(SETVAR "CMDECHO" 0)
(setq sn (getvar "osmode"))
(command "osnap" "near")
(princ "\nalters object in X direction")
(setq ht (getstring "\n What is the amount of change: "))
(setq newht (strcat ht ",0"))
(while (setq newobj (ssget '((0 . "*")))) ; Select objects
(command "copy" newobj "" "0,0" newht) ; Copy objects
)
(setvar 'osmode sn)
(princ)
)
(defun C:MHY ( / sn ht newobj)
(SETVAR "CMDECHO" 0)
(setq sn (getvar "osmode"))
(command "osnap" "near")
(princ "alters object in Y direction")
(setq ht (getstring "\n What is the amount of change: "))
(setq newht (strcat "0," ht))
(while (setq newobj (ssget '((0 . "*")))) ; Select objects
(command "move" newobj "" "0,0" newht) ; Move objects
)
(setvar 'osmode sn)
(princ)
)
(defun C:MHX ( / sn ht newobj)
(SETVAR "CMDECHO" 0)
(setq sn (getvar "osmode"))
(command "osnap" "near")
(princ "\nalters object in X direction")
(setq ht (getstring "\n What is the amount of change: "))
(setq newht (strcat ht ",0"))
(while (setq newobj (ssget '((0 . "*")))) ; Select objects
(command "move" newobj "" "0,0" newht) ; Move objects
)
(setvar 'osmode sn)
(princ)
)
Seems like you're still missing this step in your code:
Step 4. When repeat the command, the distance entered in step 2 will be replaced the default distance (1000mm) for the next steps.
Also I noticed AI chose to use this line of code for ssget:
(ssget '((0 . "*")))
Since you're not filtering out any objects but you want to select all kinds of objects, there's no need to indicate a wildcard but instead you can just use this:
(ssget)
With ORTHO on use either MOVE or COPY with the cursor locked in whatever X or Y direction you want and enter the distance. Whatever distance you enter will be the default the next time so if you're using the same distance just hit enter.
Your are right@paullimapa ,
It's okay to solve my problem for now. But it would be great if this lisp was added section at Step 4
(When repeat the command, the distance entered in step 2 will be replaced the default distance (1000mm) for the next steps).
Setup a global variable and include this in the statement to enter the new change value...
Here's the changed code on one of the routines...you should be able to implement on the others:
(defun C:CHY ( / sn ht newobj)
(SETVAR "CMDECHO" 0)
(setq sn (getvar "osmode"))
(command "osnap" "near")
(princ "alters object in Y direction")
; (setq ht (getstring "\n What is the amount of change: "))
; (setq newht (strcat "0," ht))
(if(not *ht*)(setq *ht* 1000)) ; setup global variable
(setq ht (getdist (strcat"\nWhat is the amount of change <" (rtos *ht* 2 0) ">: "))) ; getdist can enter & point distance on screen
(if(not ht)(setq ht *ht*)(setq ht (fix ht) *ht* ht)) ; 0 decimal precision
(setq newht (strcat "0," (itoa ht))) ; convert integer to string
(while (setq newobj (ssget)) ; Select objects
(command "copy" newobj "" "0,0" newht) ; Copy objects
)
(setvar 'osmode sn)
(princ)
)
My take on task with updated input dcl entry.
(defun C:CHY ( / sn newobj)
(SETVAR "CMDECHO" 0)
(setq sn (getvar "osmode"))
(setvar 'osmode 512)
(if (not AH:getvalsm)(load "Multi Getvals.lsp"))
(if (not *ht*)(setq *ht* 1000.0))
(setq *ht* (atof (car (AH:getvalsm (list "Enter value " "Y dist " 7 6 (rtos *ht* 2 1))))))
(princ "\nPress Enter after selecting objects ")
(while (setq newobj (ssget))
(command "copy" newobj "" "0,0" (list 0 *ht*))
(princ "\nSelect objects or press Enter to exit ")
)
(setvar 'osmode sn)
(princ)
)
Thank you @Sea-Haven
I saved your code as CHY.lsp
I successfully loaded lisp CHY.lsp
But when loading the Multi GETVALS.lsp file, it gives the following error as below:
Command: CHY ; error: LOAD failed: "Multi Getvals.lsp"
APPLOAD Multi GETVALS.lsp successfully loaded.
Command: ; error: extra right paren on input
Ok I have a few copies of the program and may have pasted an incorrect one try this one. I sometimes edit to suit a particular requirement.
Here's a way to do it in which:
1. A single default distance is available in all commands -- if you want to go left by a distance you just went right, so the default is positive X, you don't need to re-enter the same distance with a preceding minus sign, but can just use the leftward command and the same default distance.
2. You don't even need to know that X values are in the left-right direction and Y in the up-down directions, nor which way is positive and which negative in each direction -- it uses [abbreviations for] Up/Down/Left/Right as directions you want to Move or Copy things.
3. They work with pre-selection [noun-verb mode] if there is one; otherwise they ask you to select objects.
4. The "heavy lifting" is spelled out only once, instead of most of it repeatedly within multiple command definitions. The different commands just feed a couple of arguments to the one sub-routine.
5. [I don't see any reason it should be restricted to whole-number values -- these accept decimals, fractions, feet-and-inches.]
(defun MorCO (MorC dir / dirs ss) ; = Move or Copy Orthogonally
(initget 2); no zero
(setq
dirs '((0.5 "up") (1.5 "down") (1 "left") (0 "right")); directions as multiples of pi
*MorCdisp* ; global variable [Move or Copy displacement, in drawing units]
(cond
( (getdist
(strcat
"\nDistance to " MorC " object(s) " (cadr (assoc dir dirs)) " <"
(rtos (cond (*MorCdisp*) (100))); in current mode/precision <--EDIT desired initial default
">: "
); strcat
); getdist
); User-entry condition
(*MorCdisp*); prior value if present, on Enter
(100); default on Enter at first use <--EDIT desired initial default
); cond
); setq
(cond
((setq ss (ssget "_:L-I")); pre-selection of object(s) not on locked Layer(s)
(sssetfirst nil); un-select [now in ss variable]
); pre-selection condition
((setq ss (ssget "_:L"))); no pre-selection -- ask User
); cond
(command (strcat "_." MorC) ss "" "_displacement" (polar '(0 0) (* pi dir) *MorCdisp*))
(prin1)
)
(defun C:MMU () (MorCO "Move" 0.5)); = Move Up
(defun C:MMD () (MorCO "Move" 1.5)); = Move Down
(defun C:MML () (MorCO "Move" 1)); = Move Left
(defun C:MMR () (MorCO "Move" 0)); = Move Right
(defun C:CCU () (MorCO "Copy" 0.5)); = Copy Up
(defun C:CCD () (MorCO "Copy" 1.5)); = Copy Down
(defun C:CCL () (MorCO "Copy" 1)); = Copy Left
(defun C:CCR () (MorCO "Copy" 0)); = Copy Right
I used command names with double M's or C's before the directional letters, because ML is already AutoCAD's default command alias for MLINE, and I use CL and CR for other things. But you can use whatever command names make sense for you.
Thank you for your very detailed explanation.
I tried your new lisp above. It does not keep the last distance entered previously corresponding to each command but uses the last distance entered by the user enter as previous code you shared which use with Multi GETVALS.lsp
Can't find what you're looking for? Ask the community or share your knowledge.