Here's my take on it:
(vl-load-com)
(defun C:ENDS (/ ss n ent len)
(initget (if *endslen* 6 7)); no zero, no negative, no Enter on first use
(setq *endslen* ; global variable
(cond
( (getdist ; User input
(strcat
"\nLength of end portions to retain"
(if *endslen* (strcat " <" (rtos *endslen*) ">") "")
": "
); strcat
); getdist
); User input condition
(*endslen*); on Enter [when allowed]: previous value
); cond
); setq
(if (setq ss (ssget '((0 . "*LINE,ARC,CIRCLE,ELLIPSE"))))
(repeat (setq n (sslength ss))
(setq ent (ssname ss (setq n (1- n))))
(if
(and
(not (wcmatch (cdr (assoc 0 (entget ent))) "XLINE,MLINE"))
;; [inapplicable types accepted by *LINE in (ssget)]
(>= ; long enough
(setq len (vlax-curve-getDistAtParam ent (vlax-curve-getEndParam ent)))
(* *endslen* 2)
); >=
); and
(command "_.break" ent ; giving only entity name goes into First mode
"_none" (vlax-curve-getPointAtDist ent *endslen*)
"_none" (vlax-curve-getPointAtDist ent (- len *endslen*))
); command
); if
); repeat
); if
(princ)
); defun
It works on Lines, Arcs, Circles, Ellipses, Splines, and 2D or 3D lightweight or heavy Polylines. In the case of Circles and closed LWPolylines or Splines, the result is accurately the two ends of the desired length, but in a single Arc/Polyline/Spline twice the specified end length, centered around the original's start/end point. [Closed "heavy" 2D and 3D Polylines end up as separate end pieces, as with open-ended objects, touching at the original's start/end point.]
It remembers your end distance and offers it as default on subsequent use.
It could have Undo begin/end wrapping added, if desired, and if so, *error* handling to do the Undo end part in the event of a cancellation or error.
Kent Cooper, AIA