Опубликован: 21.02.2012 | Уровень: специалист | Доступ: свободно
Лекция 8:

Программирование на VBA

Аннотация: Язык VBA предоставляет широкие возможности программирования в среде AutoCAD. В лекции показана возможность управления окружением AutoCAD и даны технологии создания и редактирования слоев и объектов. Разбирается работа с текстом и размерностями, с блоками и листами, с трехмерными поверхностями и сплошными 3D объектами.

Цель лекции: изучить принципы и конкретные технологии программирования на VBA.

Введение. Обзор команд. Объектная модель

Введение

Интерфейс AutoCAD ActiveX/VBA дает некотoрые преимущества по сравнению с другими методами создания приложений AutoCAD:

  1. Высокая скорость выполнения процесса, так как в отличие от AutoLISP-приложений выполнение команд происходит внутри процесса;
  2. Простота использования, обусловленная простотой языка программирования;
  3. Большие возможности межпрограмного обмена, так как 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
Алексей Тимонин
Алексей Тимонин
Что возвращает функция chr() в таком примере (chr (- 65 1))?
Алексей Потапкин
Алексей Потапкин
как передать параметры в макрос
Александр Яковлев
Александр Яковлев
Россия, г. Москва
Александр Захаров
Александр Захаров
Россия, Рязань