Тема: Сохранение данных в чертеже
Хотелось бы сохранить из VBA данные (одно число Double) в самом DWG. Возможно ли это?
Информационный портал для профессионалов в области САПР
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Форумы CADUser → Программирование → VBA → Сохранение данных в чертеже
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Хотелось бы сохранить из VBA данные (одно число Double) в самом DWG. Возможно ли это?
Если не лазить в дебри, то возможно просто вставить блок с атрибутом или текст и присвоить ему значение. Затем изменить свойство объекта visible = false
в системных переменных userr1 - userr5.
Это ненадежно и некрасиво. Следует использовать словари и содержащиеся в них X-Records. Посмотрите
а) Developer Help в самом Автокаде по XRecords,
б) темы в этом разделе форума.
в) применение -- см. объект Dictionary с исчерпывающими примерами.
Уважаемый Александр 'Ctrl+E'
есть ли у Вас опыт сохранения в словарях:
1) коллекций (Я имею ввиду объекты VB Collection с произвольной информацией) ?
2) переменных пользовательских типов, определяемых инструкцией Type .. End Type ?
ALink
> ALink
1) Смотря с насколько произвольной информацией. Возможности словарей все равно ограничены их структурой.
Если у вас коллекция объектов, то можно написать процедуру, читающую каждое свойство объекта и записывающую ее в словарь. Или в файл.
2) То же самое.
> Александр /Ctrl E/
Про сохранение ВБА-объектов в словарях гляньте тему https://www.caduser.ru/forum/topic14869.html Что скажете ?
> Maxim T
Давайте возьмем теорию.
Словарь представляет собой базу данных из пары код-значение, где код определяет тип данных у соотв. значения. Значит, номенклатура всего, что может быть добавлено в словарь, ограничена оными кодами.
В вашем коде
c(0) = 1
фактически не имеет смысла, поскольку такого DXF-кода для XRecord не существует.
Вывод у меня такой. Словарь по возможностям подобен текстовому файлу типа .INI, или же бумажке с ручкой -- записать туда можно что угодно, но -- ручками. Берем объект AcDbText и пишем:
c(0)=1000 q(0)="Color=ByLayer" c(1)=1000 c(1)="Layer=0"
Это, конечно, крайность, но мысль понятна. Другое дело - зачем это надо, если есть сам формат .DWG и в нем можно записать любой примитив AutoCAD.
Попытка систематизации сведений о словарях и их записях.
Америк я тут не открываю. Потребность собрать приведенные сведения возникла из-за неполноты и разрозненности сведений в документации Autodesk. Кстати, наши зарубежные "братья по разуму" мучаются точно так же. Обращаюсь к знатокам вопроса - буду очень признателен за содержательные дополнения.
С уважением, ALink
ИТАК,
Словарь как структура данных поддерживает хранение следующих типов данных:
1. AcadObject - метод AddObject
2. AcadXRecord - метод AddXRecord
3. AcadDictionary (посредством механизма ExtensionDictionary)
4. XData как общее свойство всех объектов (случай тривиальный, рассматривать не будем).
AcadObject
-----------------------
Метод AddObject для корректной работы, требует загрузки приложения ObjectARX, в котором определяется rxClassName, и регистрации имени пользовательского класса RxClassName в системном
реестре. Судя по всему, применение этого метода к объектам типа Collection полезного результата
дать не может.
AcadXRecord
-----------------------
Метод предоставляет универсальный способ хранения, вообще говоря, любых данных пользователя в виде записей XRecord в словарях любого типа - в словаре коллекции ThisDrawing.Dictionaries либо в словаре ExtensionDictionary конкретного объекта Автокада.
Механизм XRecord является наиболее элегантным способом сохранения важных для приложения данных с целью обеспечения многосеансовой работы.
Запись XRecord имеет имя. По имени XRecord извлекается в произвольном порядке. Внутри XRecord данные последовательно записываются парами целочисленный код, значение). Допустимые коды можно найти в хелпе поиском по запросу "Group Codes in Numerical Order".
В хелпе дополнительно указывается, что:
1) можно использовать любые коды с номерами ниже 1000
2) сохранение идентификаторов объектов - ObjectID - открывает возможность ссылаться на объекты Автокада, в том числе, на другие записи. В этой связи следует сделать одно замечание: обращение к объекту потребует от вас некоторой осторожности, ибо тут нет встроенного механизма отслеживания ссылочной целостности - если объект будет юзером
удален, XRecord об этом узнать "своими силами" не сможет.
Итак, чтобы извлечь пользу их XRecord, мы должны "ручками" написать процедуру "расчленения" своих объектов или структур данных, извлекающую из них содержательную информацию и сохраняющую ее "фаршем" (целочисленный код, значение) в именованных записях XRecord конкретного словаря. Восстановление данных выполняется обратным
"синтезом": из пар (код, значение) --> в структуры данных или объекты.
Скорость выборки двнных невелика - на порядок ниже скорости обращения данных из переменных VBA.
> ALink
Распечатал себе вашу систематизацию и с удовольствием почитал утром по дороге на работу. Хочется ее дополнить и расширить.Кстати, наиболее полные сведения о структуре расширенных данных я нашел в свое время в книге Н.Н.Полещука "VisualLISP и секреты адаптации AutoCAD", но до сих пор так и не разобрался, насколько это применимо в VBA.
> Leonid
У Николая Полещука в соавторстве с Сергеем Зубовым в 2004 году вышла в свет изумительная книга ?САПР на базе AutoCAD ? как это делается?. Более серьезного издания по вопросам создания достаточно сложной системы ?своими руками? я не встречал ? с авторскими комментариями по каждому этапу разработки и со всеми исходными текстами программ.
Авторы являются убежденными сторонниками ЛИСПа, поэтому 98% кодов ? на ЛИСПе Думаю, что эта монография станет у лисповцев ?библией?. Авторские комментарии настолько глубоки и содержательны, что 450 руб. мне совершенно не жалко, хотя я пользуюсь только VBA, да и то время от времени. Можно сказать, что это ?труд жизни? авторов. Первые три главы вообще читаются запоем ? подготовка к разработке САПР, анализ и постановка задачи, архитектура и базовые принципы построения системы ? эта проблематика инвариантна по отношению к конкретному инструментарию программирования.
Так вот, в главе 13 на стр. 367 есть раздел ?Как сохранять и восстанавливать собственные данные в файле рисунка?, написанный Петром Лоскутовым. Все про Xrecords и Dictionaries.
ALink
Уважаемые коллеги,
привожу код трех процедур, демонстрирующий технику сохранения в самом чертеже дескрипторов объектов Автокада с целью обеспечения многосеансовой работы.
Пользователь должен запустить на выполнение процедуру SaveDATA(), выделить мышью интересующие его объекты и нажать Enter, а затем сохранить чертеж и завершить сеанс работы Автокада. Затем загрузите Автокад снова, откройте сохраненный ранее чертеж и запустите на исполнение процедуру GetDATA(). Программа окрасит объекты, выделенные в предыдущем сеансе, в зеленый цвет acGreen.
Прошу извинения за неказистое оформление кода - форматирование убито в процессе размещения текста программы в форуме.
ALink
'=================================================
' Демонстрационный пример использования объектов
' Dictionary и XRecord
' для сохранения дескрипторов выделенных юзером объектов
' между сеансами работы в Автокаде
' ALink avova2000@mtu-net.ru
Option Explicit
'Мои "собственные" типы данных на базе DXF-кодов
Public Const ALink_INTEGER = 70
Public Const ALink_HANDLE = 5
'для сохранения других типов данных следует этот список
'обобщить на прочие типы - Double, Long, String и т.д.
'Имя моего собственного глобального словаря
'в главной коллекции Document.Dictionaries
Public Const DictName As String = "ALink_Dict"
'Имя записи (тип XRecords) в словаре DictName
Public Const XRName As String = "ALink_XRName"
'
Sub SaveDATA()
'Сохранение дескрипторов выделенных объектов в словаре DictName
'для дальнейшего использования в следующих сеансах работы с чертежом
Dim ssetObj As AcadSelectionSet
Dim Dict As AcadDictionary
Dim XR As AcadXRecord
Dim obj As AcadObject
Dim DataCode() As Integer
Dim Data() As Variant
Dim NN As Integer 'кол-во сохраняемых объектов
Dim i As Integer
'Найдем главный словарь
Set Dict = GetMainDictionary
If Dict Is Nothing Then
MsgBox "Не удалось сохранить в документе основные данные проекта."
Exit Sub
End If
'Удаляем все записи из словаря
If Dict.Count > 0 Then
For Each XR In Dict
XR.Delete
Next
End If
'дадим юзеру возможность выделить нужные объекты
Set ssetObj = ThisDrawing.SelectionSets.Add("SSET1")
ssetObj.SelectOnScreen
If ssetObj.Count = 0 Then
'ничего не выделено
ThisDrawing.SelectionSets.Item("SSET1").Delete
Exit Sub
End If
Set XR = Dict.AddXRecord(XRName)
NN = ssetObj.Count 'кол-во выделенных объектов
'подгонка размерностей массивов, в которых будут передаваться данные
ReDim DataCode(0 To NN)
ReDim Data(0 To NN)
DataCode(0) = ALink_INTEGER
Data(0) = NN
For i = 1 To NN
Set obj = ssetObj.Item(i - 1)
DataCode(i) = ALink_HANDLE
Data(i) = obj.Handle
Next i
XR.SetXRecordData DataCode, Data
ThisDrawing.SelectionSets.Item("SSET1").Delete
End Sub 'SaveDATA
'"""""""""""""""""""
Sub GetDATA()
'Извлечение данных из словаря,
'сохраненного в предущем сеансе работы
Dim ssetObj As AcadSelectionSet
Dim Dict As AcadDictionary
Dim XR As AcadXRecord
Dim obj As AcadObject
Dim ObjHandle As String ' дескриптор объекта
Dim DataCode As Variant ' <-- обратить внимание на тип
Dim Data As Variant ' <-- обратить внимание на тип
Dim NN As Integer 'кол-во объектов
Dim i As Integer
'Найдем главный словарь
Set Dict = GetMainDictionary
If Dict Is Nothing Then
MsgBox "Не найден словарь " & DictName
Exit Sub
End If
Set XR = Dict.Item(XRName)
XR.GetXRecordData DataCode, Data
NN = Data(0)
For i = 1 To NN
ObjHandle = Data(i)
Set obj = ThisDrawing.HandleToObject(ObjHandle)
'отмечаем зеленым цветом "синтезированные" объекты
obj.color = acGreen
obj.Update
Next i
End Sub 'GetDATA
'""""""""""""""""""
Function GetMainDictionary() As AcadDictionary
' Возвращает указатель на мой главный словарь
' Если словаря еще не было, то он создается
Dim Dict As AcadDictionary
'Попытка подключения к словарю
On Error GoTo СОЗДАТЬ
Set Dict = ThisDrawing.Dictionaries(DictName)
On Error GoTo 0
Set GetMainDictionary = Dict
Exit Function
СОЗДАТЬ:
If Dict Is Nothing Then 'Словарь не существует - создаем
Set Dict = ThisDrawing.Dictionaries.Add(DictName)
End If
Resume
Set GetMainDictionary = Dict
End Function 'GetMain
'""""""""""""""""""""""
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Форумы CADUser → Программирование → VBA → Сохранение данных в чертеже
Форум работает на PunBB, при поддержке Informer Technologies, Inc