Тема: Сохранение данных в чертеже

Хотелось бы сохранить из VBA данные (одно число Double) в самом DWG. Возможно ли это?

Re: Сохранение данных в чертеже

Если не лазить в дебри, то возможно просто вставить блок с атрибутом или текст и присвоить ему значение. Затем изменить свойство объекта visible = false

Re: Сохранение данных в чертеже

в системных переменных userr1 - userr5.

Re: Сохранение данных в чертеже

Это ненадежно и некрасиво. Следует использовать словари и содержащиеся в них X-Records. Посмотрите

а) Developer Help в самом Автокаде по XRecords,
б) темы в этом разделе форума.
в) применение -- см. объект Dictionary с исчерпывающими примерами.

Re: Сохранение данных в чертеже

Уважаемый  Александр 'Ctrl+E'
есть ли у Вас опыт сохранения в словарях:
1) коллекций (Я имею ввиду объекты VB Collection с произвольной информацией) ?
2) переменных пользовательских типов, определяемых инструкцией Type .. End Type ?
ALink

Re: Сохранение данных в чертеже

> ALink
1) Смотря с насколько произвольной информацией. Возможности словарей все равно ограничены их структурой.
Если у вас коллекция объектов, то можно написать процедуру, читающую каждое свойство объекта и записывающую ее в словарь. Или в файл.
2) То же самое.

Re: Сохранение данных в чертеже

> Александр /Ctrl E/
Про сохранение ВБА-объектов в словарях гляньте тему https://www.caduser.ru/forum/topic14869.html Что скажете ?

Re: Сохранение данных в чертеже

> 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.

Re: Сохранение данных в чертеже

Попытка систематизации сведений о словарях и их записях.
Америк я тут не открываю. Потребность собрать приведенные сведения возникла из-за неполноты и разрозненности сведений в документации 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.

Re: Сохранение данных в чертеже

> ALink
Распечатал себе вашу систематизацию и с удовольствием почитал утром по дороге на работу. Хочется ее дополнить и расширить.Кстати, наиболее полные сведения о структуре расширенных данных я нашел в свое время в книге Н.Н.Полещука "VisualLISP и секреты адаптации AutoCAD", но до сих пор так и не разобрался, насколько это применимо в VBA.

Re: Сохранение данных в чертеже

> Leonid
У Николая Полещука в соавторстве с Сергеем Зубовым в 2004 году вышла в свет изумительная книга ?САПР на базе AutoCAD ? как это делается?. Более серьезного издания по вопросам создания достаточно сложной системы ?своими руками? я не встречал ? с авторскими комментариями по каждому этапу разработки и со всеми исходными текстами программ.
Авторы являются убежденными сторонниками ЛИСПа, поэтому 98% кодов ? на ЛИСПе Думаю, что эта монография станет у лисповцев ?библией?. Авторские комментарии настолько глубоки и содержательны, что 450 руб. мне совершенно не жалко, хотя я пользуюсь только VBA, да и то время от времени.  Можно сказать, что это ?труд жизни? авторов. Первые три главы вообще читаются запоем ? подготовка к разработке САПР, анализ и постановка задачи, архитектура и базовые принципы построения системы ? эта проблематика инвариантна по отношению к конкретному инструментарию программирования.
Так вот, в главе 13 на стр. 367 есть раздел ?Как сохранять и восстанавливать собственные данные в файле рисунка?, написанный Петром Лоскутовым. Все про Xrecords и Dictionaries.
ALink

Re: Сохранение данных в чертеже

Уважаемые коллеги,
привожу код трех процедур, демонстрирующий технику сохранения в самом чертеже дескрипторов объектов Автокада с целью обеспечения многосеансовой работы.
Пользователь должен запустить на выполнение процедуру 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
'""""""""""""""""""""""