Удаление всех внешних ссылок

Автор Тема: Удаление всех внешних ссылок  (Прочитано 13099 раз)

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

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Здравствуйте.
Нашел способ удаления всех внешних ссылок лишь перебором всего в модели, нахождения внешних ссылок и удаления каждой методом DetachXRef
есть ли проще?
Спасибо

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Удаление всех внешних ссылок
« Ответ #1 : 23-11-2018, 16:48:46 »
есть ли проще?
А как ты себе представляешь это "проще"?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение simson43 23-11-2018, 17:08:18

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Удаление всех внешних ссылок
« Ответ #2 : 23-11-2018, 16:50:57 »
Какой-нибудь метод Database.RemoveAllXrefs(), наверное :)

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Удаление всех внешних ссылок
« Ответ #3 : 23-11-2018, 17:08:09 »
Какой-нибудь метод Database.RemoveAllXrefs(), наверное :)
Работает, спасибо!)

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Удаление всех внешних ссылок
« Ответ #4 : 26-11-2018, 12:33:42 »
я к тому, что делать итерацию внутри XrefGraph, наверное, быстрее чем внутри модели...

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Удаление всех внешних ссылок
« Ответ #5 : 26-11-2018, 14:37:13 »
Не факт, надо проверять. Никто не гарантирует, что "внутри", при формировании XrefGraph, не используется тот же самый проход по всем объектам чертежа.

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Удаление всех внешних ссылок
« Ответ #6 : 26-11-2018, 15:20:53 »
ну да если сравнивать цифры во время отладки то они одинаковые...
в таком варианте хотя бы код поприятнее.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Удаление всех внешних ссылок
« Ответ #7 : 26-11-2018, 15:22:32 »
Никто не гарантирует, что "внутри", при формировании XrefGraph, не используется тот же самый проход по всем объектам чертежа.
Нет. Зачем? И вообще проще просканировать BlockTable на предмет нахождения в ней BlockTableRecord, соответствующим внешним ссылкам и для них выполнить DetachXref.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Удаление всех внешних ссылок
« Ответ #8 : 26-11-2018, 16:30:11 »
а как из btr вытащить слой? только BlockReference получать?

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Удаление всех внешних ссылок
« Ответ #9 : 26-11-2018, 16:34:04 »
И вообще проще просканировать BlockTable на предмет нахождения в ней BlockTableRecord, соответствующим внешним ссылкам и для них выполнить DetachXref.
Насколько я понимаю, нужно будет ещё дополнительно проверить, что эта внешняя ссылка не является вложенной в другую.
Кстати, а возможна же ситуация, когда внешняя ссылка вложена в блок чертежа? Тогда, получается, простая итерация по объектам модели или листов недостаточна. Надо ещё внутрь всех блоков входить... Маловероятно, конечно, что кто-то будет внешнюю ссылку в блок пихать. Но чего только не встретишь в реальности :)

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Удаление всех внешних ссылок
« Ответ #10 : 26-11-2018, 16:34:22 »
а как из btr вытащить слой?
А кто-то в теме спрашивал про слой? Как нибудь определись с тем, что тебе нужно.
Если тебе нужно удалить только те внешние ссылки, которые вставлены на определённый слой (или слои), то конечно нужно анализировать вставки (BlockReference), а не Xref (BlockTableRecord). Тем не менее найти все BlockReference, которые относятся к данной BlockTableRecord без сканирования всей базы можно при помощи метода BlockTableRecord.GetBlockReferenceIds
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Удаление всех внешних ссылок
« Ответ #11 : 26-11-2018, 16:35:48 »
Тогда, получается, простая итерация по объектам модели или листов недостаточна.
Конечно.
Насколько я понимаю, нужно будет ещё дополнительно проверить, что эта внешняя ссылка не является вложенной в другую.
Думаю, что да.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Удаление всех внешних ссылок
« Ответ #12 : 26-11-2018, 16:38:29 »
А может это и неважно. Возможно, что ничего страшного не случится, если "детачить" вложенную ссылку. Хотя, я бы на такое не надеялся :)
Надо проверять, тестировать...

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Удаление всех внешних ссылок
« Ответ #13 : 28-11-2018, 14:56:12 »
А кто-то в теме спрашивал про слой? Как нибудь определись с тем, что тебе нужно.
мне нужно удалить то все! но если они лежат в заблокированном слое, то его нужно разблокировать сначала. а для этого узнать что за слой! так ведь?

а вот если проходить по BlockTable, то мне нужно открывать по ObjectId каждый btr и проверять что это внешняя ссылка?

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Удаление всех внешних ссылок
« Ответ #14 : 28-11-2018, 14:59:39 »
но если они лежат в заблокированном слое, то его нужно разблокировать сначала. а для этого узнать что за слой! так ведь?
Не нужно, если открывать объект с соответствующей опцией forceOpenOnLockedLayer: http://help.autodesk.com/view/OARX/2018/ENU/?guid=OREFNET-Autodesk_AutoCAD_DatabaseServices_Transaction_GetObject_ObjectId_Autodesk_AutoCAD_DatabaseServices_OpenMode__MarshalAsUnmanagedType_U1__bool__MarshalAsUnmanagedType_U1__bool

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Удаление всех внешних ссылок
« Ответ #15 : 28-11-2018, 15:04:55 »
опа! вот это здорово! спасибо!

второй вопрос еще актуален

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Удаление всех внешних ссылок
« Ответ #16 : 28-11-2018, 15:06:59 »
а вот если проходить по BlockTable, то мне нужно открывать по ObjectId каждый btr и проверять что это внешняя ссылка?
второй вопрос еще актуален
А какие ещё есть варианты? Вроде как, иного пути нет.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Удаление всех внешних ссылок
« Ответ #17 : 28-11-2018, 15:16:03 »
А кто-то в теме спрашивал про слой? Как нибудь определись с тем, что тебе нужно.
мне нужно удалить то все! но если они лежат в заблокированном слое, то его нужно разблокировать сначала. а для этого узнать что за слой! так ведь?

а вот если проходить по BlockTable, то мне нужно открывать по ObjectId каждый btr и проверять что это внешняя ссылка?
Тут я бы рекомендовал запомнить состояние слоёв и все разблокировать, выполнить удаление внешних ссылок а затем восстановить состояние слоёв.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Удаление всех внешних ссылок
« Ответ #18 : 28-11-2018, 15:17:20 »
что то не нашел у btr соответствующих свойств, кроме статуса внешней ссылки. как определить что это внешняя ссылка(любая)? неужели перебирать все статусы в условии?
можно не отвечать.. понял
« Последнее редактирование: 28-11-2018, 16:03:49 от simson43 »

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Удаление всех внешних ссылок
« Ответ #19 : 28-11-2018, 15:27:20 »
IsFromExternalReference
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Удаление всех внешних ссылок
« Ответ #20 : 28-11-2018, 15:33:17 »
это не то же самое?
Код - C# [Выбрать]
  1. if (btrXRef.XrefStatus != XrefStatus.NotAnXref)
« Последнее редактирование: 28-11-2018, 16:04:01 от simson43 »

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Удаление всех внешних ссылок
« Ответ #21 : 28-11-2018, 16:26:13 »
а вот сейчас я окончательно запутался.
попробовал просто найти все BlockTableRecord внешних ссылок и удалил. без обратки слоев. и он удалил даже в заблокированном!
так и долнжо быть? изначально он так не мог.
причем без этого
соответствующей опцией forceOpenOnLockedLayer

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Re: Удаление всех внешних ссылок
« Ответ #22 : 28-11-2018, 16:36:00 »
попробовал просто найти все BlockTableRecord внешних ссылок и удалил. без обратки слоев. и он удалил даже в заблокированном!
так и долнжо быть?
Ну так удалены же были определения блоков. Это не графические объекты, они не располагаются на слоях. А до этого, наверное, удалялись вставки блоков - это уже графические объекты, которые могут располагаться на слоях. Удивительно, что удаление определения блока при наличии в чертеже вставок происходит без ошибок. Я бы расценивал это как подарок от API :)

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Удаление всех внешних ссылок
« Ответ #23 : 28-11-2018, 16:39:58 »
я и в прошлый раз "детачил" внешние ссылки, а не удалял вставки.. но как ты напоролся на ошибку из-за слоя...
может я опять что то путаю - не исключено

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Удаление всех внешних ссылок
« Ответ #24 : 28-11-2018, 19:56:29 »
Я проверил этот код в AutoCAD 2019:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5. using System.Collections.Generic;
  6.  
  7. #pragma warning disable 0618
  8.  
  9. // This line is not mandatory, but improves loading performances
  10. [assembly: CommandClass(typeof(Rivilis.ScanXrefs))]
  11.  
  12. namespace Rivilis
  13. {
  14.   public class ScanXrefs
  15.   {
  16.     [CommandMethod("RemoveAllXrefs")]
  17.     public void RemoveAllXrefs()
  18.     {
  19.       Document doc = Application.DocumentManager.MdiActiveDocument;
  20.       if (doc == null) return;
  21.       Editor ed = doc.Editor;
  22.       Database db = doc.Database;
  23.       List<ObjectId> idsXref = new List<ObjectId>();
  24.       using (BlockTable bt = db.BlockTableId.Open(OpenMode.ForRead) as BlockTable)
  25.       {
  26.         foreach (ObjectId idBtr in bt)
  27.         {
  28.           using (BlockTableRecord btr = idBtr.Open(OpenMode.ForRead) as BlockTableRecord)
  29.           {
  30.             if (btr.IsFromExternalReference)
  31.               idsXref.Add(idBtr);
  32.           }
  33.         }
  34.       }
  35.       foreach (ObjectId idBtr in idsXref)
  36.         db.DetachXref(idBtr);
  37.     }
  38.   }
  39. }

Он удаляет все вставки внешних ссылок, а затем и описания блоков внешних ссылок, если вставки непосредственно в модели/листе. Но если они внутри блока, то мы видим сообщение:
Цитировать
Xref 1 has multiple references. Not detached.
Так что правильно сначала удалить все вставки внешних ссылок, а затем уже их "детачить" внешние ссылки.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Удаление всех внешних ссылок
« Ответ #25 : 28-11-2018, 20:23:51 »
Вот так должно быть универсальнее. Потестируй:

Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5. using System.Collections.Generic;
  6.  
  7. #pragma warning disable 0618
  8.  
  9. // This line is not mandatory, but improves loading performances
  10. [assembly: CommandClass(typeof(Rivilis.ScanXrefs))]
  11.  
  12. namespace Rivilis
  13. {
  14.   public class ScanXrefs
  15.   {
  16.     [CommandMethod("RemoveAllXrefs")]
  17.     public void RemoveAllXrefs()
  18.     {
  19.       Document doc = Application.DocumentManager.MdiActiveDocument;
  20.       if (doc == null) return;
  21.       Editor ed = doc.Editor;
  22.       Database db = doc.Database;
  23.       List<ObjectId> idsXref = new List<ObjectId>(); // Внешние ссылки
  24.       List<ObjectId> idsLocked = new List<ObjectId>(); // Блокированные слои
  25.       // Отбираем блокированные слои и сразу их разблокируем
  26.       using (LayerTable lt = db.LayerTableId.Open(OpenMode.ForRead) as LayerTable)
  27.       {
  28.         foreach (ObjectId idLay in lt)
  29.         {
  30.           using (LayerTableRecord ltr = idLay.Open(OpenMode.ForRead) as LayerTableRecord)
  31.           {
  32.             if (ltr.IsLocked)
  33.             {
  34.               ltr.UpgradeOpen();
  35.               ltr.IsLocked = false;
  36.               idsLocked.Add(idLay);
  37.             }
  38.           }
  39.         }
  40.       }
  41.       // Отбираем внешние ссылки
  42.       using (BlockTable bt = db.BlockTableId.Open(OpenMode.ForRead) as BlockTable)
  43.       {
  44.         foreach (ObjectId idBtr in bt)
  45.         {
  46.           using (BlockTableRecord btr = idBtr.Open(OpenMode.ForRead) as BlockTableRecord)
  47.           {
  48.             if (btr.IsFromExternalReference)
  49.               idsXref.Add(idBtr);
  50.           }
  51.         }
  52.       }
  53.       // Удаляем внешние ссылки
  54.       foreach (ObjectId idBtr in idsXref)
  55.       {
  56.         using (BlockTableRecord btr = idBtr.Open(OpenMode.ForRead) as BlockTableRecord)
  57.         {
  58.           // Находим все вставки внешних ссылок и удаляем их
  59.           ObjectIdCollection idsBrefs = btr.GetBlockReferenceIds(false, true);
  60.           foreach (ObjectId idBref in idsBrefs)
  61.             using (DBObject bref = idBref.Open(OpenMode.ForWrite))
  62.               bref.Erase();
  63.         }
  64.         // Удаляем саму внешнюю ссылку
  65.         db.DetachXref(idBtr);
  66.       }
  67.       // Блокируем слои, которые были заблокированы до запуска команды
  68.       // но небыли удалены при удалении внешних ссылок
  69.       foreach (ObjectId idLay in idsLocked)
  70.           if (!idLay.IsErased)
  71.           using (LayerTableRecord ltr = idLay.Open(OpenMode.ForWrite) as LayerTableRecord)
  72.             ltr.IsLocked = true;
  73.     }
  74.   }
  75. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Удаление всех внешних ссылок
« Ответ #26 : 28-11-2018, 20:32:31 »
Ну и по подсказке Дмитрий Загорулькин можно сократить код на сохранение/восстановление блокировки слоёв:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Runtime;
  5. using System.Collections.Generic;
  6.  
  7. #pragma warning disable 0618
  8.  
  9. // This line is not mandatory, but improves loading performances
  10. [assembly: CommandClass(typeof(Rivilis.ScanXrefs))]
  11.  
  12. namespace Rivilis
  13. {
  14.   public class ScanXrefs
  15.   {
  16.     [CommandMethod("RemoveAllXrefs")]
  17.     public void RemoveAllXrefs()
  18.     {
  19.       Document doc = Application.DocumentManager.MdiActiveDocument;
  20.       if (doc == null) return;
  21.       Editor ed = doc.Editor;
  22.       Database db = doc.Database;
  23.       List<ObjectId> idsXref = new List<ObjectId>(); // Внешние ссылки
  24.  
  25.       // Отбираем внешние ссылки
  26.       using (BlockTable bt = db.BlockTableId.Open(OpenMode.ForRead) as BlockTable)
  27.       {
  28.         foreach (ObjectId idBtr in bt)
  29.         {
  30.           using (BlockTableRecord btr = idBtr.Open(OpenMode.ForRead) as BlockTableRecord)
  31.           {
  32.             if (btr.IsFromExternalReference)
  33.               idsXref.Add(idBtr);
  34.           }
  35.         }
  36.       }
  37.       // Удаляем внешние ссылки
  38.       foreach (ObjectId idBtr in idsXref)
  39.       {
  40.         using (BlockTableRecord btr = idBtr.Open(OpenMode.ForRead) as BlockTableRecord)
  41.         {
  42.           // Находим все вставки внешних ссылок и удаляем их
  43.           ObjectIdCollection idsBrefs = btr.GetBlockReferenceIds(false, true);
  44.           foreach (ObjectId idBref in idsBrefs)
  45.             // Открываем с учетом возможных блокированных слоёв
  46.             using (DBObject bref = idBref.Open(OpenMode.ForWrite,false,true))
  47.               bref.Erase();
  48.         }
  49.         // Удаляем саму внешнюю ссылку
  50.         db.DetachXref(idBtr);
  51.       }
  52.     }
  53.   }
  54. }

У меня работает.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Удаление всех внешних ссылок
« Ответ #27 : 28-11-2018, 22:20:03 »
Но если они внутри блока

Вы имеете ввиду именно блок? Не внутри другой внешней ссылки?
Если первое то не встречал такого.

Еще что примечательно, если перебирать XrefGraph, там хранятся удаленные внешние ссылки и тогда при попытке удалить вылетает исключение, при переборе BlockTable такой беды нет, поэтому я остановился на похожем на первый ваш вариант.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Удаление всех внешних ссылок
« Ответ #28 : 28-11-2018, 22:25:23 »
Вы имеете ввиду именно блок? Не внутри другой внешней ссылки?
Если первое то не встречал такого.
Именно в блоке. Запускаешь команду БЛОК (_BLOCK), выделяешь внешнюю ссылку (можешь еще что-то выбрать  - не важно). Вот у тебя вставка внешней ссылки в блоке. Вообще-то вложенность может быть любой.
Еще что примечательно, если перебирать XrefGraph, там хранятся удаленные внешние ссылки и тогда при попытке удалить вылетает исключение
Проверять нужно удалена или нет...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • ****
  • Сообщений: 411
  • Карма: 9
Re: Удаление всех внешних ссылок
« Ответ #29 : 28-11-2018, 23:36:26 »
Ну да можно и так.
 Александр Ривилис, Дмитрий Загорулькин, Спасибо за ответы!