Создание табличного стиля

В предыдущих частях вроде бы разобрались с созданием и модификацией текстового и размерного стилей. Так сказать, прочувствовали, что создание и изменение текстового стиля проработано просто превосходно (оба варианта - и entmake, и vla - отрабатывают просто отлично); что размерный стиль можно создавать только через entmake (если, конечно, вести разговор именно о LISP'e). Сегодня разберемся с табличными стилями.

Ситуация с табличным стилем совсем иная, нежели с размерным стилем. Да и от текстового стиля методология работы со стилями таблиц отличается.

Описание табличного стиля хранится в специальном словаре "ACAD_TABLESTYLE", и до него можно добраться двумя путями:

  • через entget:
    1
    (entget (cdr (assoc 350 (member '(3 . "ACAD_TABLESTYLE") (entget (namedobjdict))))))
  • через vla:
    1
    (vla-item (vla-get-dictionaries (vla-get-activedocument (vlax-get-acad-object))) "ACAD_TABLESTYLE")

Допустим, нам надо создать (сначала - именно создать) табличный стиль с именем lispru-tablestyle. Настраивать его будем позже. Скажу честно: попытавшись в свое время разобраться с ename-представлениями и запутавшись в dxf-кодах, я плюнул на entmake и все строил с помощью vla-методов.

Создать стиль через vla-представление очень просто (учтите, код пишется прежде всего для объяснения, а не для работы, поэтому улучшать его можно достаточно долго. В конце, если руки дойдут, сделаем проверку быстродействия начального кода и "улучшенного" варианта):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
(vl-load-com)

(defun _lispru-style-create-table (doc name / res)
                                  ;|
*    Функция создания табличного стиля
*    Параметры вызова:
  doc   vla-указатель на документ, в котором надо выполнять создание стиля
        nil -> текущий
  name  имя создаваемого табличного стиля. nil -> "lisptu-tablestyle"
*    Возвращает vla-указатель на созданный табличный стиль. В случае ошибки
* возвращает указатель на активный табличный стиль
|;

  (cond
    ((not doc)
     (setq res (_lispru-style-create-table
                 (vla-get-activedocument (vlax-get-acad-object))
                 name
                 ) ;_ end of _lispru-style-create-table
           ) ;_ end of setq
     )
    ((not name)
     (setq res (_lispru-style-create-table doc "lisptu-tablestyle"))
     )
    ((and doc name)
     (setq
       res (vla-addobject
             (vla-item (vla-get-dictionaries doc) "ACAD_TABLESTYLE")
             name
             "AcDbTableStyle"
             ) ;_ end of vla-addobject
       ) ;_ end of setq
     )
    ) ;_ end of cond
  ) ;_ end of defun

Если исключить все проверки, то фактически самыми интересными строками будут

1
2
3
4
5
(vla-addobject
  (vla-item (vla-get-dictionaries doc) "ACAD_TABLESTYLE")
  name
  "AcDbTableStyle"
  ) ;_ end of vla-addobject

Здесь выполняется добавление объекта в словарь. Единственное требование - необходимо указывать класс создаваемого объекта: "AcDbTableStyle".

Запускаем код на выполнение:

1
2
_$ (_lispru-style-create-table nil nil)
#<VLA-OBJECT IAcadTableStyle2 071c60cc>

Табличный стиль создан? Да, создан, если чертеж новый и в нем не было такого стиля. Попробуем повторно запустить код:

1
2
_$ (_lispru-style-create-table nil nil)
#<VLA-OBJECT IAcadTableStyle2 0f279294>

Как видно, стиль "как бы создан", то есть прямой ошибки нет. Правда, указатель уже другой получен, и куда делся предыдущий - неясно. Подобных ситуаций (с потерей указателей) лично я стараюсь не сталкиваться и поэтому ввожу проверку:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
(vl-load-com)

(defun _lispru-style-create-table (doc name / res)
                                  ;|
*    Функция создания табличного стиля
*    Параметры вызова:
  doc   vla-указатель на документ, в котором надо выполнять создание стиля
        nil -> текущий
  name  имя создаваемого табличного стиля. nil -> "lisptu-tablestyle"
*    Возвращает vla-указатель на созданный табличный стиль. В случае ошибки
* возвращает указатель на активный табличный стиль
|;

  (cond
    ((not doc)
     (setq res (_lispru-style-create-table
                 (vla-get-activedocument (vlax-get-acad-object))
                 name
                 ) ;_ end of _lispru-style-create-table
           ) ;_ end of setq
     )
    ((not name)
     (setq res (_lispru-style-create-table doc "lisptu-tablestyle"))
     )
    ((and doc name)
     (setq
       res
        (cond
          ((member
             (strcase name)
             (mapcar
               (function (lambda (x) (strcase (vla-get-name x))))
               ((lambda (/ _res)
                  (vlax-for item (vla-item (vla-get-dictionaries doc)
                                           "ACAD_TABLESTYLE"
                                           ) ;_ end of vla-item
                    (setq _res (cons item _res))
                    ) ;_ end of vlax-for
                  (reverse _res)
                  ) ;_ end of lambda
                )
               ) ;_ end of mapcar
             ) ;_ end of member
           (vla-item
             (vla-item (vla-get-dictionaries doc) "ACAD_TABLESTYLE")
             name
             ) ;_ end of vla-item
           )
          (t
           (vla-addobject
             (vla-item (vla-get-dictionaries doc) "ACAD_TABLESTYLE")
             name
             "AcDbTableStyle"
             ) ;_ end of vla-addobject
           )
          ) ;_ end of cond
       ) ;_ end of setq
     )
    ) ;_ end of cond
  ) ;_ end of defun

В результате, сколько бы раз мы ни запускали код, все время будем получать один и тот же указатель (естественно, только в текущем документе).

Все, код устойчив и работает (забудем пока про попытки запуска его, например, на BricsCAD или на старых версиях AutoCAD, где табличными стилями и не пахнет). Теперь надо настраивать созданный стиль.

Получим дамп объекта. Для AutoCAD 2008 это будет выглядеть примерно так:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
_$ (vlax-dump-object (_lispru-style-create-table nil nil) t)
; IAcadTableStyle2: AutoCAD IAcadTableStyle Interface
; Property values:
;   Application (RO) = #<VLA-OBJECT IAcadApplication 00d74d3c>
;   BitFlags = 0
;   Description = ""
;   Document (RO) = #<VLA-OBJECT IAcadDocument 022e8950>
;   FlowDirection = 0
;   Handle (RO) = "1AD"
;   HasExtensionDictionary (RO) = 0
;   HeaderSuppressed = 0
;   HorzCellMargin = 0.06
;   Name = "lisptu-tablestyle"
;   NumCellStyles (RO) = 3
;   ObjectID (RO) = -1075178648
;   ObjectName (RO) = "AcDbTableStyle"
;   OwnerID (RO) = -1075184080
;   TemplateId = 0
;   TitleSuppressed = 0
;   VertCellMargin = 0.06
; Methods supported:
;   CreateCellStyle (1)
;   CreateCellStyleFromStyle (2)
;   Delete ()
;   DeleteCellStyle (1)
;   EnableMergeAll (2)
;   GetAlignment (1)
;   GetAlignment2 (1)
;   GetBackgroundColor (1)
;   GetBackgroundColor2 (1)
;   GetBackgroundColorNone (1)
;   GetCellClass (1)
;   GetCellStyles (1)
;   GetColor (1)
;   GetColor2 (1)
;   GetDataType (3)
;   GetDataType2 (3)
;   GetExtensionDictionary ()
;   GetFormat (1)
;   GetFormat2 (2)
;   GetGridColor (2)
;   GetGridColor2 (2)
;   GetGridLineWeight (2)
;   GetGridLineWeight2 (2)
;   GetGridVisibility (2)
;   GetGridVisibility2 (2)
;   GetIsCellStyleInUse (1)
;   GetIsMergeAllEnabled (1)
;   GetRotation (1)
;   GetTextHeight (1)
;   GetTextHeight2 (1)
;   GetTextStyle (1)
;   GetTextStyleId (1)
;   GetUniqueCellStyleName (1)
;   GetXData (3)
;   RenameCellStyle (2)
;   SetAlignment (2)
;   SetAlignment2 (2)
;   SetBackgroundColor (2)
;   SetBackgroundColor2 (2)
;   SetBackgroundColorNone (2)
;   SetCellClass (2)
;   SetColor (2)
;   SetColor2 (2)
;   SetDataType (3)
;   SetDataType2 (3)
;   SetFormat (2)
;   SetFormat2 (2)
;   SetGridColor (3)
;   SetGridColor2 (3)
;   SetGridLineWeight (3)
;   SetGridLineWeight2 (3)
;   SetGridVisibility (3)
;   SetGridVisibility2 (3)
;   SetRotation (2)
;   SetTemplateId (2)
;   SetTextHeight (2)
;   SetTextHeight2 (2)
;   SetTextStyle (2)
;   SetTextStyleId (2)
;   SetXData (2)

Казалось бы, все просто и очевидно. Но, к сожалению, это не так: Autodesk почему-то не полностью проработал ActiveX для табличных стилей.
Начнем с самого простого: подавления Title и Head. Вроде бы элементарно:

1
2
3
4
5
6
_$ (setq style (_lispru-style-create-table nil nil))
#<VLA-OBJECT IAcadTableStyle2 071c60cc>
_$ (vla-put-TitleSuppressed style :vlax-true)
nil
_$ (vla-put-HeaderSuppressed style :vlax-true)
nil

А теперь попробуем создать таблицу нашего стиля. Уже при вызове команды _.table видно, что, несмотря на установленное принудительное подавление Title и Head, все равно эти строки есть. Мало того, они и при создании объекта таблицы существуют (по крайней мере об этом сообщает панель свойств). Да, я понимаю, что таблицы без заголовков существуют весьма редко, но, с другой стороны: уж если заявлено что-то, то добивать надо бы до конца, не бросая задачу на полпути.

С методами тоже не все гладко. Например, метод GetAlignment2 заявлен, но в справке для него объяснения я не увидел. DeleteCellStyle тоже заявлен, и для него даже есть что-то в справке, да только через lisp у меня этот метод не сработал, вызвав ошибку ядра.

Поэтому вывод: работать с табличным стилем приходится очень осторожно, постоянно проверяя код.

Тем не менее, настроим наш стиль. Например:

  • Текстовый стиль каждого типа ячейки - возвращаемый функцией _lispru-style-create-textstyle
  • Горизонтальное расстояние от текста ячейки (любого типа) до ее границы принимаем 0,5 единиц чертежа
  • Вертикальное расстояние принимаем тоже 0,5 единиц чертежа
  • Высота текста заголовка таблицы (Title) принимаем 7,5 ед.чертежа (ну вот захотелось мне так :))
  • Высота текста заголовков столбцов принимаем 5 ед.чертежа
  • Высота текста ячеек с данными составляет 3,5 ед.чертежа
  • Цвет текста ячеек независимо от их типа, а также цвет границ ячеек принимается ByBlock (ПоБлоку)
  • Ячейки не заливаются никаким цветом
  • Границы ячейки заголовка таблицы отсутствуют
  • Вес линий границ остальных ячеек принимаются равными 0,25
  • Заполнение таблицы идет "свеху вниз"

Вроде ничего не забыли. Но, прежде чем писать код, задумаемся - а все ли надо вводить именно в стиле? Ведь, например, текстовый стиль можно вводить напрямую в ячейке. Да и высота текста, и расстояние - вообще, практически все можно вводить и настраивать для каждой ячейки отдельно. Просто сейчас надо решить вопрос - что и в каком месте настраивать, чтобы потом уже не возвращаться.

В свое время я принял решение: все, кроме выравнивания, задается в стиле; и в объекте таблицы меняется строго индивидуально. Кроме того, есть еще один вопрос: а насколько вообще надо передавать в качестве параметров текстовые стили заголовков и данных? Может, и без этого обойтись можно? А насколько требуются параметры, обуславливающие обрамление ячеек? Ответив (только честно ответив!) на эти и подобные вопросы, количество параметров можно весьма серьезно уменьшить.

Стиль создан, осталось его лишь настроить. Об этом позже.

Размещено в Код LISP, Новости, Функции LISP · Метки: ,



Поделитесь своим мнением


Я не робот.