Программирование на VBA
Цель лекции: изучить принципы и конкретные технологии программирования на VBA.
Введение. Обзор команд. Объектная модель
Введение
Интерфейс AutoCAD ActiveX/VBA дает некотoрые преимущества по сравнению с другими методами создания приложений AutoCAD:
- Высокая скорость выполнения процесса, так как в отличие от AutoLISP-приложений выполнение команд происходит внутри процесса;
- Простота использования, обусловленная простотой языка программирования;
- Большие возможности межпрограмного обмена, так как VBA и ActiveX разрабатывались для взаимодействия с другими Windows-приложениями.
Понятие внедренных и глобальных проектов VBA
Приложение Autocad VBA представляет собой набор программных модулей, модулей классов и форм. Пороект может быть сохранен как в рисунке (внедренный), так и во внешнем файле. Внедренный проект автоматически загружается при открытии рисунка. Ограничение внедренных проектов в том, например, что они не могут закрыть рисунок, внутри которого находятся. Глобальные проекты в этом плане более гибки, при этом однако пользователь должен знать где расположен файл в котором хранятся макросы. Глобальный проект проще передавать другим пользователям и в нем удобно хранить общие макросы. В любой момент могут быть использованы оба типа проектов. На уровне двоичного кода проект Autocad VBA не совместим с проектом Visual Basic, однако обмен формами, модулями и классами можно производить через экспорт- импорт. (Команды IMPORT и EXPORT VBA).
Загрузка существующего проекта
При загрузке проекта все глобальные процедуры, называемые так же макросами, становятся доступными для использования. Загрузить проект можно через VBA-менеджер или с командной строки VBALOAD. Кроме того автокад грузит автоматически проект с именем acad.dvb, который может найти в путях файлов поддержки. При загрузке проекта может появиться предупреждение, что он содержит макросы, а значит может содержать и вирусы. Выгрузка проекта командной VBAUNLOAD приводит к высвобождению памяти ранее занятой проектом. Внедрить проект в рисунок можно с помощью VBA-менеджера, он же позволяет извлечь проект из рисунка, при этом предлагая сохранить его в отдельном файле. Чтобы среда разработки VBA автоматически загрузилась при загрузке AutoCAD, в файл acad.arx нужно внести строку acadvba.arx.
Определение компонентов проекта
Проект может состоять из различных компонентов:
- объекты;
- формы;
- стандартные модули;
- модули класса;
- ссылки.
Добавить компонент можно через меню Insert, компоненты так же можно импортировать из файлов (.frm, .bas, .cls).
Обзор команд VBA AutoCAD
- VBAIDE- открывает окно VBA IDE, позволяющее редактировать, запускать и отлаживать программы.
- VBALOAD - загружает проект.
- VBARUN - запускает макрос на выполнение.
- VBAUNLOAD - выгружает проект, освобождая память.
- VBAMAN - показывает окно менеджера VBA.
- VBASTMT - позволяет выполнить команду VBA в командной строке AutoCAD.
Основные понятия объектной модели AutoCAD
Все объекты AutoCAD организованы в виде иерархической структуры. Корнем дерева является объект Application.
Через объект Application можно получить доступ к следующим объектам:
- Preferences;
- Documents;
- MenuBar;
- MenuGroups;
Через объект Preferences можно получить доступ к следующим объектам
- PreferencesDisplay;
- PreferencesDrafting;
- PreferencesFiles;
- PreferencesOpenSave;
- PreferencesOutput;
- PreferencesProfiles;
- PreferencesSelection;
- PreferencesSystem;
- PreferencesUser.
Через объект Documents можно получить доступ к объекту Document а через него к большинству других объектов и коллекций:
- Blocks (блоки)
- Dictionaries (словари)
- DimStyles (размерные стили)
- Groups (группы)
- Layers (слои)
- Layouts ()
- Linetypes (типы линий)
- PlotConfigurations (настройки плоттеров)
- RegisteredApplications (зарегистрированные приложения)
- SelectionSets (наборы)
- TextStyles (стили текста)
- UserCoordinateSystems (системы координат определенные пользователем)
- Views (виды)
- Viewports (видовые экраны)
- DatabasePreferences ()
- Plot (печать)
- Utility (служебные программы)
- ModelSpace (пространство модели)
- PaperSpace (пространство листа)
В двух последних расположены объекты AutoCAD, видимые на рисунке:
3DFace 3DPoly 3DSolid Arc Attribute AttributeReference BlockReference Circle Dim3PointAngular DimAligned DimAngular DimDiametric DimOrdinate DimRadial DimRotated Ellipse ExternalReference Hatch Leader LWPolyline Line MInsertBlock MLine MText Point PolyfaceMesh Polyline PolygonMesh RasterImage Ray Region Shape Solid Spline Text Tolerance Trace Xline
Доступ к иерархии объектов. Коллекции, свойства и методы
Связь VBA с активным чертежом обеспечивается посредством объекта ThisDrawing. С его помощью можно получить немедленный доступ ко всем свойствам и методам объекта Document а также ко всем другим объектам в иерархии.
Когда используются глобальные проекты, ThisDrawing всегда ссылается на активный документ. При использовании внедренных проектов ThisDrawing всегда ссылается на документ, содержащий проект. Например, следующая строка кода в глобальном проекте сохраняет любой чертеж, который в данный момент активен:
ThisDrawing.Save
Ссылка на объекты в иерархии объектов
Доступ к объекту можно получить непосредственно или через объектную переменную. Для непосредственной сслыки на объект достаточно указать полный путь к нему в иерархии. Например, следующий фрагмент кода добавляет линию в пространство модели:
Sub Test() Dim startPoint(0 To 2) As Double, endPoint(0 To 2) As Double Dim LineObj As AcadLine startPoint(0) = 0: startPoint(1) = 0: startPoint(2) = 0 endPoint(0) = 30: endPoint(1) = 20: endPoint(2) = 0 Set LineObj = ThisDrawing.ModelSpace.AddLine(startPoint, endPoint) End Sub
Для доступа к объекту через объектную переменную поступаем следующим образом. Определяем переменную желаемого типа, после чего устанавливаем переменную так, чтобы она ссылалась на нужный объект. К примеру следующий код определит объектную переменную moSpace типа AcadModelSpace так, чтобы она ссылалась на текущее пространство модели:
Dim moSpace As AcadModelSpace Set moSpace = ThisDrawing.ModelSpace
В примере добавляем линию в пространство модели, используя эту переменную:
Dim startPoint(0 To 2) As Double, endPoint(0 To 2) As Double Dim LineObj as AcadLine startPoint(0) = 0: startPoint(1) = 0: startPoint(2) = 0 endPoint(0) = 30: endPoint(1) = 20: endPoint(2) = 0 Set LineObj = moSpace.AddLine(startPoint,endPoint)
Корневой объект Application расположен в иерархии выше объекта Document. Выше показано, что объект ThisDrawing обеспечивает доступ к объекту Document. А у объекта Document есть свойство Application, которое и является ссылкой на объект Application. Пример обращения:
ThisDrawing.Application.Update
Коллекции объектов
Объект Collection - является предопределенным объектом содержащим все вхождения подобных объектов. Существуют следующие объекты коллекции:
- Documents - включает все открытые в текущей сессии документы
- ModelSpace - включает все графические объекты (entities - примитивы) пространства модели
- PaperSpace - включает все графические объекты пространства активного листа
- Block Object - включает все указанные определения блоков
- Blocks - включает все блочные ссылки рисунка
- Dictionaries - включает все словари (Dictionaries) рисунка
- DimStyles - включает все размерные стили рисунка
- Groups - включает все группы рисунка
- Hyperlinks - включает все гиперссылки рисунка
- Layers - включает все слои рисунка
- Layouts - включает все листы рисунка
- Linetypes - включает все типы линий рисунка
- MenuBar - включает все отображаемые AutoCADом меню
- MenuGroups - включает все меню и панели инструментов
- RegisteredApplications - включает все зарегистрированные приложения
- SelectionSets - включает все наборы рисунка
- TextStyles - включает все стили текста рисунка
- UCSs - включает все пользовательские системы координат рисунка
- Views - включает все Виды рисунка
- Viewports - включает все видовые экраны рисунка
Доступ к коллекции
Большинство коллекций доступны через объект Document, т.к. он содержит свойства для каждой из коллекций. Следующий код устанавливает ссылку объектной переменной на коллекцию Layers:
Dim layerCollection as AcadLayers Set layerCollection = ThisDrawing.Layers
Коллекции Documents, MenuBar и MenuGroups доступны через объект Application. Он содержит свойства для каждой из этих коллекций. Следующий пример определяет объектную переменную и создает ссылку через нее на коллекцию:
Dim MenuGroupsCollection as AcadMenuGroups Set MenuGroupsCollection = ThisDrawing.Application.MenuGroups
Добавление нового элемента коллекции
Следующий пример создает слой и добавляет его в коллекцию:
Dim newLayer as AcadLayer Set newLayer = ThisDrawing.Layers.Add("MyNewLayer")
Перебор членов коллекции
Для выбора нужного члена коллекции используется метод Item. В качестве параметра ему передается номер (Index) объекта в коллекции либо его символьный идентификатор. Пример демонстрирует перебор всех слоев с отображением их имен
Sub IterateLayer() On Error Resume Next Dim I As Integer Dim msg As String msg = "" For I = 0 To ThisDrawing.Layers.count - 1 msg = msg + ThisDrawing.Layers.Item(I).Name + vbCrLf Next MsgBox msg End Sub
Пример поиска слоя с именем ABC:
Sub FindLayerABC() On Error Resume Next Dim ABCLayer As AcadLayer Set ABCLayer = ThisDrawing.Layers.Item("ABC") If Err <> 0 Then MsgBox "Слой 'ABC' не существует" End If End Sub
Примечание
Не следует использовать методы редактирования примитивов (Copy, Array, Mirror и др.) на любом объекте который одновременно перебирается с помощью механизма For Each. В случае необходимости нужно закончить перебор, создать временный массив эквивалентный коллекции и в этом массиве выполнить редактирование.
Удаление члена коллекции
Пример удаления слоя:
Dim ABCLayer as AcadLayer Set ABCLayer = ThisDrawing.Layers.Item("ABC") ABCLayer.Delete
Удаленный объект восстановлению не подлежит.
Понятие свойств и методов
Каждый объект обладает связанными с ним свойствами и методами. Свойства описывают некоторые характеристики присущие объекту, а методы позволяют выполнять действия над объектами, в частности, менять и читать свойства. Например, объект окружность имеет свойство Центр, которое представляет трехмерную координату центра окружности. Чтобы сменить свойство достаточно задать ему другое значение. Окружность как целое имеет метод Offset, который создает новый объект на указанном смещении от существующего. Полный перечень свойств и методов есть в ActiveX and VBA Reference.
Понятие родительского объекта
Каждый объект имеет своего родителя с которым он постоянно связан. Доступ к каждому объекту можно осуществить следуя от родительского объекта к дочернему. Кроме того все объекты имеют свойство Application, как непосредственную ссылку на корневой объект.
Библиотеки типов
Описание объектов, свойств и методов хранятся в библиотеке типов, с помощью которой браузеры и приложения могут определить характеристики объектов. Прежде чем использовать объекты автоматизации, следует создать ссылку на библиотеку типов. Это нужно для того, чтобы глобальные функции были доступны непосредственно без подготовки. Вызовы функций при этом могут контролироваться компилятором на корректность. Увеличивается надежность и читабельность программы.
Получение первого примитива из базы данных рисунка
Sub FindFirstEntity() On Error Resume Next Dim entity As AcadEntity If ThisDrawing.ModelSpace.count <> 0 Then Set entity = ThisDrawing.ModelSpace.Item(0) MsgBox entity.ObjectName + " первый примитив в пространстве модели." Else MsgBox "Нет ни одного объекта в пространстве модели." End If End Sub
Применение variant в методах и свойствах
Для передачи массива данных AutoCAD использует тип Variant который может принимать данные любого типа за исключением строк фиксированной длины и типов данных, определяемых пользователем. Может также принимать значения Empty, Error, Nothing, NULL. Чтобы узнать какой именно тип данных хранятся в переменной типа Variant, нужно обратиться к функции VarType или TypeName.
Тип данных Variant используется для передачи массива данных из/в AutoCAD ActiveX Automation. В AutoCAD VBA-входные массивы автоматически преобразуются в тип Variant. Однако c выходными массивами все не так просто. Метод CreateTypedArray преобразует массив в Variant, содержащий "смесь" из Integer, Double и т.д. Эту "смесь" можно передать в любой метод или любое свойство AutoCAD, которые принимают массив чисел как Variant.
В примере преобразуются три массива координат сплайна с передачей их методу AddSpline.
Sub CreateSplineUsingTypedArray() Dim splineObj As AcadSpline Dim startTan As Variant, endTan As Variant, fitPoints As Variant Dim noOfPoints As Integer Dim utilObj As Object Set utilObj = ThisDrawing.Utility ' Определение сплайна utilObj.CreateTypedArray startTan, vbDouble, 0.5, 0.5, 0 utilObj.CreateTypedArray endTan, vbDouble, 0.5, 0.5, 0 utilObj.CreateTypedArray fitPoints, vbDouble, 0, 0, 0, 5, 5, 0, 10, 0, 0 noOfPoints = 3 Set splineObj = ThisDrawing.ModelSpace.AddSpline(fitPoints, startTan, endTan) ZoomAll End Sub
Интерпретация variant-массивов
Передаваемая AutoCAD ActiveX Automation информация массива возвращается как тип Variant, если типы данных элементов массива известны. Иначе применяем функции VarType Typename. Для перебора элементов массива удобен метод For Each. Пример вычисления расстояния между двумя точками введенными пользователем:
Sub CalculateDistance() Dim point1 As Variant,point2 As Variant ' Запрос на ввод координат point1 = ThisDrawing.Utility.GetPoint (, vbCrLf & "1-ая точка: ") point2 = ThisDrawing.Utility.GetPoint (point1, vbCrLf & "2-ая: ") Dim x As Double, y As Double, z As Double Dim dist As Double x = point1(0) - point2(0) y = point1(1) - point2(1) z = point1(2) - point2(2) dist = Sqr((Sqr((x ^ 2) + (y ^ 2)) ^ 2) + (z ^ 2)) MsgBox "Расстояние между точками: " & dist End Sub
Использование других языков программирования
Чтобы использовать приведенные примеры не в VBA а в VB следует, во-первых, сослаться на библиотеку типов, во-вторых заменить все ссылки ThisDrawing Для этого определить переменную для приложения AutoCAD (myApp) и для активного документа (myDoc). Если AutoCAD запущен, метод GetObject возвращает объект AutoCAD Application. Если AutoCAD не запущен, то вызывается обработчик ошибок. Затем метод CreateObject пытается создать объект AutoCAD Application, как в следующем примере:
Sub ConnectToAcad() Dim acadApp As AcadApplication On Error Resume Next Set acadApp = GetObject(, "AutoCAD.Application") If Err Then Err.Clear Set acadApp = CreateObject("AutoCAD.Application") If Err Then MsgBox Err.Description Exit Sub End If MsgBox "Запушен " + acadApp.Name + " версии " + acadApp.Version End Sub ' Далее установить ссылку на Document object в приложении AutoCAD Dim acadDoc as AcadDocument Set acadDoc = acadApp.ActiveDocument
Здесь уже используем acadDoc-переменную для ссылки на текущий рисунок AutoCAD. Если запущены несколько сеансов, AutoCAD-функция GetObject возвращает первое вхождение из Windows Running Object Table (ROT) .
Следующий пример демонстрирует создание линии в VB и VBA
Sub AddLineVBA() Dim lineObj As AcadLine Dim startPoint(0 To 2) As Double,endPoint(0 To 2) As Double ' Определим начальные и конечные координаты линии startPoint(0) = 1: startPoint(1) = 1: startPoint(2) = 0 endPoint(0) = 5: endPoint(1) = 5: endPoint(2) = 0 Set lineObj = ThisDrawing.ModelSpace.AddLine (startPoint, endPoint) ZoomExtents End Sub Sub AddLineVB() On Error Resume Next ' Подключение к приложению AutoCAD Dim acadApp As AcadApplication Set acadApp = GetObject (, "AutoCAD.Application") If Err Then Err.Clear Set acadApp = CreateObject ("AutoCAD.Application") If Err Then MsgBox Err.Description Exit Sub End If ' Подключение к рисунку AutoCAD Dim acadDoc As AcadDocument Set acadDoc = acadApp.ActiveDocument Dim lineObj As AcadLine Dim startPoint(0 To 2) As Double Dim endPoint(0 To 2) As Double startPoint(0) = 1: startPoint(1) = 1: startPoint(2) = 0 endPoint(0) = 5: endPoint(1) = 5: endPoint(2) = 0 Set lineObj = acadDoc.ModelSpace.AddLine (startPoint, endPoint) ZoomExtents End Sub
Управление окружением AutoCAD
Открытие, сохранение и закрытие чертежа
Коллекция Documents и объект Document обеспечивают доступ к файловым функциям. Для этого следует использовать один из методов Add, Close, Save, SaveAs, Import, Export. Пример открытия рисунка:
Sub OpenDrawing() Dim dwgName As String dwgName = "c:\Program Files\acad2002\sample\campus.dwg" If Dir(dwgName) <> "" Then ThisDrawing.Application.Documents.Open dwgName Else MsgBox "Файл " & dwgName & " не существует." End If End Sub
Пример создания чертежа:
Sub NewDrawing() Dim docObj As AcadDocument Set docObj = ThisDrawing.Application.Documents.Add End Sub
Пример сохранения рисунка:
Sub SaveActiveDrawing() ' Сохранить рисунок с текущим именем ThisDrawing.Save ' А теперь с новым именем ThisDrawing.SaveAs "MyDrawing.dwg" End Sub
Проверка были ли в рисунке какие-то изменения с момента последнего сохранения
Sub TestIfSaved() If Not (ThisDrawing.Saved) Then If MsgBox("Сохранить изменения?", vbYesNo) = vbYes Then ThisDrawing.Save End If End Sub
Установка собственных предпочтений
Доступ к объекту Preferences
Dim acadPref as AcadPreferences Set acadPref = ThisDrawing.Application.Preferences
После чего можно получить доступ к любому объекту Preference (предпочтений) пользуясь свойствами Display, Drafting, Files, OpenSave, Output, Profile, Selection, System, и User properties. Например, сменить размер перекрестия:
acadPref.Display.CursorSize = 100
Объект database preferences включает все настройки, которые сохраняются вместе с текущим рисунком.
Управление окном приложения
Пример смены размера и положения окна, минимизация и увеличение до максимума:
Sub PositionApplicationWindow() ThisDrawing.Application.WindowTop = 0 ThisDrawing.Application.WindowLeft = 0 ThisDrawing.Application.width = 400 ThisDrawing.Application.height = 400 ThisDrawing.Application.WindowState = acMax ThisDrawing.Application.WindowState = acMin End Sub
Проверка состояния окна:
Sub CurrentWindowState() Dim CurrWindowState As Integer Dim msg As String CurrWindowState = ThisDrawing.Application.WindowState msg = Choose(CurrWindowState, "normal", "minimized", "maximized") MsgBox "Окно приложения" + msg End Sub
Сделать окно невидимым:
ThisDrawing.Application.Visible = False
Управление окном рисунка
Аналогично окну приложения можно менять размеры и подчиненного окна - чертежа, как например:
Sub CurrentWindowState() Dim CurrWindowState As Integer Dim msg As String ThisDrawing.Width = 400 ThisDrawing.Height = 400 ThisDrawing.WindowState = acMin ThisDrawing.WindowState = acMax CurrWindowState = ThisDrawing.WindowState msg = Choose(CurrWindowState, "normal", "minimized", "maximized") MsgBox "Окно документа " + msg End Sub
Использование zoom
Виды - это особые комбинации расположения, масштаба и ориентации рисунка. Команда zoom не меняет размер рисунка, она влияет только на размер его отображения на экране. AutoCAD предлагает несколько путей "зуммирования" по указанному окну, вписать рисунок в окно, указать масштаб вручную. Для "зуммирования" с указанием границ используются методы ZoomWindow или ZoomPickWindow Первый из них позволяет все сделать чисто программно, второй требует ввода границ окна от пользователя. Пример:
Sub ZoomWindow() MsgBox "Увеличение в пределах:" & vbCrLf & "1.3, 7.8, 0" & vbCrLf & "13.7, -2.6, 0" Dim point1(0 To 2) As Double Dim point2(0 To 2) As Double point1(0) = 1.3: point1(1) = 7.8: point1(2) = 0 point2(0) = 13.7: point2(1) = -2.6: point2(2) = 0 ThisDrawing.Application.ZoomWindow point1, point2 MsgBox "А теперь ZoomPickWindow" ThisDrawing.Application.ZoomPickWindow End Sub