Создание табличного стиля
В предыдущих частях вроде бы разобрались с созданием и модификацией текстового и размерного стилей. Так сказать, прочувствовали, что создание и изменение текстового стиля проработано просто превосходно (оба варианта – и entmake, и vla – отрабатывают просто отлично); что размерный стиль можно создавать только через entmake (если, конечно, вести разговор именно о LISP’e). Сегодня разберемся с табличными стилями.
Ситуация с табличным стилем совсем иная, нежели с размерным стилем. Да и от текстового стиля методология работы со стилями таблиц отличается.
Описание табличного стиля хранится в специальном словаре “ACAD_TABLESTYLE”, и до него можно добраться двумя путями:
- через entget:
(entget (cdr (assoc 350 (member '(3 . "ACAD_TABLESTYLE") (entget (namedobjdict))))))
- через vla:
(vla-item (vla-get-dictionaries (vla-get-activedocument (vlax-get-acad-object))) "ACAD_TABLESTYLE")
Допустим, нам надо создать (сначала – именно создать) табличный стиль с именем lispru-tablestyle. Настраивать его будем позже. Скажу честно: попытавшись в свое время разобраться с ename-представлениями и запутавшись в dxf-кодах, я плюнул на entmake и все строил с помощью vla-методов.
Создать стиль через vla-представление очень просто (учтите, код пишется прежде всего для объяснения, а не для работы, поэтому улучшать его можно достаточно долго. В конце, если руки дойдут, сделаем проверку быстродействия начального кода и “улучшенного” варианта):
(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
Если исключить все проверки, то фактически самыми интересными строками будут
(vla-item (vla-get-dictionaries doc) "ACAD_TABLESTYLE")
name
"AcDbTableStyle"
) ;_ end of vla-addobject
Здесь выполняется добавление объекта в словарь. Единственное требование – необходимо указывать класс создаваемого объекта: “AcDbTableStyle”.
Запускаем код на выполнение:
#<VLA-OBJECT IAcadTableStyle2 071c60cc>
Табличный стиль создан? Да, создан, если чертеж новый и в нем не было такого стиля. Попробуем повторно запустить код:
#<VLA-OBJECT IAcadTableStyle2 0f279294>
Как видно, стиль “как бы создан”, то есть прямой ошибки нет. Правда, указатель уже другой получен, и куда делся предыдущий – неясно. Подобных ситуаций (с потерей указателей) лично я стараюсь не сталкиваться и поэтому ввожу проверку:
(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 это будет выглядеть примерно так:
; 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. Вроде бы элементарно:
#<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
- Заполнение таблицы идет “свеху вниз”
Вроде ничего не забыли. Но, прежде чем писать код, задумаемся – а все ли надо вводить именно в стиле? Ведь, например, текстовый стиль можно вводить напрямую в ячейке. Да и высота текста, и расстояние – вообще, практически все можно вводить и настраивать для каждой ячейки отдельно. Просто сейчас надо решить вопрос – что и в каком месте настраивать, чтобы потом уже не возвращаться.
В свое время я принял решение: все, кроме выравнивания, задается в стиле; и в объекте таблицы меняется строго индивидуально. Кроме того, есть еще один вопрос: а насколько вообще надо передавать в качестве параметров текстовые стили заголовков и данных? Может, и без этого обойтись можно? А насколько требуются параметры, обуславливающие обрамление ячеек? Ответив (только честно ответив!) на эти и подобные вопросы, количество параметров можно весьма серьезно уменьшить.
Стиль создан, осталось его лишь настроить. Об этом позже.
Материалы для проектирования, работы и разработки (и не только в AutoCAD)