Очистка файлов от ненужных данных LineStyle DGN в AutoCAD.

Автор Тема: Очистка файлов от ненужных данных LineStyle DGN в AutoCAD.  (Прочитано 133004 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Подшиваленко Дмитрий

  • ADN Club
  • **
  • Сообщений: 64
  • Карма: 0
Насчет "используемые-неиспользуемые": не уверен, что это легко реализуемо. Можно попытаться, конечно, удалять объект, и, если это удалось, тут же его восстанавливать - но мне такой подход не нравится на интуитивном уровне.
А если так:
Сохранить копию словаря, удалять объекты, посчитать количество удалённых элементов и восстановить словарь из копии?

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
"Сохранить копию" - куда? Можно, конечно, скопировать текущий документ в %temp%, открыть его через ObjetDBX, поудалять лишнее, получить результаты и закрыть - но отчет будет не для текущего состояния, а для последнего сохранения. Т.е. тоже "не фонтан".
С именем словаря попробую поиграться, но не сию секунду - просто работы как-то многовато навалили :(
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Подшиваленко Дмитрий

  • ADN Club
  • **
  • Сообщений: 64
  • Карма: 0
"Сохранить копию" - куда?
Создать пользовательский словарь и туда... А потом обратно и удалить пользовательский словарь. Прошу сильно не пинать за идею...

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
По-быстрому, без особых проверок:
Код - Auto/Visual Lisp [Выбрать]
  1. (vl-load-com)
  2.  
  3. (defun check-dict (doc name value / dict)
  4.                   ;|
  5. doc   - указатель на обрабатываемый документ. nil -> текущий
  6. name  - имя словаря. Не может быть пустым. Регистронезависимо.
  7. value - максимально допустимое значение, до которого не выводится никакое сообщение.
  8.         nil -> принимается равным 100
  9.  
  10. Примеры вызова:
  11. (check-dict nil "acad_dgnlinestylecomp" nil)
  12. (check-dict nil "
  13. |;
  14.   (if name
  15.     (progn (if (not doc)
  16.              (setq doc (vla-get-activedocument (vlax-get-acad-object)))
  17.              ) ;_ end of if
  18.            (if (not value)
  19.              (setq value 100)
  20.              ) ;_ end of if
  21.            (if (and (= (type
  22.                          (setq dict (vl-catch-all-apply (function (lambda () (vla-item (vla-get-dictionaries doc) name)))))
  23.                          ) ;_ end of type
  24.                        'vla-object
  25.                        ) ;_ end of =
  26.                     (> (vla-get-count dict) value)
  27.                     ) ;_ end of and
  28.              (alert
  29.                (strcat "Обнаружен словарь " name ", количество записей " (vl-princ-to-string (vla-get-count dict)))
  30.                ) ;_ end of alert
  31.              ) ;_ end of if
  32.            ) ;_ end of progn
  33.     (alert (strcat "\n** Error ** : не передано имя обрабатываемого словаря"))
  34.     ) ;_ end of if
  35.   (princ)
  36.   ) ;_ end of defun

В предоставленном файле буду обрабатываться только словари следующих наименований:
"ACAD_CIP_PREVIOUS_PRODUCT_INFO" "ACAD_COLOR" "ACAD_DETAILVIEWSTYLE" "ACAD_DGNLINESTYLECOMP" "ACAD_IMAGE_DICT" "ACAD_MLEADERSTYLE" "ACAD_MLINESTYLE" "ACAD_PLOTSTYLENAME" "ACAD_SCALELIST" "ACAD_SECTIONVIEWSTYLE" "ACAD_TABLESTYLE" "ACAD_VISUALSTYLE" "AEC_CLASSIFICATION_SYSTEM_DEFS" "AEC_PROPERTY_SET_DEFS" "ASE_INDEX_DICTIONARY" "AcDbVariableDictionary" "AcStStandard" "AcadDim" "BNS_VARIABLES"

На самом деле в файле могут быть словари, которые моим кодом обрабатываться не будут (в частности, ACAD_VARIABLES - был такой словарь, если не ошибаюсь).

Код для получения имен всех словарей, которые можно поставить в check-dict:
Код - Auto/Visual Lisp [Выбрать]
  1. (defun get-all-dict-names ()
  2.   (vl-sort (vl-remove nil
  3.                       (mapcar (function (lambda (x)
  4.                                           (if (vlax-property-available-p x 'name)
  5.                                             (vla-get-name x)
  6.                                             ) ;_ end of if
  7.                                           ) ;_ end of lambda
  8.                                         ) ;_ end of function
  9.                               ((lambda (/ lst)
  10.                                  (vlax-for item (vla-get-dictionaries (vla-get-activedocument (vlax-get-acad-object)))
  11.                                    (setq lst (cons item lst))
  12.                                    ) ;_ end of vlax-for
  13.                                  lst
  14.                                  ) ;_ end of LAMBDA
  15.                                )
  16.                               a
  17.                               ) ;_ end of mapcar
  18.                       ) ;_ end of vl-remove
  19.            '<
  20.            ) ;_ end of vl-sort
  21.   ) ;_ end of defun
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Подшиваленко Дмитрий

  • ADN Club
  • **
  • Сообщений: 64
  • Карма: 0
Алексей, очень извиняюсь, но можно ещё немного отвлеку тебя от работы.
В оригинале идея выглядела так:
"Можно сделать эту функцию универсальной, передавать ей имя словаря, а она будет возвращать количество записей и уже вне функции сравнивать количество записей словаря с адекватным количеством и выдавать alert?"
То есть проверку количества записей вынести вне функции, чтобы я со своим минимальным знанием лиспа мог выполнять какие-то другие действия при превышении адекватного количества записей (диалоговое окно вместо alert, или очистка).
Конструкция вроде:
Код - Auto/Visual Lisp [Выбрать]
  1. (check-dict nil "acad_dgnlinestylecomp" val)
  2. (if (> val 100) ; Если количество больше 100
  3.  (alert (strcat "Этот чертёж содержит "(itoa val)" объектов DGN! "))
  4. )
« Последнее редактирование: 27-04-2016, 12:31:08 от Подшиваленко Дмитрий »

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Так, минуту. Можно сделать так, что на выходе будет список из точечных пар: ИмяСловаря - КоличествоЗаписей. И потом его анализировать. Основная проблема - соответствие имени словаря и "вменяемого" (для человека) названия. Подумаю, что и как можно сделать. Надо примерно часа два - у меня тут совещание нарисовывается :(
Пока есть время, задам еще вопрос: а "критическое количество записей" для каждого словаря надо делать отдельным или нет? И, если да, то где и как брать соответствия?
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Подшиваленко Дмитрий

  • ADN Club
  • **
  • Сообщений: 64
  • Карма: 0
Да я вроде не прошу так сложно. Достаточно того, что я передам функции имя словаря, будь то "acad_dgnlinestylecomp" или "ACAD_SCALELIST", а она мне вернёт количество записей этого словаря. Проверку внутри функции нужно убрать.
"Критическое количество записей"  для каждого словаря уже будет определяться мной вне этой функции.
Идея в том, чтобы просто иметь универсальную функцию, которая просто бы считала количество записей передаваемого ей словаря и возвращала это значение, а уже вне функции пишется обработка в стиле "Если количество записей больше чего-то, то сделать то-то"
« Последнее редактирование: 27-04-2016, 13:54:11 от Подшиваленко Дмитрий »

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Как вариант:
Код - Auto/Visual Lisp [Выбрать]
  1. (vl-load-com)
  2.  
  3. (defun check-dict (doc)
  4.   (mapcar (function (lambda (x)
  5.                       (cons (vla-get-name x)
  6.                             (if (vlax-property-available-p x 'count)
  7.                               (vla-get-count x)
  8.                               -1
  9.                               ) ;_ end of if
  10.                             ) ;_ end of cons
  11.                       ) ;_ end of lambda
  12.                     ) ;_ end of function
  13.           (vl-remove-if-not
  14.             (function (lambda (x) (vlax-property-available-p x 'name)))
  15.             ((lambda (/ lst)
  16.                (vlax-for item (vla-get-dictionaries
  17.                                 (cond (doc)
  18.                                       (t (vla-get-activedocument (vlax-get-acad-object)))
  19.                                       ) ;_ end of cond
  20.                                 ) ;_ end of vla-get-dictionaries
  21.                  (setq lst (cons item lst))
  22.                  ) ;_ end of vlax-for
  23.                lst
  24.                ) ;_ end of lambda
  25.              )
  26.             ) ;_ end of vl-remove-if-not
  27.           ) ;_ end of mapcar
  28.   ) ;_ end of defun

doc - указатель на обрабатываемый документ (nil - текущий). Возвращает список из точечных пар  '("ИмяСловаря" . КоличествоЗаписей)
Если количество записей получить невозможно, то в КоличествоЗаписей показывается -1.

Конкретно для предоставленного файла результат:
Код - Auto/Visual Lisp [Выбрать]
  1. _$ (check-dict nil)
  2. '(("BNS_VARIABLES" . 4)
  3.   ("ASE_INDEX_DICTIONARY" . 1)
  4.   ("AEC_PROPERTY_SET_DEFS" . 0)
  5.   ("AEC_CLASSIFICATION_SYSTEM_DEFS" . 0)
  6.   ("AcStStandard" . 0)
  7.   ("AcDbVariableDictionary" . 13)
  8.   ("AcadDim" . -1)
  9.   ("ACAD_VISUALSTYLE" . 26)
  10.   ("ACAD_TABLESTYLE" . 1)
  11.   ("ACAD_SECTIONVIEWSTYLE" . 1)
  12.   ("ACAD_SCALELIST" . 1)
  13.   ("ACAD_PLOTSTYLENAME" . 1)
  14.   ("ACAD_MLINESTYLE" . 1)
  15.   ("ACAD_MLEADERSTYLE" . 1)
  16.   ("ACAD_IMAGE_DICT" . 0)
  17.   ("ACAD_DGNLINESTYLECOMP" . 398993)
  18.   ("ACAD_DETAILVIEWSTYLE" . 1)
  19.   ("ACAD_COLOR" . 0)
  20.   ("ACAD_CIP_PREVIOUS_PRODUCT_INFO" . -1)
  21.   )
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Вот это я сглупил!.. Сейчас сравню по быстродействию, выложу обновленный вариант
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Второй вариант, более медленный (как ни странно):
Код - Auto/Visual Lisp [Выбрать]
  1. (vl-load-com)
  2.  
  3. (defun check-dict2 (doc / lst)
  4.   (vlax-for item (vla-get-dictionaries
  5.                    (cond (doc)
  6.                          (t (vla-get-activedocument (vlax-get-acad-object)))
  7.                          ) ;_ end of cond
  8.                    ) ;_ end of vla-get-dictionaries
  9.     (if (vlax-property-available-p item 'name)
  10.       (setq lst (cons (cons (vla-get-name item)
  11.                             (if (vlax-property-available-p item 'count)
  12.                               (vla-get-count item)
  13.                               -1
  14.                               ) ;_ end of if
  15.                             ) ;_ end of cons
  16.                       lst
  17.                       ) ;_ end of cons
  18.             ) ;_ end of setq
  19.       ) ;_ end of vlax-for
  20.     lst
  21.     ) ;_ end of vlax-for
  22.   ) ;_ end of defun
Может, такой код будет более понятен.
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Подшиваленко Дмитрий

  • ADN Club
  • **
  • Сообщений: 64
  • Карма: 0
Алексей, всё замечательно, только я просил всего лишь возвращать количество записей для конкретного передаваемого словаря, чтобы потом мне с моими знаниями я мог понятными мне командами сотворить обработку типа:
Код - Auto/Visual Lisp [Выбрать]
  1. (check-dict nil "acad_dgnlinestylecomp" val)
  2. (if (> val 100) ; Если количество больше 100
  3.  (alert (strcat "Этот чертёж содержит "(itoa val)" объектов DGN! "))
  4. )
А словари я буду проверять по одному по мере необходимости. Это нужно потому, что после проверки словаря будут разные действия.
Проверил словарь acad_dgnlinestylecomp, если записей больше N1 - alert.
Проверил словарь ACAD_SCALELIST, если записей больше N2 - диалоговое окно или команда с очисткой.
Да и не нужно пока проверять все словари сразу.
« Последнее редактирование: 27-04-2016, 16:11:30 от Подшиваленко Дмитрий »

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Код - Auto/Visual Lisp [Выбрать]
  1. (vl-load-com)
  2.  
  3. (defun check-dict2 (doc name / dict)
  4.   ;; doc - Документ (nil - текущий)
  5.   ;; name - имя словаря
  6.   (if (and name
  7.            (= (type (setq dict (vl-catch-all-apply
  8.                                  (function (lambda ()
  9.                                              (vla-item (vla-get-dictionaries
  10.                                                          (cond (doc)
  11.                                                                (t (vla-get-activedocument (vlax-get-acad-object)))
  12.                                                                ) ;_ end of cond
  13.                                                          ) ;_ end of vla-get-Dictionaries
  14.                                                        name
  15.                                                        ) ;_ end of vla-item
  16.                                              ) ;_ end of lambda
  17.                                            ) ;_ end of function
  18.                                  ) ;_ end of VL-CATCH-ALL-APPLY
  19.                           ) ;_ end of setq
  20.                     ) ;_ end of type
  21.               'vla-object
  22.               ) ;_ end of =
  23.            (vlax-property-available-p dict 'count)
  24.            ) ;_ end of and
  25.     (vla-get-count dict)
  26.     ) ;_ end of if
  27.   ) ;_ end of defun
Пример вызова:
Код - Auto/Visual Lisp [Выбрать]
  1. (if (> (check-dict2 nil "ACAD_SCALELIST") 100) (alert "масштабы"))
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Подшиваленко Дмитрий

  • ADN Club
  • **
  • Сообщений: 64
  • Карма: 0
Алексей, всё супер! То что надо!
Спасибо огромное!!! :)

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1115
  • Карма: 173
Отлично :) В качестве оффтопа: лично я бы проходил по всем возможным словарям, получал их имена, сопоставлял с осмысленными названиями, проверял количество записей - и при необходимости формировал бы либо отчет, либо диалог, либо вообще втихаря все сносил ;)
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Подшиваленко Дмитрий

  • ADN Club
  • **
  • Сообщений: 64
  • Карма: 0
либо вообще втихаря все сносил
Думаю не стоит этого делать.
Я тут пару раз снёс людям "ненужное", а некоторым оно оказалось очень даже нужно (тот же словарь DGN и масштабы аннотаций). Пришлось быстро убирать такие очистки и разгребать последствия. Так что когда чистишь файлы на 600 компах, нужно быть предельно аккуратным. А вот проверять количество записей словаря и доставать людей окошком, чтобы они понимали, что их чертёж замусорен, для начала самое оно. Не поймут - со временем перейти к другим действиям.