(изменено: Григорий Калинин, 1 июля 2009г. 15:00:26)

Тема: Массовое изменение свойств атрибутов блоков

Всем привет!
Занимаюсь программированием САПР для маркшейдеров и геологов. По их просьбе добавил программу, позволяющую изменить атрибуты множества выбранных блоков. Прога состоит из LISP-файла и DCL-файла диалога. Как говорится: берите, люди, пользуйтесь!
Благодарности:
1. Алексею Кулику aka kpblc за бесценный материал
2. В. Левину за полезный сайт http://www.levins.land.ru по DCL.
Вот LISP-файл AttrProptis.lsp:

(defun c:AttrProptis ()
;;* ==================================================================================================================================
;;* С помощью данной проги можно:  
;;* 1. Изменять координаты точки вставки видимых атрибутов блоков, задавая относительные смещения по вертикали и горизонтали
;;*    с помощью ползунков или числом.
;;* 2. Изменять высоту текста атрибута
;;* 3. Изменять высоту угол наклона текста атрибута  
;;* 4. Изменять угол поворота текста атрибута
;;* 5. Помещать атрибуты на отдельный слой чертежа из предлагаемых в выпадающем списке.
;;*    Последнее позволяет скрыть атрибуты, если слой сделать невидимым.
;;* 6. Изменять цвета атрибутов.
;;* 7. При наличии нескольких видимых атрибутов свойства каждого можно изменять индивидуально.  
;;* Блоки с видимыми атрибутами можно выбрать заранее (неважно, если в выбор попадут другие объекты чертежа - сработает фильтр).
;;* Затем в окне диалога меняем свойства (например, задаем смещения вверх-вниз, влево-вправо точки вставки атрибута.
;;* После закрытия окна диалога выбор не сбрасывается, текущие значения запоминаются, можно продолжать от достигнутого.
;;* ==================================================================================================================================  
(vl-load-com)
  (setq adoc (vla-get-activedocument (vlax-get-acad-object)))

  (vla-startundomark adoc)
  (princ "\nВыберите блоки (с видимыми атрибутами) (Enter - завершить) ")
  (if (not
    (setq objSet (ssget "_I" '((0 . "INSERT") (66 . 1))))
      )                    ;(ssget "_I" '((0 . "INSERT")))))
    (progn (princ "\nВыберите блоки (с видимыми атрибутами) (Enter - завершить) ")
       (setq objSet (ssget '((0 . "INSERT") (66 . 1))))
    )
  )                    ; end if
  (setq Tag_Attr_list nil)
    (setq item (ssname objSet 0))
    (foreach sub_item
         (vlax-safearray->list
           (vlax-variant-value
         (vla-getattributes (vlax-ename->vla-object item))
           ) ;_ end of vlax-variant-value
         ) ;_ end of vlax-safearray->list
      (if (= (vla-get-Invisible sub_item) :vlax-false)
    (progn
        (setq Tag_Attr_list (append Tag_Attr_list (list (vla-get-tagstring sub_item))))
    ) ;_ end of progn
      ) ;_ end if
    ) ;_ end of foreach
  (setq Layers_list nil)
  (vlax-for Item (vla-get-layers adoc)
    (setq Layers_list (append Layers_list (list (vla-get-name Item))))
  )
  (setq Layers_list (cons "" Layers_list))
  (setq Attr_List (AttrInsert))
  (setq Tag_Attr_Name (nth 0 Attr_List)) ; имя изменяемого видимого атрибута
  (setq Height (nth 1 Attr_List)) ; высота текста атрибута 
  (setq TextAngle (nth 2 Attr_List)) ; угол наклона текста атрибута
  (setq TextRotation (nth 3 Attr_List)) ; угол вращения текста атрибута
  (setq TextColor (nth 4 Attr_List)) ; цвет текста атрибута
  (setq Layer_Name (nth 5 Attr_List)) ; слой
  (setq shift_All (cddr (cddddr Attr_List))) ; смещения координат точки вставки атрибута
  
  (while (and objSet
          (> (sslength objSet) 0)
     ) ;_ end of and
    (setq item (ssname objSet 0))
    (ssdel item objSet)
    (foreach sub_item
         (vlax-safearray->list
           (vlax-variant-value
         (vla-getattributes (vlax-ename->vla-object item))
           ) ;_ end of vlax-variant-value
         ) ;_ end of vlax-safearray->list
      (if (= (vla-get-tagstring sub_item) Tag_Attr_Name) ; имя видимого атрибута совпадает с выбранным?
    (progn
      (setq    insertionpoint (vlax-safearray->list
               (vlax-variant-value
             (vla-get-insertionpoint sub_item)
               )
             )
      )
      (setq oldAlign (vla-get-Alignment sub_item))    ; запомнить выравнивания текста
      (setq    oldAlignTextPoint
         (vlax-safearray->list
           (vlax-variant-value
             (vla-get-TextalignmentPoint sub_item)
           )
         )
      )
      (vla-put-insertionpoint
        sub_item
        (vlax-3d-point (mapcar '+ shift_All insertionpoint))
      )
      (if (/= oldAlign acAlignmentLeft)    ; восстанавливать вторую точку выравнивания текста, если выравнивание - не влево
        (vla-put-TextalignmentPoint
          sub_item
          (vlax-3d-point
        (mapcar '+ shift_All oldAlignTextPoint)
          )
        )
      )
      (if (/= TextAngle nil) 
        (vla-put-ObliqueAngle sub_item (angtof TextAngle 0))
      )
      (if (/= TextRotation nil) 
        (vla-put-rotation sub_item (angtof TextRotation 0))
      )
      (if (> Height 0)
              (vla-put-height sub_item Height)
      )
      (if (/= TextColor nil) 
              (vla-put-color sub_item TextColor)
      )
      (if (/= Layer_Name nil) 
              (vla-put-Layer sub_item Layer_Name)
      )
    ) ;_ end of progn
      ) ;_ end if
    ) ;_ end of foreach
  ) ;_ end of while
  (vla-endundomark adoc)
)
(defun TagAttributes ( / )
  ; получение списка видимых атрибутов блока
  (setq Tag_list nil)
    (setq item (ssname objSet 0))
    (foreach sub_item
         (vlax-safearray->list
           (vlax-variant-value
         (vla-getattributes (vlax-ename->vla-object item))
           ) ;_ end of vlax-variant-value
         ) ;_ end of vlax-safearray->list
      (if (= (vla-get-Invisible sub_item) :vlax-false)
    (progn
        (append (list (vla-get-tagstring sub_item)))
    ) ;_ end of progn
      ) ;_ end if
    ) ;_ end of foreach
)  
(defun AttrInsert( / )
;;;>> Восстановление начальных значений переменных 
  (setq Height 0)
  
  (if (not veb_sl_Left)(setq veb_sl_Left "0"))
  (if (not veb_sl_Right)(setq veb_sl_Right "0"))
  (if (not veb_sl_Up)(setq veb_sl_Up "0"))
  (if (not veb_sl_Down)(setq veb_sl_Down "0"))
  
;;;--- Загрузать файл DCL и поместить его имя в dcl_id
(setq dcl_id (load_dialog "AttrDialog.dcl"))
;;;--- Если этот файл еще не загружен,
;;;--- то открыть его, иначе - выйти  
(if (not (new_dialog "AttrInsert" dcl_id)
    ); конец not
    (exit);если не обнаружен диалог - выход
); конец if
;;;>> Восстановление сохраненных значений переменных   

(set_tile "eb_sl_Left" veb_sl_Left)
(set_tile "eb_sl_Right" veb_sl_Right)
(set_tile "eb_sl_Up" veb_sl_Up)
(set_tile "eb_sl_Down" veb_sl_Down)

(setq middle_sliders (/ (atoi (get_attr "sl_Horizontal" "max_value")) 2))
(setq text_middle_sliders (itoa middle_sliders))

(if (not vsl_Left)(setq vsl_Left text_middle_sliders))
(set_tile "sl_Horizontal" vsl_Left)  

(if (not vsl_Right)(setq vsl_Right text_middle_sliders))
(set_tile "sl_Horizontal" vsl_Right)
  
(if (not vsl_Up)(setq vsl_Up text_middle_sliders))
(set_tile "sl_Vertical" vsl_Up)
  
(if (not vsl_Down)(setq vsl_Down text_middle_sliders))
(set_tile "sl_Vertical" vsl_Down)

(setq TextColor nil)

(setq Tag_Attr_index "0")
(setq Tag_Attr_Name (nth 0 Tag_Attr_list))
(setq Layers_index "0")
(setq Layer_Name nil)
;;; Заполнение выпадающего списка именами видимых атрибутов блока
(start_list "Tag_Attr_list")
   (mapcar 'add_list Tag_Attr_list)
(end_list)
(set_tile "Tag_Attr_list" Tag_Attr_index)
;;; Заполнение выпадающего списка именами слоев чертежа
(start_list "Layers_list")
   (mapcar 'add_list Layers_list)
(end_list)
(set_tile "Layers_list" Layers_index)
  
;;;--- Если нажата кнопка "cancel"
;;;--- выполнить функцию (done_dialog), установить флаг act = nil
(action_tile "cancel" "(setq act nil)(done_dialog)"
);конец actio_tile 'сancel'
  
;;;--- Если нажата кнопка "accept"
;;;--- выполнить функцию (done_dialog), установить флаг act =T (true)
(action_tile "accept"  
    "(setq act T)(done_dialog))"
); конец action_tile 'accept'
(start_dialog)            ;Показать Диалоговое окно
(unload_dialog dcl_id)    ;Закрыть Диалоговое окно
  
;;;--- Если выбрана кнопка "cancel"
;;;--- показать сообщение об отмене
(if (= act nil)
      (exit)
); конец if
;;;--- Если выбрана кнопка "accept"
;;;--- показать сообщение об успешном выполнении
(if (= act T)
      (rem_shift)
 ))    ; конец if 
 
;;; (princ)); "Тихий" выход и конец программы D1301

;;;>> Подпрограмма формирования списка с данными о высоте текста, наклоне, вращении и заданных смещениях атрибута
(defun rem_shift()
    (setq shift_Horizontal (- (atof veb_sl_Right) (atof veb_sl_Left)))
    (setq shift_Vertical (- (atof veb_sl_Up) (atof veb_sl_Down)))
    (list Tag_Attr_Name Height TextAngle TextRotation TextColor Layer_Name shift_Horizontal shift_Vertical 0)
);end rem_Data

;;;>> Подпрограммы связи горизонтального ползунка с текстовыми окнами "Левее" и "Правее"
  (defun sl_Horizontal_action ();если сдвинут ползунок
    (setq vsl_Left (get_tile "sl_Horizontal")) ;присвоить переменой значение value ползунка
    (setq vsl_Right (get_tile "sl_Horizontal")) ;присвоить переменой значение value ползунка
    (if (<= (atof vsl_Left) middle_sliders)
          (progn 
            (set_tile "eb_sl_Left" (rtos (- 5.0 (/ (atof vsl_Left) 10.0))) );модифицировать и передать это значение в текстовое окно "eb_sl_Left"
          (set_tile "eb_sl_Right" "0")
    )
    )
    (if (>= (atof vsl_Right) middle_sliders)
          (progn 
            (set_tile "eb_sl_Right" (rtos (- (/ (atof vsl_Right) 10.0) 5.0 )) );модифицировать и передать это значение в текстовое окно "eb_sl_Right"
          (set_tile "eb_sl_Left" "0")
    )
    )
    (setq veb_sl_Left (get_tile "eb_sl_Left")) ;присвоить значение value ползунка
    (setq veb_sl_Right (get_tile "eb_sl_Right")) ;присвоить значение value ползунка
  );end defun

  (defun eb_sl_Left_action ();если изменен текст в окне "eb_sl_Left"
    (setq veb_sl_Left (get_tile "eb_sl_Left"));присвоить переменной значение value текстового окна
        (if (or (/= veb_sl_Left "0") (= (get_tile "eb_sl_Right") "0"))
      (progn
        (set_tile "sl_Horizontal" (rtos (* (- 5 (atof veb_sl_Left)) 10)));передать это значение в тайл ползунка
        (setq vsl_Left (get_tile "sl_Horizontal")) ;присвоить переменой vsl_Left значение value ползунка
        (set_tile "eb_sl_Right" "0")
      )
        )
  );end defun

  (defun eb_sl_Right_action ();если изменен текст в окне "eb_sl_Right"
    (setq veb_sl_Right (get_tile "eb_sl_Right"));присвоить переменной значение value текстового окна
        (if (or (/= veb_sl_Right "0") (= (get_tile "eb_sl_Left") "0"))
      (progn
        (set_tile "sl_Horizontal" (rtos (* (+ (atof veb_sl_Right) 5) 10)));передать это значение в тайл ползунка
        (setq vsl_Right (get_tile "sl_Horizontal")) ;присвоить переменой vsl_Right значение value ползунка
        (set_tile "eb_sl_Left" "0")
      )
    )
  );end defun

;;;>> Подпрограммы связи вертикального ползунка с текстовыми окнами "Выше" и "Ниже"
  (defun sl_Vertical_action ();если сдвинут ползунок
    (setq vsl_Up (get_tile "sl_Vertical")) ;присвоить переменой значение value ползунка
    (setq vsl_Down (get_tile "sl_Vertical")) ;присвоить переменой значение value ползунка
    (if (>= (atof vsl_Up) middle_sliders)
          (progn 
            (set_tile "eb_sl_Up" (rtos (- (/ (atof vsl_Up) 10.0) 5.0 )) );модифицировать и передать это значение в текстовое окно "eb_sl"
          (set_tile "eb_sl_Down" "0")
    )
    )
    (if (<= (atof vsl_Down) middle_sliders)
          (progn
            (set_tile "eb_sl_Down" (rtos (- 5.0 (/ (atof vsl_Down) 10.0))) );модифицировать и передать это значение в текстовое окно "eb_sl"
          (set_tile "eb_sl_Up" "0")
    )
    )
    (setq veb_sl_Up (get_tile "eb_sl_Up")) ;присвоить переменой vsl_Up значение value ползунка
    (setq veb_sl_Down (get_tile "eb_sl_Down")) ;присвоить переменой vsl_Down значение value ползунка
  );end defun

  (defun eb_sl_Up_action ();если изменен текст в окне "eb_sl_Up"
    (setq veb_sl_Up (get_tile "eb_sl_Up"));присвоить переменной значение value текстового окна
    (if (or (/= veb_sl_Up "0") (= (get_tile "eb_sl_Down") "0"))
    (progn
        (set_tile "sl_Vertical" (rtos (* (+ (atof veb_sl_Up) 5) 10)));передать это значение в тайл ползунка
        (setq vsl_Up (get_tile "sl_Vertical")) ;присвоить переменой vsl_Up значение value ползунка
        (set_tile "eb_sl_Down" "0")
    )
    )
  );end defun

  (defun eb_sl_Down_action ();если изменен текст в окне "eb_sl_Down"
    (setq veb_sl_Down (get_tile "eb_sl_Down"));присвоить переменной значение value текстового окна
    (if (or (/= veb_sl_Down "0") (= (get_tile "eb_sl_Up") "0"))
    (progn
        (set_tile "sl_Vertical" (rtos (* (- 5 (atof veb_sl_Down)) 10)));передать это значение в тайл ползунка
        (setq vsl_Down (get_tile "sl_Vertical")) ;присвоить переменой vsl_Down значение value ползунка
        (set_tile "eb_sl_Up" "0")
     )
    )
  );end defun

  (defun TextHeight_action ();если изменен текст в окне "Высота текста"
    (setq TextHeight (get_tile "TextHeight"));присвоить переменной значение value текстового окна
    (if (/= TextHeight nil) 
    (setq Height (atof TextHeight))
        (setq Height 0)
    )
  );end defun

  (defun TextAngle_action ();если изменен текст в окне "Наклон"
    (setq TextAngle (get_tile "TextAngle"));присвоить переменной значение value текстового окна
  );end defun

  (defun TextRotation_action ();если изменен текст в окне "Поворот"
    (setq TextRotation (get_tile "TextRotation"));присвоить переменной значение value текстового окна
  );end defun

  (defun TextColor_action ();если нажата кнопка "Палитра"
    (setq TextColor (acad_colordlg 0));присвоить переменной номер цвета из 256-цветной палитры
  );end defun

  (defun Layers_list_action ();если произведен выбор из списка слоев
    (setq Layers_index (get_tile "Layers_list"));присвоить номер индекса в списке
    (setq Layer_Name (nth (atoi Layers_index) Layers_list))
  );end defun

  (defun Tag_Attr_list_action ();если произведен выбор из списка слоев
    (setq Tag_Attr_index (get_tile "Tag_Attr_list"));присвоить номер индекса в списке
    (setq Tag_Attr_Name (nth (atoi Tag_Attr_index) Tag_Attr_list))
  );end defun

А вот DCL-файл AttrDialog.dcl:

 AttrIns ert : dialog {
  label = "Свойства атрибутов блоков" ;
:boxed_row{label = "Видимые атрибуты";
:popup_list{fixed_width=true;
      key="Tag_Attr_list";
      label="";
      width=10;
      height=8;
      edit_width=22;
      value = "5";
      alignment=centered;
      action="(Tag_Attr_list_action)";
}//end Attr_list                  }
}
:row{alignment=centered;
    height=10;fixed_width=true;width=36;label = "Смещения:" ;
    :column{label = "Вертикальное" ;
         :edit_box{key="eb_sl_Up";// Текстовое окно положение движка
              label="Выше";
              alignment=right;
              value="0";
              edit_width=3;
              fixed_width_font=true;
              fixed_width=true;
              action="(eb_sl_Up_action)";
         }//end eb_sl_Up
         :edit_box{key="eb_sl_Down";// Текстовое окно положение движка
              label="Ниже";
              alignment=right;
              value="0";
              edit_width=3;
              fixed_width_font=true;
              fixed_width=true;
              action="(eb_sl_Down_action)";
         }//end eb_sl_Down
    }//end column
    :column{
         :slider{key="sl_Vertical";    // Ползунок для задания вертикального смещения
               layout=vertical;
               fixed_width=true;
               width=2;
               height=10;
              max_value=100; // Значение при крайнем правом положении
              min_value=0;   // Значение при крайнем левом положении
              value="0";    // Начальная установка
              small_increment=1;
              big_increment=1;
              fixed_height=true;
              action="(sl_Vertical_action)";
         }//end sl_Vertical
    }//end column
    :column{
         :row{label = "Высота";
             :edit_box{key="TextHeight";// Текстовое окно высоты текста
                  label="      ";
                  value="";
                  edit_width=3;
                  fixed_width_font=true;
                  fixed_width=true;
                  action="(TextHeight_action)";
             }//end eb_sl_Up
         }
         :row{label = "Наклон";
             :edit_box{key="TextAngle";// Текстовое окно угла наклона текста
                  label="      ";
                  value="";
                  edit_width=3;
                  fixed_width_font=true;
                  fixed_width=true;
                  action="(TextAngle_action)";
             }//end eb_sl_Down
         }
         :row{label = "Поворот";
             :edit_box{key="TextRotation";// Текстовое окно угла поворота текста
                  label="      ";
                  value="";
                  edit_width=3;
                  fixed_width_font=true;
                  fixed_width=true;
                  action="(TextRotation_action)";
             }//end eb_sl_Down
         }
    }//end column
}//end row
    :row{alignment=centered;label = "Горизонтальное" ;
         fixed_width=true; width=36;
         :edit_box{key="eb_sl_Left";// Текстовое окно положение движка
              label="Левее";
              value="0";
              edit_width=3;
              fixed_width_font=true;
              action="(eb_sl_Left_action)";
         }//end eb_sl_Left
         :row{fixed_width=true; width=3;}
         :edit_box{key="eb_sl_Right";// Текстовое окно положение движка
              label="Правее";
              value="0";
              edit_width=3;
              fixed_width_font=true;
              action="(eb_sl_Right_action)";
         }//end eb_sl_Right
    }
    :row{fixed_width=true; width=30;
         alignment=centered;
         :slider{key="sl_Horizontal";    // Ползунок для задания горизонтального смещения
               fixed_width=true; 
               width=30;
              max_value=100; // Значение при крайнем правом положении
              min_value=0;   // Значение при крайнем левом положении
              value="0";    // Начальная установка
              small_increment=1;
              big_increment=1;
              action="(sl_Horizontal_action)";
         }//end sl_Horizontal
    }
         :boxed_row{label = "Слой и цвет";
        :popup_list{fixed_width=true;
              key="Layers_list";
              label="";
              width=10;
              height=8;
              edit_width=22;
              value = "5";
              alignment=centered;
              action="(Layers_list_action)";
        }//end popup_list                  }
             :button{key="TextColor";// Текстовое окно цвета текста
                  label="Палитра";
                  action="(TextColor_action)";
             }//end eb_sl_Down
         }
    :row{
        fixed_width=true;  //Минимальная ширина по объектам внутри
        alignment = centered; //Выровнен по правому краю
     ok_cancel;// Кнопка
     }    //end Row
   }    //конец диалога 

Строка для кнопки вызова:
^C^C^P(if (null C:AttrProptis) (load "AttrProptis")) AttrProptis

Re: Массовое изменение свойств атрибутов блоков

В файле dcl лишний пробел в первой строке:

AttrIns ert : dialog {

должно быть

AttrInsert : dialog {


Спасибо за программку!

Re: Массовое изменение свойств атрибутов блоков

Странно, хотел исправить очепятку, но изменение не сохраняется :?:

Re: Массовое изменение свойств атрибутов блоков

Спасибо за программку.
Я понимаю, что прошло уже много времени, но может можно еще добавить возможность изменения ширины текста, замену стиля и выравнивание.