Изменение атрибутов определения блока

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

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

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

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

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Добрый день, Коллеги!
Давно ничего не писал под AutoCAD и тут столкнулся с такой проблемой - пытаюсь поменять атрибуты у определения блока, а затем сделать AttSync.
К AttSync вопросов нет, все работает как надо, если в AutoCAD'е поменять атрибуты у определения блока, то во всех вставках все корректно работает.
А вот корректной замены атрибутов не происходит, вернее они меняются, но когда заходишь в редактор блока, то они там все пропадают, но у вставки блока они есть. Чую, что что-то не совсем корректно работает в замене атрибутов и после этого начинаются какие-то проблемы с файлом.
Код - C# [Выбрать]
  1.         public static void ChangeAttr(Document doc, string blockName, string oldValue, string NewValue)
  2.         {
  3.             Database sourceDb = doc.Database;
  4.             Editor ed = doc.Editor;
  5.             using (Transaction t = sourceDb.TransactionManager.StartTransaction())
  6.             {
  7.                 // открываем таблицу блоков
  8.                 BlockTable blockTable = t.GetObject(sourceDb.BlockTableId, OpenMode.ForWrite) as BlockTable;
  9.  
  10.                 foreach (ObjectId asObjId in blockTable)
  11.                 {
  12.  
  13.                     BlockTableRecord ent = t.GetObject(asObjId, OpenMode.ForRead) as BlockTableRecord;
  14.                     if (ent != null)
  15.                     {
  16.                         if (ent.Name != blockName)
  17.                             continue;
  18.                         ed.WriteMessage("\n Block Name" + ent.Name);
  19.                         ed.WriteMessage("\n");
  20.                         // теперь попробуем разобрать его атрибуты
  21.                         IEnumerable<AttributeDefinition> attdefs = ent.Cast<ObjectId>()
  22.                                             .Where(n => n.ObjectClass.Name == "AcDbAttributeDefinition")
  23.                                          .Select(n => (AttributeDefinition)t.GetObject(n, OpenMode.ForWrite))
  24.                                           .Where(n => !n.Constant);
  25.                         foreach (AttributeDefinition atDef in attdefs)
  26.                         {
  27.                             ed.WriteMessage("\n AttrDef Name: " + atDef.Tag + " Value: " + atDef.TextString + " Caption: " + atDef.Prompt);
  28.                             ed.WriteMessage("\n");
  29.                             // если атрибут совпадает, меняем его значение и подсказку
  30.                             if (atDef.TextString == oldValue)
  31.                             {
  32.                                 atDef.TextString = NewValue;
  33.                                 atDef.Prompt = NewValue;
  34.                             }
  35.                         }
  36.                     }
  37.                 }
  38.      
  39.                 t.Commit();
  40.             }
  41.         }
  42.  
Ах, да забыл добавить - блок динамический.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Ну если блок динамический, то (наверное) нужно менять атрибуты не только в главном блоке, но и во всех анонимных с ним связанных. И кроме того что на что ты меняешь?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Добрый день, Александр!
Спасибо за ответ, я меняю atDef.TextString и atDef.Prompt, т.е. значение атрибута и его подсказку.
Т.е. по сути мне необходимо для заданного блока поменять значение атрибута и подсказку.
А как найти все анонимно с ним связанные блоки? По аналогии с AttSync?

Отмечено как Решение JohnLennin 10-08-2017, 14:45:54

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
А как найти все анонимно с ним связанные блоки?
Код - C# [Выбрать]
  1. // получаем все анонимные блоки динамического блока
  2.         ObjectIdCollection anonymousIds = ent.GetAnonymousBlockIds();
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Спасибо Александр за наводку.
Попробовал добавить обновление связанных анонимных блоков - результат такой-же. Какие-то проблемы с файлом начинаются и атрибуты пропадают из определения блока.
Код - C# [Выбрать]
  1.         public static void ChangeAttr(Document doc, string blockName, string oldValue, string NewValue)
  2.         {
  3.             Database sourceDb = doc.Database;
  4.             Editor ed = doc.Editor;
  5.             using (Transaction t = sourceDb.TransactionManager.StartTransaction())
  6.             {
  7.                 // открываем таблицу блоков
  8.                 BlockTable blockTable = t.GetObject(sourceDb.BlockTableId, OpenMode.ForWrite) as BlockTable;              
  9.  
  10.                 foreach (ObjectId asObjId in blockTable)
  11.                 {
  12.  
  13.                     BlockTableRecord ent = t.GetObject(asObjId, OpenMode.ForRead) as BlockTableRecord;
  14.                     if (ent != null)
  15.                     {
  16.                         if (ent.Name != blockName)
  17.                             continue;
  18.                         ed.WriteMessage("\n Block Name" + ent.Name);
  19.                         ed.WriteMessage("\n");
  20.                         // теперь попробуем разобрать его атрибуты
  21.  
  22.                         foreach (ObjectId it in ent)
  23.                         {
  24.                             if (it.ObjectClass.Name == "AcDbAttributeDefinition")
  25.                             {
  26.                                 AttributeDefinition attdef = t.GetObject(it, OpenMode.ForWrite) as AttributeDefinition;
  27.                                 if (it == null || attdef.Constant)
  28.                                     continue;
  29.                                 if (attdef.TextString == oldValue)
  30.                                 {
  31.                                     attdef.UpgradeOpen();
  32.                                     attdef.TextString = NewValue;
  33.                                     attdef.Prompt = NewValue;
  34.                                 }
  35.                             }
  36.                         }
  37.                         ent.UpdateAnonymousBlocks();
  38.                         if (ent.IsDynamicBlock)
  39.                         {
  40.                             foreach (ObjectId id in ent.GetAnonymousBlockIds())
  41.                             {
  42.                                 BlockTableRecord _ent = (BlockTableRecord)t.GetObject(id, OpenMode.ForWrite);
  43.                                 //
  44.                                 foreach (ObjectId it in _ent)
  45.                                 {
  46.                                     if (it.ObjectClass.Name == "AcDbAttributeDefinition")
  47.                                     {
  48.                                         AttributeDefinition attdef = t.GetObject(it, OpenMode.ForWrite) as AttributeDefinition;
  49.                                         if (it == null || attdef.Constant)
  50.                                             continue;
  51.                                         if (attdef.TextString == oldValue)
  52.                                         {
  53.                                             attdef.UpgradeOpen();
  54.                                             attdef.TextString = NewValue;
  55.                                             attdef.Prompt = NewValue;
  56.                                         }
  57.                                     }
  58.                                 }
  59.                                 _ent.UpdateAnonymousBlocks();
  60.                             }
  61.                         }
  62.                     }
  63.                 }
  64.                 t.Commit();
  65.             }
  66.         }
  67.  
В чем может быть еще проблема?

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Если
Код - C# [Выбрать]
  1. AttributeDefinition attdef = t.GetObject(it, OpenMode.ForWrite) as AttributeDefinition;
то
Код - C# [Выбрать]
  1. attdef.UpgradeOpen();
делать нельзя.
Почему пропадают - сказать не могу. Может NewValue == ""?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Не
Код - C# [Выбрать]
  1.    if (it == null || attdef.Constant)
  2.                                     continue;
  3.  
а
Код - C# [Выбрать]
  1.    if (attdef == null || attdef.Constant)
  2.                                     continue;
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Спасибо Александр, подправил по замечаниям.
Все корректно работает на обычных блоках, а на динамических, особенно у которых несколько видимостей, происходит какая-то порча файлов.
Причем, когда заходишь в редактор блока, то появляется в командной строке куча сообщений:
Цитировать
Неописанная форма 1042
** Неописанная форма 1080
** Неописанная форма 1076
** Неописанная форма 1080
** Неописанная форма 1084
** Неописанная форма 1086
** Неописанная форма 1089
и т.д.
и зачастую AutoCAD падает после этого.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
ричем, когда заходишь в редактор блока, то появляется в командной строке куча сообщений:
Цитировать

    Неописанная форма 1042
    ** Неописанная форма 1080
    ** Неописанная форма 1076
    ** Неописанная форма 1080
    ** Неописанная форма 1084
    ** Неописанная форма 1086
    ** Неописанная форма 1089

и т.д.
и зачастую AutoCAD падает после этого.
Тут какая-то проблема со шрифтами. Ты случайно строки меняешь не на китайско/корейско/японские???
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Черт! Какая версия AutoCAD и какое значение системной переменной FIBERWORLD???
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Нет, строки обычные там даже нет символов, одни цифры, хотя имена тэгов написаны кирилицей. Еще попробовал принудительно перед запуском сделать локализацию потока на русском
Код - C# [Выбрать]
  1. System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("ru");
AutoCAD Architecture 2013,  FIBERWORLD = 1 (только чтение)
Самое интересное, что ничего не падает и все отлично работает, если перед запуском команды данный блок не имеет вставок в пространстве модели.
После применения локализации культуры вроде все заработало, только перестала корректно работать синхронизация.
Попробую с этим разбобраться.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Спасибо, Александр!

Все прекрасно заработало!
Проблема была как с анонимными блоками, так и с отладкой.
На всякий случай, если кому вдруг пригодится:
Код - C# [Выбрать]
  1.         public static void ChangeAttr(Document doc, string blockName, string oldValue, string NewValue)
  2.         {
  3.             System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("ru");
  4.  
  5.             Database sourceDb = doc.Database;
  6.             Editor ed = doc.Editor;
  7.             using (Transaction t = sourceDb.TransactionManager.StartTransaction())
  8.             {
  9.                 // открываем таблицу блоков
  10.                 BlockTable blockTable = t.GetObject(sourceDb.BlockTableId, OpenMode.ForWrite) as BlockTable;
  11.  
  12.                 foreach (ObjectId asObjId in blockTable)
  13.                 {
  14.  
  15.                     BlockTableRecord ent = t.GetObject(asObjId, OpenMode.ForRead) as BlockTableRecord;
  16.                     if (ent != null)
  17.                     {
  18.                         if (ent.Name != blockName)
  19.                             continue;
  20.                         ed.WriteMessage("\n Block Name" + ent.Name);
  21.                         ed.WriteMessage("\n");
  22.                         // теперь попробуем разобрать его атрибуты
  23.  
  24.                         foreach (ObjectId it in ent)
  25.                         {
  26.                             if (it.ObjectClass.Name == "AcDbAttributeDefinition")
  27.                             {
  28.                                 AttributeDefinition attdef = t.GetObject(it, OpenMode.ForWrite) as AttributeDefinition;
  29.                                 if (attdef == null || attdef.Constant)
  30.                                     continue;
  31.                                 if (attdef.TextString == oldValue)
  32.                                 {
  33.                                     attdef.TextString = NewValue;
  34.                                     attdef.Prompt = NewValue;
  35.                                 }
  36.                             }
  37.                         }
  38.                         ent.UpdateAnonymousBlocks();
  39.                         ent.AttSync(false, true, true);
  40.                         if (ent.IsDynamicBlock)
  41.                         {
  42.                             foreach (ObjectId id in ent.GetAnonymousBlockIds())
  43.                             {
  44.                                 BlockTableRecord _ent = (BlockTableRecord)t.GetObject(id, OpenMode.ForWrite);
  45.                                 //
  46.                                 foreach (ObjectId it in _ent)
  47.                                 {
  48.                                     if (it.ObjectClass.Name == "AcDbAttributeDefinition")
  49.                                     {
  50.                                         AttributeDefinition attdef = t.GetObject(it, OpenMode.ForWrite) as AttributeDefinition;
  51.                                         if (attdef == null || attdef.Constant)
  52.                                             continue;
  53.                                         if (attdef.TextString == oldValue)
  54.                                         {                                            
  55.                                             attdef.TextString = NewValue;
  56.                                             attdef.Prompt = NewValue;
  57.                                         }
  58.                                     }
  59.                                 }
  60.                                 _ent.UpdateAnonymousBlocks();
  61.                                 _ent.AttSync(false, true, true);
  62.                             }
  63.                         }
  64.                     }
  65.                 }
  66.                 t.Commit();
  67.             }
  68.         }

AttSync я взял отсюда:
https://sites.google.com/site/bushmansnetlaboratory/moi-zametki/attsynch