Как определить имя листа, которому принадлежит блок?

Автор Тема: Как определить имя листа, которому принадлежит блок?  (Прочитано 8215 раз)

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

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

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Добрый день, коллеги!

Ищу блоки в таблице блоков документа по имени блока методом выделения всех объектов текущего чертежа. Хочу определять имя листа, которому принадлежит блок. Есть такое свойство или метод в каком-нибудь менеджере?

Код - vb.net [Выбрать]
  1. Imports Autodesk.AutoCAD.Runtime
  2. Imports Autodesk.AutoCAD.ApplicationServices
  3. Imports Autodesk.AutoCAD.DatabaseServices
  4. Imports Autodesk.AutoCAD.EditorInput
  5. Public Class Gallurgy
  6.    <CommandMethod("SERACHINGONLYBLOCKBYNAME")>
  7.    Public Sub SERACHINGONLYBLOCKBYNAME()
  8.        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
  9.        If acDoc IsNot Nothing Then
  10.            Dim acDB As Database = acDoc.Database
  11.            Dim acEd As Editor = acDoc.Editor
  12.            Using tr = acDB.TransactionManager.StartTransaction()
  13.                Dim acSelSetPrompt As PromptSelectionResult = acEd.SelectAll
  14.                Dim acSSet = acSelSetPrompt.Value
  15.                For Each acSelSetObj As SelectedObject In acSSet
  16.                    Try
  17.                        If acSelSetObj IsNot Nothing Then
  18.                            If tr.GetObject(acSelSetObj.ObjectId, OpenMode.ForRead).GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.BlockReference" Then
  19.                                Dim blkRef As BlockReference = tr.GetObject(acSelSetObj.ObjectId, OpenMode.ForRead)
  20.                                Dim block As BlockTableRecord = Nothing
  21.                                If blkRef.IsDynamicBlock Then
  22.                                    block = tr.GetObject(blkRef.DynamicBlockTableRecord, OpenMode.ForRead)
  23.                                Else
  24.                                    block = tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead)
  25.                                End If
  26.                                If block.Name = "Рамка_v4" Then
  27.                                    MsgBox("Это блок Рамка_v4") ' Хочу здесь получить имя листа!!!
  28.                                End If
  29.                            End If
  30.                        End If
  31.                    Catch ex As Autodesk.AutoCAD.Runtime.Exception
  32.                    End Try
  33.                Next
  34.            End Using
  35.        End If
  36.    End Sub
  37. End Class

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
А разве вот это Dim acSelSetPrompt As PromptSelectionResult = acEd.SelectAll выберет все блоки во всех листах? Нет конечно! Это сработает только в том пространстве, которое в данный момент является текущим - будь это модель или лист. Значит остается только получить имя текущего листа
Код - C# [Выбрать]
  1. LayoutManager lm = LayoutManager.Current;
  2. var curLayout = lm.CurrentLayout;

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
А разве вот это Dim acSelSetPrompt As PromptSelectionResult = acEd.SelectAll выберет все блоки во всех листах? Нет конечно! Это сработает только в том пространстве, которое в данный момент является текущим - будь это модель или лист. Значит остается только получить имя текущего листа

Александр, ты только сильно не удивляйся, но я запустил этот код в чертеже (в котором 6 листов с такими блоками) из пространства модели, в котором нет блоков вообще, но мне он показал, что нашёл 6 блоков с таким именем! Не странно ли?



Любопытно!!! В справке написано,
SelectAll
Selects all objects in the current space in which are not locked or frozen. - что действительно переводится как текущее пространство, на слоях, которые не заморожены!!! Но вот ведь дикость, у меня и слои заморожены тоже!!! Но почему-то он их видит!!! Ошибка в справке или баг?

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Пашин Евгений, да, действительно так:
Цитировать
SelectAll
Selects all the objects in the drawing.
Note: Objects in all layouts and spaces are selected, and objects that are locked or frozen.
А что вам вернет BlockReference.OwnerId? Пробовали
И вот еще нашел, но не проверял:
Код - C# [Выбрать]
  1. namespace Autodesk.AutoCAD.DatabaseServices
  2. {
  3.     public static class EntityExtensions
  4.     {
  5.         public static string LayoutName(this Entity ent, Transaction tr)
  6.         {
  7.             BlockTableRecord blockTableRecord =
  8.                 (BlockTableRecord)tr.GetObject(ent.BlockId, OpenMode.ForRead);
  9.  
  10.             Layout layout =
  11.                 (Layout)tr.GetObject(blockTableRecord.LayoutId, OpenMode.ForRead);
  12.  
  13.             return layout.LayoutName;
  14.         }
  15.     }
  16. }
Пример использования:
Код - C# [Выбрать]
  1. // start transaction
  2.  
  3.     // get dbobject
  4.  
  5.     BlockReference br = (BlockReference)obj;
  6.  
  7.     string layoutName = br.LayoutName(tr);
  8.  
  9.     // commit()

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
А что вам вернет BlockReference.OwnerId?

Попробовал. Разные 13-ти значные цифры!!! По ним получается можно найти лист?

Отмечено как Решение Пашин Евгений 15-05-2017, 10:49:59

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Александр Пекшев aka Modis, идеальное решение!!! Легко и просто находятся имена листов, спасибо!!!

Код - vb.net [Выбрать]
  1.     <CommandMethod("SERACHINGONLYBLOCKBYNAME")>
  2.     Public Sub SERACHINGONLYBLOCKBYNAME()
  3.         Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
  4.         If acDoc IsNot Nothing Then
  5.             Dim acDB As Database = acDoc.Database
  6.             Dim acEd As Editor = acDoc.Editor
  7.             Using tr = acDB.TransactionManager.StartTransaction()
  8.                 Dim acSelSetPrompt As PromptSelectionResult = acEd.SelectAll
  9.                 Dim acSSet = acSelSetPrompt.Value
  10.                 For Each acSelSetObj As SelectedObject In acSSet
  11.                     Try
  12.                         If acSelSetObj IsNot Nothing Then
  13.                             If tr.GetObject(acSelSetObj.ObjectId, OpenMode.ForRead).GetType.ToString = "Autodesk.AutoCAD.DatabaseServices.BlockReference" Then
  14.                                 Dim blkRef As BlockReference = tr.GetObject(acSelSetObj.ObjectId, OpenMode.ForRead)
  15.                                 Dim block As BlockTableRecord = Nothing
  16.                                 If blkRef.IsDynamicBlock Then
  17.                                     block = tr.GetObject(blkRef.DynamicBlockTableRecord, OpenMode.ForRead)
  18.                                 Else
  19.                                     block = tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead)
  20.                                 End If
  21.                                 If block.Name = "Рамка_v4" Then
  22.                                     Dim blockTableRecord As BlockTableRecord = tr.GetObject(blkRef.OwnerId, OpenMode.ForRead) ' Очень просто находим ObjectID листа
  23.                                     If blockTableRecord.IsLayout Then
  24.                                         Dim layt As Layout = tr.GetObject(blockTableRecord.LayoutId, OpenMode.ForRead) ' Здесь его определяем по ObjectID
  25.                                         MsgBox("Это блок Рамка_v4 и находится он на листе " & layt.LayoutName) ' Сюда выводим его имя!!!
  26.                                     End If
  27.                                 End If
  28.                             End If
  29.                         End If
  30.                     Catch ex As Autodesk.AutoCAD.Runtime.Exception
  31.                     End Try
  32.                 Next
  33.             End Using
  34.         End If
  35.     End Sub

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Пашин Евгений, спасибо говорите тут =)) Я всего лишь нашел

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Интересно, а если блок будет внутри другого блока, где вывалится исключение? :)
Наверное, стоит добавить проверку на blockTableRecord.IsLayout.

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Пашин Евгений, спасибо говорите тут =)) Я всего лишь нашел

Нашёл быстро, а я и в справке и на форуме долго найти не мог!

Можно на «ты»?

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Наверное, стоит добавить проверку на blockTableRecord.IsLayout.

Один момент! Проверю!

Дмитрий, вроде вставляю другой блок в этот блок, но никаких ошибок не наблюдаю при выполнении кода. Однако, лучше не заигрывать с «законом Мерфи» и поставить проверку. Код исправил.

Всем большое спасибо за помощь!

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Ну в этом коде есть два момента.
Первый - я не знаю, выберет ли SelectAll вложенные блоки. Надо проверять, но, скорее всего, нет.
А второй:
Цитировать
вставляю другой блок в этот блок
, а надо наоборот. Блок "Рамка_v4" вставлять в какой-то другой и проверять.
В общем, в Вашем случае, возможно, эта проверка всегда будет избыточной. А вот в методе расширения LayoutName, который нашел Александр, лишней не будет.

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
, а надо наоборот. Блок "Рамка_v4" вставлять в какой-то другой и проверять.В общем, в Вашем случае, возможно, эта проверка всегда будет избыточной. А вот в методе расширения LayoutName, который нашел Александр, лишней не будет.

В любом случае я постараюсь не забыть про это.