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

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

VBA. Проверка существования блока с определённым именем

Ответ
Поиск в этой теме
Непрочитано 18.09.2013, 15:10 #1
VBA. Проверка существования блока с определённым именем
swell{d}
 
гадание на конечно-элементной гуще
 
Düsseldorf
Регистрация: 31.05.2006
Сообщений: 7,596

я г..кодер, поэтому не ругайтесь сразу =)

у меня есть такой г..код для создания блока, причём он может вызываться несколько раз, а выполниться должен только один раз:
Код:
[Выделить все]
Sub st1()
    Dim item As AcadBlock, block_name As String
    block_name = "bla-bla"
    For Each item In ThisDrawing.Blocks
        If item.Name = block_name Then
            Exit Sub
        End If
    Next

    Dim block As AcadBlock, pt0(2) As Double
    Set block = ThisDrawing.Blocks.Add(pt0, block_name)
    'здесь создаём начинку блока
End Sub
я заметил, что цикл ооочень сильно подтормаживает всю программку в целом. стал разбираться, оказывается он перебирает вообще все блоки чертежа.
т.е. если у меня один и тот же блок вставлен 100500 раз, то программа перебирает 100500 элементов.
а мне-то достаточно проверить есть блок с таким названием или нет. как быть?

п.с. чтобы понимать всю степень моей "трудности" уточню - я пишу в экселе (vba) под нанокад через COM. связка эксель-нано тормозит прилично, поэтому стараюсь сократить количество обращений...
__________________
.: WikiЖБК + YouTube :.
Просмотров: 6366
 
Непрочитано 18.09.2013, 15:39
#2
Кулик Алексей aka kpblc
Moderator

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


Учитывая, что я не пишу на VBA, прошу не ругать за кривой код:
Код:
[Выделить все]
Option Explicit 

Public Function GetOrCreateBlockDef(BlockName As String) As AcadBlock
Dim res As AcadBlock
On Error GoTo lCreateBlockDef
  Set res = ThisDrawing.Blocks.Item(BlockName)
  GoTo lExit
lCreateBlockDef:
  Dim ptBase(2) As Double
  ptBase(0) = 0#: ptBase(1) = 0#: ptBase(2) = 0#
  Set res = ThisDrawing.Blocks.Add(ptBase, BlockName)
lExit:
  Set GetOrCreateBlockDef = res
End Function
 
'Проверка
Sub test()
Dim obj As AcadBlock
  Set obj = GetOrCreateBlockDef("test")
  MsgBox obj.Name
End Sub
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 18.09.2013, 16:07
#3
Дима_

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


Цитата:
Сообщение от swell{d} Посмотреть сообщение
заметил, что цикл ооочень сильно подтормаживает всю программку в целом. стал разбираться, оказывается он перебирает вообще все блоки чертежа.
т.е. если у меня один и тот же блок вставлен 100500 раз, то программа перебирает 100500 элементов.
Может и перебирает, но точно не этот фрагмент - если только 100500 разных вариантов 1-го динамического блока, у Вас он пробегается только по описаниям блоков. Снаружи действительно COM API автокада тормозят жутко (работают внутри достаточно быстро - а само каждое обращение - занимает приличное время) - посему - в Вашем случае используйте Item (как и предложенно Крысом) с проверкой ошибок (внутри он сделает все то-же самое, вряд-ли блоки у него проиндексированны, но количество обращений будет 1, а не по кол-ву блоков. Хотя тот-же пример "изнутри" предпочтительно реализовать как у Вас - т.к. выполнить с контролем ошибок это не есть хороший метод по многим причинам, а на метод проверки наличия блока в коллекции автокад не осилил видимо).
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Непрочитано 18.09.2013, 16:14
#4
hwd

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


Цитата:
Сообщение от swell{d}
если у меня один и тот же блок вставлен 100500 раз, то программа перебирает 100500 элементов.
Значит ты, скорее всего, перебираешь вхождения блоков, а нужно перебирать их определения.
Offtop:
Цитата:
Сообщение от Дима_
Снаружи действительно COM API автокада тормозят жутко (работают внутри достаточно быстро - а само каждое обращение - занимает приличное время)
Хм... Интересно, а вот если (в качестве теста) в AutoCAD подгрузить плагин (серверная часть), ожидающий (в параллельном потоке) запрос на перечисление имён определений блоков, а во внешнем приложении набросать для этого сервера клиента и обратиться к серверной части за обозначенной информацией, то какова будет разница по скорости? Передачу данных выполнять через сокеты по протоколу TCP\IP.
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:

Последний раз редактировалось hwd, 18.09.2013 в 16:23.
hwd вне форума  
 
Автор темы   Непрочитано 18.09.2013, 16:48
#5
swell{d}

гадание на конечно-элементной гуще
 
Регистрация: 31.05.2006
Düsseldorf
Сообщений: 7,596


Цитата:
Сообщение от hwd Посмотреть сообщение
Значит ты, скорее всего, перебираешь вхождения блоков, а нужно перебирать их определения.
дык, объектная модель содержит только коллекцию всех блоков чертежа.
если есть коллекция определений - подскажите, как до неё достучаться.

идею Алексея понял, сейчас попробую.
на тему скорости, вот пример видео
__________________
.: WikiЖБК + YouTube :.
swell{d} вне форума  
 
Непрочитано 18.09.2013, 16:53
#6
Дима_

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


Цитата:
Сообщение от swell{d} Посмотреть сообщение
если есть коллекция определений - подскажите, как до неё достучаться.
В Вашем примере Вы именно в нее и стучитесь.
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Непрочитано 18.09.2013, 16:55
#7
hwd

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


Цитата:
Сообщение от Дима_ Посмотреть сообщение
В Вашем примере Вы именно в нее и стучитесь.
Да, похоже на то.
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
 
Автор темы   Непрочитано 18.09.2013, 16:58
#8
swell{d}

гадание на конечно-элементной гуще
 
Регистрация: 31.05.2006
Düsseldorf
Сообщений: 7,596


Цитата:
Сообщение от Дима_ Посмотреть сообщение
В Вашем примере Вы именно в нее и стучитесь.
хм, странно. так, надо поразбираться...

добавлено:
эм. я нахожусь в некотором замешательстве. проблема вот в чём. при добавлении в чертёж одного повёрнутого размера в коллекцию блоков добавляются 2 новых объекта.
я не знаю бага это или фича, и относится ли она только к нанокаду, или в акаде так же, но суть, что количество записей в коллекции блоков значительно больше, чем их фактическое количество.
и что самое забавное, после удаления размеров, записи всё равно остаются, а "пурге" не помогает.
__________________
.: WikiЖБК + YouTube :.

Последний раз редактировалось swell{d}, 18.09.2013 в 17:36.
swell{d} вне форума  
 
Непрочитано 18.09.2013, 17:48
#9
Дима_

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


Цитата:
Сообщение от hwd Посмотреть сообщение
Хм... Интересно, а вот если (в качестве теста) в AutoCAD подгрузить плагин (серверная часть), ожидающий (в параллельном потоке) запрос на перечисление имён определений блоков, а во внешнем приложении набросать для этого сервера клиента и обратиться к серверной части за обозначенной информацией, то какова будет разница по скорости? Передачу данных выполнять через сокеты по протоколу TCP\IP.
Из паралельного потока обратится можно только к "свободному" автокаду, при достаточном количестве блоков разница будет существенной:
Внешние обращение F#:
> acad.ActiveDocument.Blocks.Count;; //получает количество через свойство Count
Real: 00:00:00.002, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val it : int = 1005
> seq {for x in acad.ActiveDocument.Blocks->x}|>Seq.length;; //то же самое но пробежкой по коллекции снаружи
Real: 00:00:04.072, CPU: 00:00:01.747, GC gen0: 0, gen1: 0, gen2: 0
val it : int = 1005
> seq {for x in acad.ActiveDocument.Blocks->x.Name}|>Seq.length;; // + еще получает имена с этих-же объектов
Real: 00:00:05.818, CPU: 00:00:01.716, GC gen0: 0, gen1: 0, gen2: 0
val it : int = 1005

Этот же сеанс из самого автокада через тот же ActiveX - лиспом:

Команда: (defun coll->list (obj / ret) (vlax-for x obj (setq ret (cons x ret))) (reverse ret))
COLL->LIST

Команда: (length (coll->list (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))))
1005 // - это количество

Команда:
((lambda (cd)
(length (coll->list (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))))
(- (getvar "cdate") cd))
(getvar "cdate"))
3.72529e-009 // время в сутках (в F# в секундах) - то есть достаточно быстро с учетом что еще список переворачивали (что для данного действия не нужно) и это интерпритатор.
В общем за это время можно и по ком-порту успеть отослать.
__________________
Когда в руках молоток все вокруг кажется гвоздями.

Последний раз редактировалось Дима_, 18.09.2013 в 17:54.
Дима_ вне форума  
 
Непрочитано 18.09.2013, 18:04
#10
Boxa

КЖ; C#
 
Регистрация: 03.11.2005
Санкт-Петербург
Сообщений: 2,611


Я с vba давно не работал, там разве нет что то на подобии
Код:
[Выделить все]
Dim coll As New Collection
If coll.Contains("block_name") = True Then
End If
Boxa вне форума  
 
Непрочитано 18.09.2013, 18:32
#11
Олег (jr.)

специалист по околачиванию грушевых деревьев
 
Регистрация: 14.09.2004
Pietari, Venäjä
Сообщений: 811


Попробуй так, не будет быстрее?
Код:
[Выделить все]
'' by Dick Kusleika http://dailydoseofexcel.com/
Public Function BlockExists(blockName As String) As Boolean
Dim blkDef As AcadBlock
On Error Resume Next
Set blkDef = ThisDrawing.Blocks(blockName)
BlockExists = (Err.Number = 0)
End Function
Олег (jr.) вне форума  
 
Автор темы   Непрочитано 18.09.2013, 18:40
#12
swell{d}

гадание на конечно-элементной гуще
 
Регистрация: 31.05.2006
Düsseldorf
Сообщений: 7,596


ну примерно так и сделал:
Код:
[Выделить все]
Sub st1()
    On Error GoTo ErrorHandler
    Dim block_name As String
    block_name = "bla-bla"
    Dim tmp_block As IAcadBlock
    Set tmp_block = ThisDrawing.blocks.item(block_name)
Exit Sub
ErrorHandler:
    Select Case Err.Number
        Case -2145386470
            Dim block As IAcadBlock, pt0(2) As Double
            Set block = ThisDrawing.blocks.Add(pt0, block_name)

'здесь начинка блока

    End Select
End Sub
стало заметно бодрее отрисовываться
__________________
.: WikiЖБК + YouTube :.
swell{d} вне форума  
 
Непрочитано 18.09.2013, 18:48
#13
Олег (jr.)

специалист по околачиванию грушевых деревьев
 
Регистрация: 14.09.2004
Pietari, Venäjä
Сообщений: 811


Потому что выражение:
ThisDrawing.blocks.item(block_name)
сразу определяет наличие блока в таблице BlockTable
Олег (jr.) вне форума  
 
Непрочитано 04.12.2014, 16:16
#14
p_sh

новичок
 
Регистрация: 19.06.2005
Ярославль
Сообщений: 3,396


нужно name добавить
b_string = ThisDrawing.Blocks.Item("blname").name
p_sh вне форума  
 
Автор темы   Непрочитано 04.12.2014, 16:23
#15
swell{d}

гадание на конечно-элементной гуще
 
Регистрация: 31.05.2006
Düsseldorf
Сообщений: 7,596


куда чего зачем добавить?
__________________
.: WikiЖБК + YouTube :.
swell{d} вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > VBA. Проверка существования блока с определённым именем



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проблема с базовой точкой блока и вхождением блока в DXF nogaems Программирование 5 29.08.2013 15:46
AutoCAD 2013 Rus SP2 СПДС при проверке _audit находит и исправляет ошибки но, повторная проверка опять указывает на тоже zoro ПО от CSoft 10 06.08.2013 00:33
Проверка существования текстового стиля. acidburst Программирование 24 09.03.2010 00:03
Обновление/замена блока с таким же именем из другого файла. Pesec AutoCAD 2 11.11.2009 19:33