Практика

AutoLISP для проектировщика

Минимум синтаксиса. Максимум полезных сценариев.

Это не курс программирования: каждый урок — одна практическая задача, короткий готовый код и упражнение «поменяй строку — увидь результат». Несколько уроков — и вы берёте чужой LISP, понимаете, что в нём менять, и пользуетесь. Работает в AutoCAD (в AutoCAD LT — с версии LT 2024).

Старт — Первая команда и обращение с .lsp

Выбор объектов — Один объект, набор, фильтр по имени

Слои — Перенести и погасить без ручной возни

Блоки и атрибуты — Читать и менять маркировку

Массовые операции — Счёт и нумерация десятков блоков

Рецепты — готовый код без урока

Маленькие проверенные заготовки: скопируйте, при желании поменяйте пару строк — и в работу. Запуск у всех одинаковый: сохраните код в файл с расширением .lsp (кодировка ANSI), загрузите через ЗАГПРИЛ (APPLOAD) или перетащите файл в окно чертежа, затем введите имя команды из заголовка рецепта.

Выбрать блоки по имени (с маской)НАЙТИ

Спрашивает имя блока (можно маску вроде ИП*) и подсвечивает все вхождения по чертежу с подсчётом.

(defun c:НАЙТИ (/ nm ss)  (setq nm (getstring "\nИмя блока (можно маску, например ИП*): "))  (setq ss (ssget "_X" (list '(0 . "INSERT") (cons 2 nm))))  (if ss    (progn      (sssetfirst nil ss)      (princ (strcat "\nНайдено: " (itoa (sslength ss))))    )    (princ "\nТаких блоков нет.")  )  (princ))

Что поменять под себя

  • Нужен ещё и фильтр по слою — добавьте в list пару (cons 8 "ИмяСлоя").
  • Хотите выбирать область рамкой, а не весь чертёж — уберите "_X": (ssget (list …)).
Перенести выбранное на слойНАСЛОЙ

Спрашивает имя слоя, проверяет, что он существует, и переносит на него все выбранные объекты.

(defun c:НАСЛОЙ (/ nm ss i e d)  (setq nm (getstring T "\nНа какой слой: "))  (if (tblsearch "LAYER" nm)    (progn      (setq ss (ssget))      (if ss        (progn          (setq i 0)          (repeat (sslength ss)            (setq e (ssname ss i)                  d (entget e))            (entmod (subst (cons 8 nm) (assoc 8 d) d))            (setq i (1+ i))          )          (princ (strcat "\nПеренесено: " (itoa (sslength ss))))        )      )    )    (princ "\nТакого слоя нет в чертеже.")  )  (princ))

Что поменять под себя

  • tblsearch — проверка «слой существует»; уберёте её — entmod молча отклонит перенос на несуществующий слой.
  • Зашить слой намертво: замените запрос на (setq nm "СС_СПС").
Добавить префикс к атрибутуПРЕФИКС

Спрашивает тег атрибута и префикс, затем дописывает префикс к значению этого атрибута во всех выбранных блоках.

(defun c:ПРЕФИКС (/ tg pf ss i e a d)  (setq tg (strcase (getstring "\nТег атрибута (например МАРК): ")))  (setq pf (getstring T "\nПрефикс: "))  (setq ss (ssget '((0 . "INSERT"))))  (if ss    (progn      (setq i 0)      (repeat (sslength ss)        (setq e (ssname ss i)              a (entnext e))        (while (and a (= "ATTRIB" (cdr (assoc 0 (setq d (entget a))))))          (if (= tg (strcase (cdr (assoc 2 d))))            (progn              (entmod (subst (cons 1 (strcat pf (cdr (assoc 1 d))))                             (assoc 1 d) d))              (entupd a)            )          )          (setq a (entnext a))        )        (setq i (1+ i))      )    )  )  (princ))

Что поменять под себя

  • Замена значения целиком вместо префикса: (cons 1 pf) вместо (cons 1 (strcat pf …)).
  • Суффикс вместо префикса: поменяйте аргументы strcat местами.
Найти блоки с пустым атрибутомПУСТЫЕ

Спрашивает тег и подсвечивает блоки, у которых этот атрибут не заполнен, — быстрая проверка маркировки перед выпуском.

(defun c:ПУСТЫЕ (/ tg ss out i e a d)  (setq tg (strcase (getstring "\nТег атрибута (например МАРК): ")))  (setq ss (ssget "_X" '((0 . "INSERT"))))  (setq out (ssadd))  (if ss    (progn      (setq i 0)      (repeat (sslength ss)        (setq e (ssname ss i)              a (entnext e))        (while (and a (= "ATTRIB" (cdr (assoc 0 (setq d (entget a))))))          (if (and (= tg (strcase (cdr (assoc 2 d))))                   (= "" (cdr (assoc 1 d))))            (ssadd e out)          )          (setq a (entnext a))        )        (setq i (1+ i))      )      (sssetfirst nil out)      (princ (strcat "\nБлоков с пустым " tg ": " (itoa (sslength out))))    )  )  (princ))

Что поменять под себя

  • Искать не пустые, а конкретное значение: замените (= "" …) на (= "СТАРОЕ" …).
  • Ограничить проверку слоем: добавьте в фильтр ssget пару (8 . "ИмяСлоя").
Погасить слои по маскеПОГАСИ

Спрашивает маску (например СС_*) и отключает все подходящие слои; парная команда включает их обратно.

(defun c:ПОГАСИ (/ m)  (setq m (getstring "\nМаска слоёв (например СС_*): "))  (command "_.-LAYER" "_OFF" m "")  (princ))(defun c:ЗАЖГИ (/ m)  (setq m (getstring "\nМаска слоёв: "))  (command "_.-LAYER" "_ON" m "")  (princ))

Что поменять под себя

  • Заморозка вместо отключения: "_Freeze" и "_Thaw" вместо "_OFF" и "_ON".
  • Перед гашением переключитесь на нейтральный текущий слой — иначе AutoCAD задаст уточняющий вопрос про текущий.
Посчитать блоки по именамСЧЕТБЛОК

Группирует выбранные блоки по именам и печатает мини-спецификацию: «имя — количество».

(defun c:СЧЕТБЛОК (/ ss i e nm lst p)  (setq ss (ssget '((0 . "INSERT"))))  (if ss    (progn      (setq i 0 lst nil)      (repeat (sslength ss)        (setq e (ssname ss i)              nm (cdr (assoc 2 (entget e)))              p (assoc nm lst))        (setq lst (if p                    (subst (cons nm (1+ (cdr p))) p lst)                    (cons (cons nm 1) lst)))        (setq i (1+ i))      )      (foreach x lst        (princ (strcat "\n" (car x) " — " (itoa (cdr x)) " шт.")))    )  )  (princ))

Что поменять под себя

  • Считать по всему чертежу без выбора: (ssget "_X" '((0 . "INSERT"))).
  • Числа нужны в таблице, а не в строке — тот же подсчёт по DXF делает наш онлайн-инструмент «Спецификация с плана».

Примеры используют базовый AutoLISP, одинаковый во всех актуальных версиях AutoCAD; перед применением на рабочих чертежах пробуйте команды на копии файла. AutoCAD и AutoLISP — продукты Autodesk; этот раздел — независимые учебные материалы сервиса. Прогресс хранится в вашем браузере и никуда не отправляется.