Преобразование единиц измерения блоков в файле
Известно, что при создании блока (ручного создания) можно указывать единицы, в которых этот блок будет вставляться: миллиметры, метры, дюймы и т.д. Это удобно, если гарантируется, что вся работа всегда выполняется на основе единственного шаблона с раз и навсегда настроенными единицами. Но бывает такое не всегда (да и за смежниками, бывает, приходится “доделывать”).
Оптимальным решением, как ни странно, будут “безразмерные” блоки. То есть те, у которых единицы – “Unitless” (в русской версии перевода не помню). С новыми блоками все понятно – достаточно контролировать это значение и стараться не допускать ошибок. А что делать со старыми, уже вставленными? Да очень просто – заменить!
Менять можно вручную, переопределяя блоки (к примеру). И этот подход более чем достаточен, если блоков 1-2. Ну, всяко не больше 10 (и то лично я уже на втором озверею). Программное решение намного более интересно.
Вариантов программы, конечно, может быть сколько угодно. Рассмотрим 2: либо обрабатывать все блоки в файле (независимо ни от чего), либо обрабатывать только указанные блоки. В набор обрабатываемых блоков может попадать несколько блоков. ТЗ составлено, приступаем к реализации.
Наиболее удобным будет применение ActiveX – код получится достаточно простым, читабельным и понятным.
;; Вызов: (lispru-change-block-units)
(defun lispru-change-block-units (/ adoc)
;; Поставим метку начала отмены. Ну так, на всякий случай
(vla-startundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object))))
;; Проходим по всем описаниям блоков документа
(vlax-for blk_def (vla-get-blocks adoc)
;; Из обработки исключаем внешние ссылки, пространства модели и листа
(if (and (equal (vla-get-islayout blk_def) :vlax-false)
(equal (vla-get-isxref blk_def) :vlax-false)
;; И дополнительно исключаем блоки таблиц и размеров
(not (wcmatch (strcase (vla-get-name blk_def)) "`*D*,`*T*"))
) ;_ end of and
(vl-catch-all-apply
(function
(lambda ()
(vla-put-units blk_def 0)
) ;_ end of lambda
) ;_ end of function
) ;_ end of vl-catch-all-apply
) ;_ end of if
) ;_ end of vlax-for
;; Теперь метка конца отмены
(vla-endundomark adoc)
;; Ну и "тихий" выход
(princ)
) ;_ end of defun
При обработке выбранных блоков код немного усложняется:
;; Вызов: (lispru-change-block-units-by-select)
(defun lispru-change-block-units-by-select (/ _dwgru-conv-pickset-to-list adoc selset blk_list name)
(defun fun_get-name (ent)
;; Получение имени блока
(cond
((vlax-property-available-p ent 'effectivename)
(vla-get-effectivename ent)
)
((vlax-property-available-p ent 'name)
(vla-get-name ent)
)
) ;_ end of cond
) ;_ end of defun
(defun _dwgru-conv-pickset-to-list (value / tab item)
;;; http://forum.dwg.ru/showpost.php?p=188342&postcount=21
(repeat (setq tab nil
item (sslength value)
) ;_ end setq
(setq tab (cons (ssname value (setq item (1- item))) tab))
) ;_ end repeat
) ;_ end defun
;; Поставим метку начала отмены. Ну так, на всякий случай
(vla-startundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object))))
;; Получаем набор блоков, обрабатывая нажатие Esc
(if (= (type (setq selset (vl-catch-all-apply
(function
(lambda ()
(ssget '((0 . "INSERT")))
) ;_ end of lambda
) ;_ end of function
) ;_ end of vl-catch-all-apply
) ;_ end of setq
) ;_ end of type
'pickset
) ;_ end of =
(progn
;; Сформируем список имен блоков, исключая дубликаты
(foreach ent
;; Преобразовываем набор в список элементов, исключая внешние ссылки.
;; Это при полностью программной обработке надо отслеживать блоки листов
;; и модели. Вручную их не выделить.
(vl-remove-if
(function
(lambda (x)
(equal (vla-get-isxref (vla-item (vla-get-blocks adoc) (vla-get-name x))) :vlax-true)
) ;_ end of lambda
) ;_ end of function
(mapcar (function vlax-ename->vla-object) (_dwgru-conv-pickset-to-list selset))
) ;_ end of vl-remove-if
(if (not (member (setq name (fun_get-name ent)) blk_list))
(setq blk_list (cons name blk_list))
) ;_ end of if
) ;_ end of foreach
;; Запускаем новый цикл
(foreach blk_def
;; Из списка имен получаем список указателей на описания блоков
(mapcar
(function
(lambda (x)
(vla-item (vla-get-blocks adoc) x)
) ;_ end of lambda
) ;_ end of function
blk_list
) ;_ end of mapcar
(vl-catch-all-apply
(function
(lambda ()
(vla-put-units blk_def 0)
) ;_ end of lambda
) ;_ end of function
) ;_ end of vl-catch-all-apply
) ;_ end of foreach
) ;_ end of progn
) ;_ end of if
;; Теперь метка конца отмены
(vla-endundomark adoc)
;; Ну и "тихий" выход
(princ)
) ;_ end of defun
У этого кода есть один, но очень серьезный недостаток: он не обрабатывает (по крайней мере на данный момент) вложенные блоки.
Конечно, будь этот код “для работы”, я бы исправил эту ошибку и попытался его ускорить (ввел бы дополнительные переменные, логику бы немного поменял – особенно в части проверки на то, является ли блок внешней ссылкой. Если надо – можно обсудить. Нет – так нет.
—
Добавлено: можно за компанию потом еще и выполнить регенерацию чертежа. По вкусу, как говорится
Материалы для проектирования, работы и разработки (и не только в AutoCAD)
В случае, если надо обрабатывать только выделяемые блоки, но с учетом вложенных, код становится чуть посложнее.
;; Вызов: (lispru-change-block-units-by-select-with-subblocks)
(defun lispru-change-block-units-by-select-with-subblocks
(/ _dwgru-conv-pickset-to-list adoc selset blk_list name)
;|
* Преобразование единиц измерения блоков, включая вложенные блоки
|;
(defun fun_get-name (ent)
;; Получение имени блока
(cond
((vlax-property-available-p ent 'effectivename)
(vla-get-effectivename ent)
)
((vlax-property-available-p ent 'name)
(vla-get-name ent)
)
) ;_ end of cond
) ;_ end of defun
(defun _dwgru-conv-pickset-to-list (value / tab item)
;;; http://forum.dwg.ru/showpost.php?p=188342&postcount=21
(repeat (setq tab nil
item (sslength value)
) ;_ end setq
(setq tab (cons (ssname value (setq item (1- item))) tab))
) ;_ end repeat
) ;_ end defun
;; Поставим метку начала отмены. Ну так, на всякий случай
(vla-startundomark
(setq adoc (vla-get-activedocument (vlax-get-acad-object)))
) ;_ end of vla-startundomark
;; Получаем набор блоков, обрабатывая нажатие Esc
(if (= (type (setq selset (vl-catch-all-apply
(function
(lambda ()
(ssget '((0 . "INSERT")))
) ;_ end of lambda
) ;_ end of function
) ;_ end of vl-catch-all-apply
) ;_ end of setq
) ;_ end of type
'pickset
) ;_ end of =
(progn
;; Сформируем список имен блоков, исключая дубликаты
;; И не забываем про вложенные блоки
(foreach ent
;; Преобразовываем набор в список элементов, исключая внешние ссылки.
((lambda (/ item lst)
(foreach item
(apply
(function append)
(mapcar
(function
(lambda (x / res)
;; применяем эту функцию
(setq res (list x))
(vlax-for item x
(if
(wcmatch
(strcase
(vla-get-objectname item)
) ;_ end of strcase
"*BLOCK*"
) ;_ end of wcmatch
(setq res (cons item res))
) ;_ end of if
) ;_ end of vlax-for
res
) ;_ end of lambda
) ;_ end of function
;; begin : удаление внешних ссылок
(vl-remove-if
(function
(lambda (x)
(equal
(vla-get-isxref
(vla-get-name x)
) ;_ end of vla-get-isxref
:vlax-true
) ;_ end of equal
) ;_ end of lambda
) ;_ end of function
(mapcar
(function
(lambda (x)
(vla-item
(vla-get-blocks adoc)
(fun_get-name
(vlax-ename->vla-object x)
) ;_ end of fun_get-name
) ;_ end of vla-item
) ;_ end of lambda
) ;_ end of function
(_dwgru-conv-pickset-to-list selset)
) ;_ end of mapcar
) ;_ end of vl-remove-if
;; end : удаление внешних ссылок
) ;_ end of mapcar
) ;_ end of apply
(if (not (member (fun_get-name item)) lst)
(setq lst (cons item lst))
) ;_ end of if
) ;_ end of foreach
lst
) ;_ end of lambda
) ;_ end of foreach
(if (not (member (setq name (fun_get-name ent)) blk_list))
(setq blk_list (cons name blk_list))
) ;_ end of if
) ;_ end of foreach
;; Запускаем новый цикл
(foreach blk_def
;; Из списка имен получаем список указателей на описания блоков
(mapcar
(function
(lambda (x)
(vla-item (vla-get-blocks adoc) x)
) ;_ end of lambda
) ;_ end of function
blk_list
) ;_ end of mapcar
(vl-catch-all-apply
(function
(lambda ()
(vla-put-units blk_def 0)
) ;_ end of lambda
) ;_ end of function
) ;_ end of vl-catch-all-apply
) ;_ end of foreach
) ;_ end of progn
) ;_ end of if
;; Теперь метка конца отмены
(vla-endundomark adoc)
;; Ну и "тихий" выход
(princ)
) ;_ end of defun
Код не комментирую (хотя по-хорошему надо бы, я там немного логику поменял). Надо будет – обращайтесь