(vl-load-com)
(defun c:FOO (/ *error* acDoc ss pt y item data blocks)
(defun *error* (msg)
(if ss (vla-delete ss))
(if acDoc (vla-endundomark acDoc))
(cond ((not msg)) ; Normal exit
((member msg '("Function cancelled" "quit / exit abort"))) ; <esc> or (quit)
((princ (strcat "\n** Error: " msg " ** "))) ; Fatal error, display it
)
(princ)
)
(if
(and
(ssget "_:L" '((0 . "INSERT")))
(setq d (getreal "\nEnter Block distance: "))
)
(progn
(vla-startundomark
(setq acDoc (vla-get-activedocument (vlax-get-acad-object)))
)
(vlax-for x (setq ss (vla-get-activeselectionset acDoc))
(setq pt (vlax-get x 'insertionpoint))
(if (setq item (assoc (setq y (cadr pt)) data))
(setq data
(subst (cons (car item) (append (cdr item) (list x))) item data)
)
(setq data (cons (cons y (list x)) data))
)
)
(if data
(foreach item data
(setq blocks
(vl-sort
(cdr item)
(function
(lambda (a b)
(< (car (vlax-get a 'insertionpoint))
(car (vlax-get b 'insertionpoint))
)
)
)
)
)
(setq pt (vlax-get (car blocks) 'insertionpoint))
(foreach block (cdr blocks)
(vla-move
block
(vlax-3d-point (vlax-get block 'insertionpoint))
(vlax-3d-point (setq pt (polar pt 0.0 d)))
)
)
)
)
)
)
(*error* nil)
)
This works for each group of Blocks at a given Y level, based on the lowest X position in a given row as starting point.