Копирование поля в атрибуте блока

Автор Тема: Копирование поля в атрибуте блока  (Прочитано 7425 раз)

0 Пользователей и 3 Гостей просматривают эту тему.

Оффлайн Захаров МаксимАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 141
  • Карма: 3
Здравствуйте.
Подскажите пожалуйста. У меня есть блок с атрибутом. В атрибут добавлено поле (формула) которая вычисляет отметку Z в точке вставки блока. Если блок вставлять стандартными средствами автокада (Вставка-Блок...) то все хорошо, отметка Z в блоке отображается. А вот програмно скопировать поле я не могу. Вроде все проходит, но в место отметки отображаются ####. Может кто подправит код или пример подскажет
Код - vb.net [Выбрать]
  1. Public Function InsertBlock(ByVal InsPt As Geometry.Point3d, ByVal BlockName As String, ByVal Scl As Scale3d, ByVal lObj As String, Optional ByVal Rot As Double = 0) As DatabaseServices.ObjectId
  2.         Dim myBlockRef As BlockReference
  3.         Dim myDB As Database = HostApplicationServices.WorkingDatabase
  4.         Using myTrans As Transaction = myDB.TransactionManager.StartTransaction
  5.             Dim myBT As BlockTable = myDB.BlockTableId.GetObject(OpenMode.ForRead)
  6.             Dim myBTR As BlockTableRecord = myBT(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForWrite)
  7.             '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  8.             'Вставляем блок
  9.             Dim myBlockDef As BlockTableRecord = myBT(BlockName).GetObject(OpenMode.ForRead)
  10.             myBlockRef = New DatabaseServices.BlockReference(InsPt, myBT(BlockName))
  11.             myBlockRef.ScaleFactors = Scl
  12.             myBlockRef.Rotation = Rot
  13.             myBlockRef.Layer = lObj
  14.             myBTR.AppendEntity(myBlockRef)
  15.             myTrans.AddNewlyCreatedDBObject(myBlockRef, True)
  16.             '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  17.             'Читаем атрибуты блока
  18.             Dim myAttColl As DatabaseServices.AttributeCollection
  19.             Dim myEnt As DatabaseServices.Entity
  20.             myAttColl = myBlockRef.AttributeCollection
  21.             For Each entID As ObjectId In myBlockDef
  22.                 myEnt = entID.GetObject(OpenMode.ForWrite)
  23.                 If TypeOf myEnt Is DatabaseServices.AttributeDefinition Then
  24.                     Dim myAttDef As DatabaseServices.AttributeDefinition = myEnt
  25.                     'смотрим тег аотрибут
  26.                     Dim tagOtm As String = myAttDef.Tag
  27.                     'проверяем атрибут на наличие полей
  28.                     If myAttDef.HasFields = True Then
  29.                         Dim id As ObjectId = myAttDef.GetField()
  30.                         Dim fd As Field = myTrans.GetObject(id, OpenMode.ForWrite)
  31.                         fd.Evaluate()
  32.                         'Dim fldCode As String = fd.GetFieldCode()
  33.                         'Dim fldCode As String = "%<\AcExpr \f " & "%lu2%pr2""" & ">%"""
  34.                         'Dim myField1 As New DatabaseServices.Field(fldCode)
  35.                         'myField1.Evaluate()
  36.                         'If tagOtm Like "ОТМЕТКА_ЗЕМЛИ" Or tagOtm Like "ОТМЕТКА_ЦЕНТРА" Or tagOtm Like "ОТМЕТКА_КОЛЬЦА" Or tagOtm Like "ОТМЕТКА_ВЫСОТ" Or tagOtm Like "ОТМЕТКА_УРЕЗА_ВОДЫ" Then
  37.                         'Dim Otm As Double = Math.Round(InsPt.Z, 2)
  38.                         'myAttDef.TextString = String.Format(CultureInfo.InvariantCulture, "{0:0.00}", Otm)
  39.                         'End If
  40.                         Dim myAttRef As New DatabaseServices.AttributeReference
  41.                         myAttRef.SetField(fd)
  42.                         myAttRef.SetAttributeFromBlock(myAttDef, myBlockRef.BlockTransform)
  43.                         myAttColl.AppendAttribute(myAttRef)
  44.                         myTrans.AddNewlyCreatedDBObject(myAttRef, True)
  45.                     End If
  46.  
  47.                 End If
  48.             Next
  49.             myTrans.Commit()
  50.         End Using
  51.         Return myBlockRef.ObjectId
  52.     End Function

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Копирование поля в атрибуте блока
« Ответ #1 : 22-07-2016, 19:45:12 »
В атрибут добавлено поле (формула) которая вычисляет отметку Z в точке вставки блока
Выложи чертеж с таким блоком, чтобы было понятно. Хотя я думаю, что внутри описания блока (BlockTableRecord) ты не можешь ссылаться на точку вставки блока (BlockReference), и соотвественно должен переопределить поле во вставке атрибута (AttributeReference) так, чтобы оно указывало на точку вставки конкретного экземпляра блока.
Пример как это можно сделать посмотри здесь: Добавление полей к атрибутам блока, вставленными в пространство модели
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Захаров МаксимАвтор темы

  • ADN OPEN
  • ***
  • Сообщений: 141
  • Карма: 3
Re: Копирование поля в атрибуте блока
« Ответ #2 : 23-07-2016, 17:15:27 »
Спасибо Александр. Который раз выручаете. Да действительно, назначаю поле атрибуту, а сам атрибут и поле без ссылки на блок. Все заработало, вот код, может кому и пригодится. Один еще маленький вопрос, у меня все прекрасно работает при таком поле %<\AcObjProp Object(%<\_ObjId 8796088487056>%).InsertionPoint \f "%lu2%pt4">%
В примере на который вы ссылаетесь  %<\AcObjProp16.2 это на что то влияет?
Код - vb.net [Выбрать]
  1. Public Function InsertBlock(ByVal InsPt As Geometry.Point3d, ByVal BlockName As String, ByVal Scl As Scale3d, ByVal lObj As String, Optional ByVal Rot As Double = 0) As DatabaseServices.ObjectId
  2.         Dim myBlockRef As BlockReference = Nothing
  3.         Try
  4.             Dim myDB As Database = HostApplicationServices.WorkingDatabase
  5.             Using myTrans As Transaction = myDB.TransactionManager.StartTransaction
  6.                 Dim myBT As BlockTable = myDB.BlockTableId.GetObject(OpenMode.ForRead)
  7.                 Dim myBTR As BlockTableRecord = myBT(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForWrite)
  8.                 '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  9.                 'Вставляем блок
  10.                 Dim myBlockDef As BlockTableRecord = myBT(BlockName).GetObject(OpenMode.ForRead)
  11.                 myBlockRef = New DatabaseServices.BlockReference(InsPt, myBT(BlockName))
  12.                 myBlockRef.ScaleFactors = Scl
  13.                 myBlockRef.Rotation = Rot
  14.                 myBlockRef.Layer = lObj
  15.                 myBTR.AppendEntity(myBlockRef)
  16.                 myTrans.AddNewlyCreatedDBObject(myBlockRef, True)
  17.                 '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  18.                 'Читаем атрибуты блока
  19.                 Dim myAttColl As DatabaseServices.AttributeCollection
  20.                 Dim myEnt As DatabaseServices.Entity
  21.                 myAttColl = myBlockRef.AttributeCollection
  22.                 For Each entID As ObjectId In myBlockDef
  23.                     myEnt = entID.GetObject(OpenMode.ForWrite)
  24.                     If TypeOf myEnt Is DatabaseServices.AttributeDefinition Then 'если это атрибут
  25.                         'делаем на него ссылку
  26.                         Dim myAttDef As DatabaseServices.AttributeDefinition = myEnt
  27.                         'создаем новый атрибут
  28.                         Dim myAttRef As New DatabaseServices.AttributeReference
  29.                         'копируем значения в новый атрибут
  30.                         myAttRef.SetAttributeFromBlock(myAttDef, myBlockRef.BlockTransform)
  31.                         myAttRef.Position = myAttDef.Position.TransformBy(myBlockRef.BlockTransform)
  32.                         myAttRef.TextString = myAttDef.TextString
  33.                         myAttRef.Tag = myAttDef.Tag
  34.                         myAttColl.AppendAttribute(myAttRef)
  35.                         'проверяем атрибут на наличие поля
  36.                         If myAttDef.HasFields = True Then
  37.                             Dim id As ObjectId = myAttDef.GetField() 'смотрим старый атрибут
  38.                             Dim fd As Field = myTrans.GetObject(id, OpenMode.ForRead) 'читаем его
  39.                             Dim CodStrFiled As String = fd.GetFieldCode 'получаем код поля
  40.                             Dim StrFind As String = "InsertionPoint \f " & """" & "%lu2%pt4"
  41.                             Dim ind As Integer = CodStrFiled.IndexOf(StrFind)
  42.                             If ind <> -1 Then
  43.                                 Dim str1 As String = "%<\AcObjProp Object(%<\_ObjId "
  44.                                 Dim strID As String = myBlockRef.Id.ToString() 'получаем id вновь созданного блока
  45.                                 strID = Mid(strID, 2, strID.Length - 2) 'убираем из строки первую и последние скобки
  46.                                 Dim str2 As String = ">%).InsertionPoint \f " & """" & "%lu2%pt4%pr2" & """" & ">%"
  47.                                 Dim str As String = str1 + strID + str2
  48.                                 Dim Z As Point3d = myBlockRef.Position
  49.                                 Dim fldstr As String = String.Format(str, Z.ToString())
  50.                                 Dim field As Field = New Field(fldstr)
  51.                                 field.Evaluate()
  52.                                 Dim fieldEval As FieldEvaluationStatusResult = field.EvaluationStatus
  53.                                 If fieldEval.Status = FieldEvaluationStatus.Success Then
  54.                                     myAttRef.SetField(field)
  55.                                     myTrans.AddNewlyCreatedDBObject(field, True)
  56.                                 Else
  57.                                     Dim Otm As Double = Math.Round(InsPt.Z, 2)
  58.                                     myAttDef.TextString = String.Format(CultureInfo.InvariantCulture, "{0:0.00}", Otm)
  59.                                 End If
  60.  
  61.                             End If
  62.                         End If
  63.                         myTrans.AddNewlyCreatedDBObject(myAttRef, True)
  64.                         'If tagOtm Like "ОТМЕТКА_ЗЕМЛИ" Or tagOtm Like "ОТМЕТКА_ЦЕНТРА" Or tagOtm Like "ОТМЕТКА_КОЛЬЦА" Or tagOtm Like "ОТМЕТКА_ВЫСОТ" Or tagOtm Like "ОТМЕТКА_УРЕЗА_ВОДЫ" Then
  65.                         'Dim Otm As Double = Math.Round(InsPt.Z, 2)
  66.                         'myAttDef.TextString = String.Format(CultureInfo.InvariantCulture, "{0:0.00}", Otm)
  67.                         'End If
  68.                     End If
  69.                 Next
  70.                 myTrans.Commit()
  71.             End Using
  72.         Catch ex As Exception
  73.         End Try
  74.         Return myBlockRef.ObjectId
  75.     End Function
  76. End Class

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Копирование поля в атрибуте блока
« Ответ #3 : 23-07-2016, 19:10:34 »
Один еще маленький вопрос, у меня все прекрасно работает при таком поле %<\AcObjProp Object(%<\_ObjId 8796088487056>%).InsertionPoint \f "%lu2%pt4">%
В примере на который вы ссылаетесь  %<\AcObjProp16.2 это на что то влияет?
Должно работать и так и так. 16.2 означало версию AutoCAD (в данном случае 2006), к которой это было применимо. Но потом похоже на это перестали обращать внимание. В всяком случае когда я создаю поле "вручную" (командой _FIELD) в AutoCAD 2016, то версия (16.2) не дописывается.
Я посмотрел в реестре какие типы полей обрабатываются:
AcVar, AcVar.16.2, AcDiesel, AcObjProp, AcObjProp.16.2, AcSm, AcSm.16.2, AcExpr
Похоже, что имеющие суффикс .16.2 и не имеющие его - это одно и тоже.

P.S.: У тебя неточности в терминах:
AttributeDefinition - это не атрибут, а "определение атрибута"
AttributeReference - это атрибут (или вставка атрибута).
Поэтому "старый атрибут" и "новый атрибут" - это логически неправильно.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение