VBA Как узнать общее количество блоков ?
| Правила | Регистрация | Пользователи | Сообщения за день |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > VBA Как узнать общее количество блоков ?

VBA Как узнать общее количество блоков ?

Ответ
Поиск в этой теме
Непрочитано 27.02.2013, 20:59 #1
VBA Как узнать общее количество блоков ?
maratovich
 
г. Самара
Регистрация: 12.07.2009
Сообщений: 2,437

Вопрос простой - сколько блоков в чертеже ?
После выполнения кода получаю 9 шт. а в реальности 30. (поправка :ошибочка вышла, их 27)
Код:
[Выделить все]
Private Sub CommandButton1_Click()
Dim i As Long
Dim objEnt As AcadEntity
i = 0
For Each objEnt In ThisDrawing.ModelSpace
    If objEnt.ObjectName = "AcDbBlockReference" Then
       i = i + 1
    End If
Next
MsgBox i
End Sub

Вложения
Тип файла: dwg
DWG 2007
Блоки.dwg (65.0 Кб, 3118 просмотров)


Последний раз редактировалось maratovich, 28.02.2013 в 12:15. Причина: Поправка
Просмотров: 7734
 
Непрочитано 27.02.2013, 21:36
#2
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,404


В чертеже, в пространстве модели или в файле? Вхождений блоков или их описаний? Учитывать ли вложенные блоки? Как обрабатывать внешние ссылки?
И ради интересу сначала руками выполни команду _.qselect и посмотри на количество вхождений блоков в пространстве модели.

---
Добавлено:
Код:
[Выделить все]
Option Explicit

Public Function GetBlockReferences(Optional bCheckSubEnt As Boolean = True) As Long
Dim lRes As Long
Dim oBlockDef As AcadBlock
Dim oEnt As AcadEntity
  If bCheckSubEnt Then
    For Each oBlockDef In ThisDrawing.Blocks
      If oBlockDef.IsXRef = False Then
          For Each oEnt In oBlockDef
            If oEnt.ObjectName = "AcDbBlockReference" Then
              lRes = lRes + 1
            End If
          Next
      End If
    Next
  Else
    For Each oEnt In ThisDrawing.ModelSpace
       If oEnt.ObjectName = "AcDbBlockReference" Then
              lRes = lRes + 1
            End If
    Next
  End If
  GetBlockReferences = lRes
End Function

Public Sub test()
  MsgBox "Включая вложенные: " & CStr(GetBlockReferences)
  MsgBox "Только пространство модели : " & CStr(GetBlockReferences(False))
End Sub
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.

Последний раз редактировалось Кулик Алексей aka kpblc, 27.02.2013 в 21:49.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 27.02.2013, 21:42
#3
maratovich


 
Регистрация: 12.07.2009
г. Самара
Сообщений: 2,437
Отправить сообщение для maratovich с помощью Skype™


В пространстве модели.
Описаний.
Учитывать вложенные блоки.
Конечный результат должен быть = 30
Сколько видно - столько и есть в модели. (при размороженных и включенных слоях)
Вот эти 30 получить и не могу. Как ?
maratovich вне форума  
 
Непрочитано 27.02.2013, 21:50
#4
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,404


Я неверный код там написал... По логике: проходишь по всем примитивам пространства модели. Если примитив блок, то получить его описание, пройтись по всем его примитивам. Если внутри блока тоже блок, то...
Рекурсия чистой воды. Сейчас попробую нарисовать
P.S. Гоняй, тестируй. Но откуда ты взял 30 штук, когда их у меня получилось 27 - не пойму. Что я сделал: разморозил и разблокировал все слои, выбрал все блоки (9 штук), разбил. Выбрал все блоки (12 штук), разбил. Выбрал все блоки (6 штук), разбил. 9+12+6=27.
Или у меня с логикой что-то не то?
Код:
[Выделить все]
Option Explicit

Public Function GetBlockReferencesByOwner(objOwner As AcadBlock) As Long
Dim lRes As Long
Dim oEnt As AcadEntity
  lRes = 0
  For Each oEnt In objOwner
    If oEnt.ObjectName = "AcDbBlockReference" Then
      lRes = lRes + 1 + GetBlockReferencesByOwner(ThisDrawing.Blocks.Item(oEnt.Name))
    End If
  Next
  GetBlockReferencesByOwner = lRes
End Function

Public Function GetBlockReferences(Optional bCheckSubEnt As Boolean = True) As Long
Dim lRes As Long
Dim oBlockDef As AcadBlock
Dim oEnt As AcadEntity
  lRes = 0
  If bCheckSubEnt Then
    For Each oBlockDef In ThisDrawing.Blocks
      If oBlockDef.IsXRef = False Then
          For Each oEnt In oBlockDef
            If oEnt.ObjectName = "AcDbBlockReference" Then
              lRes = lRes + 1 + GetBlockReferencesByOwner(ThisDrawing.Blocks.Item(oEnt.Name))
            End If
          Next
      End If
    Next
  Else
    For Each oEnt In ThisDrawing.ModelSpace
      If oEnt.ObjectName = "AcDbBlockReference" Then
        lRes = lRes + 1
      End If
    Next
  End If
  GetBlockReferences = lRes
End Function

Public Sub test()
  MsgBox "Включая вложенные: " & CStr(GetBlockReferencesByOwner(ThisDrawing.ModelSpace))
  MsgBox "Только пространство модели : " & CStr(GetBlockReferences(False))
End Sub
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.

Последний раз редактировалось Кулик Алексей aka kpblc, 27.02.2013 в 21:59.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 27.02.2013, 22:12
#5
maratovich


 
Регистрация: 12.07.2009
г. Самара
Сообщений: 2,437
Отправить сообщение для maratovich с помощью Skype™


Цитата:
Сообщение от Кулик Алексей aka kpblc Посмотреть сообщение
Или у меня с логикой что-то не то?
Вы правы ! Это я заработался. Там их 27.
Спасибо огромное !
А я то лез перебирать все внутри каждого блока....
Код:
[Выделить все]
For Each ACADObjectVModele In VibranieObiekti 'ThisDrawingModSpace
If ACADObjectVModele.ObjectName = "AcDbBlockReference" Then 
.............действие
   Set ACADObjectBlok2 = ThisDrawing.Blocks(ACADObjectVModele.Name)
   For Each ACADObjectVModele2 In ACADObjectBlok2
   If ACADObjectVModele2.ObjectName = "AcDbBlockReference" Then 
.............действие
И это уходило в бесконечный цикл.
Ещё раз спасибо !

Теперь буду пытаться считать атрибуты для каждого блока, хотя они у каждого вложения будут разные (хоть имя одинаковое) но надеюсь считаются как надо.
maratovich вне форума  
 
Непрочитано 28.02.2013, 08:00
#6
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
В пространстве модели.
Описаний.
Две взаимоисключающие записи. Если "В пространстве модели", то речь явно о вхождениях блоков. Если "Описаний", то пространство тут ни к месту, т.к. эти самые "описания" хранятся в таблице блоков, а не в конкретном пространстве. Судя по тому, что делает Алексей, и как радостно ликует топикстартер - речь всё же не об описаниях, а о вхождениях.

Цитата:
Сообщение от Кулик Алексей aka kpblc Посмотреть сообщение
Что я сделал: разморозил и разблокировал все слои, выбрал все блоки (9 штук), разбил. Выбрал все блоки (12 штук), разбил. Выбрал все блоки (6 штук), разбил.
Почему не захотел просто выполнить итерацию имеющихся записей в таблице блоков, отфильтровав лишнее? Насколько я помню, в определении блока имеется свойство в котором содержится коллекция идентификаторов, указанных на вхождения этого блока. Т.о. можно было бы всё выполнить очень просто, безо всяких там рекурсий - банально пересчитать общее количество таких идентификаторов.
Цитата:
Теперь буду пытаться считать атрибуты для каждого блока, хотя они у каждого вложения будут разные (хоть имя одинаковое) но надеюсь считаются как надо.
Возможно эта информация будет интересной.
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:

Последний раз редактировалось hwd, 28.02.2013 в 08:05.
hwd вне форума  
 
Автор темы   Непрочитано 28.02.2013, 09:08
#7
maratovich


 
Регистрация: 12.07.2009
г. Самара
Сообщений: 2,437
Отправить сообщение для maratovich с помощью Skype™


И Вам спасибо, но
Цитата:
Сообщение от hwd Посмотреть сообщение
Т.о. можно было бы всё выполнить очень просто, безо всяких там рекурсий - банально пересчитать общее количество таких идентификаторов.
Таи используется ObjectId , а это надо делать версии по х32 и 64 отдельно. Нехотелось бы.
Цитата:
Сообщение от hwd Посмотреть сообщение
Возможно эта информация будет интересной.
Мои познания не настолько глубоки в .net
Поэтому ответ Кулик Алексей aka kpblc полностью удовлетворил вопрос.
maratovich вне форума  
 
Непрочитано 28.02.2013, 09:12
#8
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
Сообщение от maratovich Посмотреть сообщение
Таи используется ObjectId , а это надо делать версии по х32 и 64 отдельно. Нехотелось бы.
На VBA не проверял, но на .NET в данном случае компилировать отдельно под x86/x64 не нужно, достаточно "AnyCPU". Я же не предлагал использовать OldIdPtr, зависящий от разрядности ПО.
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
 
Непрочитано 28.02.2013, 09:46
#9
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,404


Цитата:
Сообщение от hwd Посмотреть сообщение
Почему не захотел просто выполнить итерацию имеющихся записей в таблице блоков, отфильтровав лишнее?
Хотел проверить вручную, каков должен быть реузультат.
Цитата:
Сообщение от hwd Посмотреть сообщение
Насколько я помню, в определении блока имеется свойство в котором содержится коллекция идентификаторов, указанных на вхождения этого блока.
На лиспе подобное я видел, но это а) на лиспе; б) попытки, показанные здесь, показали, что не все так просто как хотелось бы (правда, опять же - на лиспе).
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 28.02.2013, 10:31
#10
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
Сообщение от Кулик Алексей aka kpblc Посмотреть сообщение
показанные здесь
По указанной ссылке все изображения битые. Или это только у меня не отображаются?
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
 
Непрочитано 28.02.2013, 10:40
#11
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,404


Сейчас все равно ничего исправить не могу - дома посмотрю
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 28.02.2013, 10:46
#12
maratovich


 
Регистрация: 12.07.2009
г. Самара
Сообщений: 2,437
Отправить сообщение для maratovich с помощью Skype™


Цитата:
Сообщение от hwd Посмотреть сообщение
Или это только у меня не отображаются?
Открылось нормально. Мозила, Вин 7.
P.S. Изображений нет (картинок).
maratovich вне форума  
 
Непрочитано 28.02.2013, 10:49
#13
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
Сообщение от maratovich Посмотреть сообщение
Открылось нормально. Мозила, Вин 7.
P.S. Изображений нет (картинок).
А я разве писал, что сама ссылка битая?
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
 
Непрочитано 28.02.2013, 11:03
#14
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,839


Цитата:
Сообщение от hwd Посмотреть сообщение
в определении блока имеется свойство в котором содержится коллекция идентификаторов, указанных на вхождения этого блока.
Это где такое???
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Непрочитано 28.02.2013, 11:04
#15
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,404


Через DXF найти можно. Может быть, через .NET тоже - не знаю...
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 28.02.2013, 11:11
#16
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,839


Offtop: Так тут вроде про VBA разговор...
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Непрочитано 28.02.2013, 11:12
#17
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
Сообщение от Дима_ Посмотреть сообщение
Это где такое???
Смотрел BlockTableRecord.GetBlockReferenceIds? Возможно на VBA есть что-то подобное.
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
 
Непрочитано 28.02.2013, 11:21
#18
trir


 
Регистрация: 18.12.2010
Сообщений: 5,107


нету
trir вне форума  
 
Непрочитано 28.02.2013, 11:30
#19
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
Сообщение от Кулик Алексей aka kpblc Посмотреть сообщение
Но откуда ты взял 30 штук, когда их у меня получилось 27 - не пойму.
А у меня следующий код показывает 23 вхождения блока, а не 27 и не 30.
Код:
[Выделить все]
App.Document doc = cad.DocumentManager.MdiActiveDocument;
Db.Database db = doc.Database;
Ed.Editor ed = doc.Editor;
Int32 count = 0; /* общее количество вхождений блоков */
using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {
    Db.BlockTable bt = tr.GetObject(db.BlockTableId, Db.OpenMode.ForRead) as Db.BlockTable;
    foreach (Db.ObjectId id in bt) {
        Db.BlockTableRecord btr = tr.GetObject(id, Db.OpenMode.ForRead) as Db.BlockTableRecord;
        Db.ObjectIdCollection refs = btr.GetBlockReferenceIds(false, false);
        ed.WriteMessage("\nБлок '{0}': {1}", btr.Name, refs.Count);
        count += refs.Count;
    }                
    tr.Commit();
}
ed.WriteMessage("\nBlock references count: {0}\n", count);
Результат работы кода такой:
Цитата:
Блок '*Model_Space': 0
Блок '*Paper_Space': 0
Блок '*Paper_Space0': 0
Блок 'Блок1': 13
Блок 'Блок2': 7
Блок 'Блок3': 3
Block references count: 23
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:

Последний раз редактировалось hwd, 28.02.2013 в 12:01.
hwd вне форума  
 
Непрочитано 28.02.2013, 12:02
#20
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,404


hwd, еще раз скачай вложение и проверь, что должно получиться при ручном расчете / обработке.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 28.02.2013, 12:10
#21
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
Сообщение от Кулик Алексей aka kpblc Посмотреть сообщение
hwd, еще раз скачай вложение и проверь, что должно получиться при ручном расчете.
Как показывает практика - сегодня повторно скачивать бесполезно. Это уже на следующий день нужно качать.

UPD
Если выполнить прямую итерацию по базе данных, то получаю вообще 13 вхождений:
Код:
[Выделить все]
App.Document doc = cad.DocumentManager.MdiActiveDocument;
Db.Database db = doc.Database;
Ed.Editor ed = doc.Editor;
Int32 count = 0; /* общее количество вхождений блоков */
using (Db.Transaction tr = db.TransactionManager.StartTransaction()) {                
    Db.Handle handle = default(Db.Handle);
    Db.ObjectId id = Db.ObjectId.Null;
    for (Int64 i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++) {
        handle = new Db.Handle(i);                    
        Boolean result = db.TryGetObjectId(handle, out id);
        if (result && id.IsValid && !id.IsErased && id.ObjectClass.Name.Equals("AcDbBlockReference",
            StringComparison.CurrentCulture)) {
            Db.BlockReference btr = tr.GetObject(id, Db.OpenMode.ForRead) as Db.BlockReference;     
            ed.WriteMessage("\nВхождение блока '{0}'", btr.Name);
            ++count;
        }
    }
    tr.Commit();
}

ed.WriteMessage("\nBlock references count: {0}\n", count);
Результат работы такой:
Цитата:
Вхождение блока 'Блок1'
Вхождение блока 'Блок2'
Вхождение блока 'Блок3'
Вхождение блока 'Блок1'
Вхождение блока 'Блок2'
Вхождение блока 'Блок2'
Вхождение блока 'Блок3'
Вхождение блока 'Блок3'
Вхождение блока 'Блок1'
Вхождение блока 'Блок1'
Вхождение блока 'Блок2'
Вхождение блока 'Блок1'
Вхождение блока 'Блок1'
Block references count: 13
Странно. И это всё при том, что блоки даже не параметрические и не аннотативные.
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:

Последний раз редактировалось hwd, 28.02.2013 в 13:36. Причина: Добавил информацию.
hwd вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > VBA Как узнать общее количество блоков ?



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Каким образом узнать длину нескольких динамических блоков ie.spb Динамические блоки 40 10.08.2021 13:25
Где узнать на какое количество машин расчитан гараж? sima Прочее. Архитектура и строительство 77 15.01.2009 13:43
VBA - как узнать закрытый ли контур To Thuc Программирование 4 18.06.2007 16:55
как узнать сколько блоков в чертеже определенного имени? ilka_t AutoCAD 11 22.07.2005 10:57
как узнать сколько layout в файле текущем DWG файле VBA sf Программирование 1 09.03.2005 12:36