Получение невидимых константных атрибутов блока

Автор Тема: Получение невидимых константных атрибутов блока  (Прочитано 4323 раз)

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн AtomohodАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Здравствуйте! Такая ситуация - есть блок с константными невидимыми атрибутами (сделано намеренно чтобы не видел пользователь). Нужно достать их значения и сформировать из них строку. Возможно ли это? Я написал код, вроде бы верно, но коллекция атрибутов не заполняется.
Код - C# [Выбрать]
  1.  public static string GetBlockAttributes(ObjectId bRefId)
  2.         {
  3.             Document doc = Application.DocumentManager.MdiActiveDocument;
  4.             Editor ed = doc.Editor;
  5.             Database db = doc.Database;
  6.  
  7.             List<string> content = null;
  8.             using (Transaction tr = doc.TransactionManager.StartTransaction())
  9.             {
  10.                
  11.  
  12.                 BlockReference br = tr.GetObject(bRefId, OpenMode.ForRead) as BlockReference; // получить BlockReference
  13.                
  14.                 AttributeCollection attrIdCollection = br.AttributeCollection;
  15.  
  16.                 //
  17.                 foreach (ObjectId idAttRef in attrIdCollection)
  18.                 {
  19.                     AttributeReference att = tr.GetObject(idAttRef, OpenMode.ForRead) as AttributeReference;
  20.                     if (att.Tag.ToUpper() == "LENGTH")
  21.                     {
  22.                         content[0] = att.TextString;
  23.                     }
  24.                     if (att.Tag.ToUpper() == "WIDTH")
  25.                     {
  26.                         content[1] = att.TextString;
  27.                     }
  28.                     if (att.Tag.ToUpper() == "FILLET")
  29.                     {
  30.                         content[2] = att.TextString;
  31.                     }
  32.                     if (att.Tag.ToUpper() == "ASSEMBLY")
  33.                     {
  34.                         content[3] = att.TextString;
  35.                     }
  36.                 }
  37.  
  38.                 tr.Commit();
  39.             }
  40.             string assembliedText = string.Join(" ", content);
  41.             return assembliedText;
  42.         }

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Код - C# [Выбрать]
  1. List<string> content = null;
  2. .....
  3. content[0] = att.TextString;
Каким таким образом вы добавляете элементы в список, который null? Да еще и по индексу

Оффлайн AtomohodАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
проблема не в этом - AttributeCollection не наполняется, остальное я все пущу в переработку(индексы остались т.к. раньше был массив) и список через new создам тоже.

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Цитировать
AutoCAD itself never creates a constant AttributeReference object. AutoCAD creates the AttributeReference objects for each BlockReference based on the AttributeDefinition objects within the referenced BlockTableRecord. If a constant AttributeDefinition is encountered, then AutoCAD uses the AttributeDefinition itself instead of creating a matching AttributeReference
Тыц, тыц. И это минута в гугле =)

В общем смысл в том, что константные атрибуты хранятся не в BlockReference, а в BlockTableRecord

Оффлайн AtomohodАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Тыц, тыц. И это минута в гугле =)
одну из этих ссылок я читал, но не разобрался как подключить к коду AcadBlockReference. Я получаю object[] и пытаюсь привести его к AttributeCollection-ошибка. Как это сделать?

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Atomohod,
По аналогии с твоим кодом для константных атрибутов (код не тестировал):

Код - C# [Выбрать]
  1. public static string GetBlockConstantAttributes(ObjectId bRefId)
  2. {
  3.   Document doc = Application.DocumentManager.MdiActiveDocument;
  4.   Editor ed = doc.Editor;
  5.   Database db = doc.Database;
  6.  
  7.   List<string> content = new List<string>(4);
  8.   Dictionary<string, int> atts = new Dictionary<string, int>
  9.   {
  10.     {"LENGTH",   0},
  11.     {"WIDTH",    1},
  12.     {"FILLET",   2},
  13.     {"ASSEMBLY", 3}
  14.   };
  15.  
  16.   using (Transaction tr = doc.TransactionManager.StartTransaction())
  17.   {
  18.     // получить BlockReference
  19.     BlockReference br =
  20.       tr.GetObject(bRefId, OpenMode.ForRead) as BlockReference;
  21.     // получить его BlockTableRecord
  22.     BlockTableRecord btr =
  23.       tr.GetObject(br.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;
  24.     foreach (ObjectId id in btr)
  25.     {
  26.       if (id.ObjectClass == RXObject.GetClass(typeof(AttributeDefinition)))
  27.       {
  28.         AttributeDefinition att =
  29.           tr.GetObject(id, OpenMode.ForRead) as AttributeDefinition;
  30.         if (att.Constant && atts.ContainsKey(att.Tag.ToUpper()))
  31.         {
  32.           content[atts[att.Tag.ToUpper()]] = att.TextString;
  33.         }
  34.       }
  35.     }
  36.     tr.Commit();
  37.   }
  38.   return string.Join(" ", content);
  39. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AtomohodАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Спасибо за пример кода, до атрибутов теперь добираюсь, но хватаю исключение, что индекс за границами. Может я туплю, но ведь 3 в границах списка из четырех? См скриншот.


Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Спасибо за пример кода, до атрибутов теперь добираюсь, но хватаю исключение, что индекс за границами. Может я туплю, но ведь 3 в границах списка из четырех? См скриншот.
Вы при инициализации списка задали свойство Capacity в значение 4. Это свойство означает:
Цитировать
Возвращает или задает общее число элементов, которые может вместить внутренняя структура данных без изменения размера
Но вы не можете добавлять в список элементы, например, по индексу 2, если там ничего нет по индексам 0, 1

Отмечено как Решение Atomohod 28-11-2019, 23:38:21

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Думаю так будет правильнее (снова без проверки):
Код - C# [Выбрать]
  1. public static string GetBlockConstantAttributes(ObjectId bRefId)
  2. {
  3.   Document doc = Application.DocumentManager.MdiActiveDocument;
  4.   Editor ed = doc.Editor;
  5.   Database db = doc.Database;
  6.  
  7.   Dictionary<string, int> atts = new Dictionary<string, int>
  8.   {
  9.     {"LENGTH",   0},
  10.     {"WIDTH",    1},
  11.     {"FILLET",   2},
  12.     {"ASSEMBLY", 3}
  13.   };
  14.  
  15.   string[] content = new string[atts.Count];
  16.  
  17.   using (Transaction tr = doc.TransactionManager.StartTransaction())
  18.   {
  19.     // получить BlockReference
  20.     BlockReference br =
  21.       tr.GetObject(bRefId, OpenMode.ForRead) as BlockReference;
  22.     // получить его BlockTableRecord
  23.     BlockTableRecord btr =
  24.       tr.GetObject(br.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;
  25.     foreach (ObjectId id in btr)
  26.     {
  27.       if (id.ObjectClass == RXObject.GetClass(typeof(AttributeDefinition)))
  28.       {
  29.         AttributeDefinition att =
  30.           tr.GetObject(id, OpenMode.ForRead) as AttributeDefinition;
  31.         if (att.Constant && atts.TryGetValue(att.Tag.ToUpper(), out int i))
  32.         {
  33.           content[i] = att.TextString;
  34.         }
  35.       }
  36.     }
  37.     tr.Commit();
  38.   }
  39.   return string.Join(" ", content);
  40. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AtomohodАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Заработало! Спасибо.