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

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > VBA. Не работает групповой код 2 (имя блока) DXF в изменённых динамических блоках.

VBA. Не работает групповой код 2 (имя блока) DXF в изменённых динамических блоках.

Ответ
Поиск в этой теме
Непрочитано 02.02.2019, 08:26 #1
VBA. Не работает групповой код 2 (имя блока) DXF в изменённых динамических блоках.
Кудахтыч
 
Регистрация: 28.01.2019
Сообщений: 62

На чертеже нужно выбрать все динамические блоки по имени блока и слою при помощи "Групповых кодов DXF в цифровой последовательности", чтобы не использовать долгие циклы перебора.
Если блок обычный или блок динамический с не изменёнными динамическими настройками, то всё работает нормально и фильтрация срабатывает корректно, но как только происходит изменение настроек динамического блока, так сразу же перестаёт работать фильтр по имени блока для изменённых блоков.
Что сделать чтобы фильтрация по gpCode(1) = 2: dataValue(1) = "Круг с прямоуг" заработала и для изменённых динамических блоков, ну или как ещё можно выбрать все динамические блоки активного чертежа по имени блока и слою без использования циклов (с циклами я и сам знаю как)?

Код:
[Выделить все]
    
    Dim APolyline As AcadLWPolyline '2D полилиния
    Dim Obj As AcadEntity 'Общий объект автокада (сущность)

    Dim ssetName As String 'Объявление переменная имени набора
    Dim ssetObj As AcadSelectionSet 'Объявление переменной набора

    ssetName = "TEST_SSET1" 'Присвоение переменной ssetName имени набора
    'On Error Resume Next
    'ThisDrawing.SelectionSets.Item(ssetName).Delete 'Удаление набора, если до этого он не был удалён в результате ошибки
    Set ssetObj = ThisDrawing.SelectionSets.Add(ssetName) 'Присвоение переменной ssetObj и добавление к активному чертежу набора выбора с именем набора переменной ssetName

    Dim mode As Integer
    mode = acSelectionSetAll

    Dim gpCode(2) As Integer
    Dim dataValue(2) As Variant
    gpCode(0) = 0: dataValue(0) = "INSERT" 'Вставка блока
    gpCode(1) = 2: dataValue(1) = "Круг с прямоуг" 'Имя блока
    gpCode(2) = 8: dataValue(2) = "Пр._Отметка низа или лотка трубы" 'Имя слоя

    Dim groupCode As Variant, dataCode As Variant
    groupCode = gpCode: dataCode = dataValue

    ssetObj.Select mode, , , groupCode, dataCode
'    ssetObj.Select mode
    If ssetObj.Count > 0 Then
    CommandButton26.Caption = ssetObj.Item(0).ObjectName & " = " & ssetObj.Count & " шт."
    Else
    CommandButton26.Caption = ssetObj.Count
    End If

'   Очистка данных
    ssetObj.Delete
    Set ssetObj = Nothing
Просмотров: 3804
 
Непрочитано 02.02.2019, 09:37
#2
maratovich


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


Никак.
Все блоки в чертеже имеют имена "*U...", поэтому берём всё и перебором сравниваем имя.
__________________
Вопрос : Где находится Тургай ? Ответ : Между Парагваем и Уругваем.....
maratovich вне форума  
 
Автор темы   Непрочитано 02.02.2019, 09:51
#3
Кудахтыч


 
Регистрация: 28.01.2019
Сообщений: 62


Цитата:
Сообщение от maratovich Посмотреть сообщение
Никак.
Все блоки в чертеже имеют имена "*U...", поэтому берём всё и перебором сравниваем имя.
Ну может есть отдельный код фильтрации для свойства блока EffectiveName, которое указывает оригинальное имя блока, а не имя уникального блока описываемое свойством Name. Так например для изменённого динамического блока получится:
ABlockReference.EffectiveName = "Круг с прямоуг"
ABlockReference.Name = "*U139"
Или Групповые коды DXF вообще не могут работать с динамическими блоками поэтому используют уникальные блоки типа "*U139" как прокладку для возможности их сохранения?
Кудахтыч вне форума  
 
Непрочитано 02.02.2019, 09:58
#4
maratovich


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


Offtop:
Цитата:
Сообщение от Кудахтыч Посмотреть сообщение
Ну может есть отдельный код фильтрации для свойства блока EffectiveName
Если кто это найдёт (на vba) - подарю лицензию без ограничения на Реверс

Цитата:
Сообщение от Кудахтыч Посмотреть сообщение
Или Групповые коды DXF вообще не могут работать с динамическими блоками
А тут разницы нет, свойства одинаковы у всех боков, только есть параметр - динамический или нет, причем в DXF его тоже нет, определяется в том же переборе.
__________________
Вопрос : Где находится Тургай ? Ответ : Между Парагваем и Уругваем.....
maratovich вне форума  
 
Автор темы   Непрочитано 02.02.2019, 10:07
#5
Кудахтыч


 
Регистрация: 28.01.2019
Сообщений: 62


Цитата:
Сообщение от maratovich Посмотреть сообщение
Offtop:
Если кто это найдёт (на vba) - подарю лицензию без ограничения на Реверс


А тут разницы нет, свойства одинаковы у всех боков, только есть параметр - динамический или нет, причем в DXF его тоже нет, определяется в том же переборе.
Ну значит все новые Автокады это просто костыли к старому DXF формату, а на новую архитектуру переходить не хотят чтобы не потерять поддержку старых продуктов и кучу клиентов с ними.
Кудахтыч вне форума  
 
Непрочитано 02.02.2019, 13:57
#6
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,041


Цитата:
Сообщение от Кудахтыч Посмотреть сообщение
Ну значит все новые Автокады это просто костыли к старому DXF формату, а на новую архитектуру переходить не хотят чтобы не потерять поддержку старых продуктов и кучу клиентов с ними
просто вы с размаху влетели лбом в очередные ограничения VBA, как и другие начинающие программисты) А дальше уже от вас зависит - пытаться ломиться дальше или выбрать более подходящие для решения ваших задач средства разработки. Например, в NetApi есть метод GetBlockReferenceIds, который позволяет получить как раз вставки указанного определения блока без перебора всего подряд. И на его основе можно написать универсальную функцию для получения Id всех вставок блока типа такой:


Код:
[Выделить все]
// AutoCAD
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;


namespace SelectDynBlocks
{
    public class CommandsClass
    {
        /// <summary>
        /// Получение списка идентификаторов вставок динблока на указанном слое
        /// </summary>
        /// <param name="aNameDefineBlock">Имя динблока</param>
        /// <param name="aNameLayer">Имя слоя</param>
        /// <param name="aAcadDb">База данных чертежа</param>
        /// <returns>Список идентификаторов вставок блока либо null</returns>
        public ObjectIdCollection GetListInsertBlock(
            string aNameDefineBlock, string aNameLayer, Database aAcadDb)
        {
            // Вспомогательная коллекция Id
            ObjectIdCollection lColIds = new ObjectIdCollection();
            // Открываем транзакцию
            using (Transaction lAcadTran = aAcadDb.TransactionManager.StartTransaction())
            {
                // Получаем таблицу слоев
                LayerTable lLayerTable = lAcadTran.GetObject(
                    aAcadDb.LayerTableId, OpenMode.ForRead) as LayerTable;
                // Если указанный слой существует
                if (lLayerTable.Has(aNameLayer))
                {
                    // Получаем идентификатор слоя
                    ObjectId lLayerId = lLayerTable[aNameLayer];
                    // Получаем таблицу блоков
                    BlockTable lBlockTable = lAcadTran.GetObject(
                        aAcadDb.BlockTableId, OpenMode.ForRead) as BlockTable;
                    // Если указанное имя динблока существует
                    if (lBlockTable.Has(aNameDefineBlock))
                    {
                        // Получаем запись таблицы блоков
                        BlockTableRecord lBlockTableRecord = lAcadTran.GetObject(
                            lBlockTable[aNameDefineBlock], OpenMode.ForRead) as BlockTableRecord;
                        // Получаем Id всех прямых вставок блока
                        ObjectIdCollection lDirectIds = 
                            lBlockTableRecord.GetBlockReferenceIds(true, true);
                        // В цикле по коллекции прямых вставок блока
                        foreach (ObjectId lDirectId in lDirectIds)
                        {
                            // Получаем вставку блока
                            BlockReference lDirectBlockRef = lAcadTran.GetObject(
                                lDirectId, OpenMode.ForRead) as BlockReference;
                            // Если данная вставка находится на заданном слое
                            if (lDirectBlockRef.LayerId.Equals(lLayerId))
                            {
                                lColIds.Add(lDirectId);
                            }
                        }
                        // Если блок динамический
                        if (lBlockTableRecord.IsDynamicBlock)
                        {
                            // Получаем Id всех анонимных блоков динамического блока
                            ObjectIdCollection lAnonymousIds = lBlockTableRecord.GetAnonymousBlockIds();
                            // В цикле по Id анонимных блоков
                            foreach (ObjectId lAnonymousId in lAnonymousIds)
                            {
                                // Получаем запись таблицы блоков для анонимного блока
                                BlockTableRecord lAnonymousBtr = lAcadTran.GetObject(
                                    lAnonymousId, OpenMode.ForRead) as BlockTableRecord;
                                // Получаем Id всех вставок данного анонимного блока
                                ObjectIdCollection lColBlockRefIds =
                                    lAnonymousBtr.GetBlockReferenceIds(true, true);
                                // В цикле по коллекции вставок данного анонимного блока
                                foreach (ObjectId lAnonymousId2 in lColBlockRefIds)
                                {
                                    // Получаем вставку блока
                                    BlockReference lAnonymousBlockRef = lAcadTran.GetObject(
                                        lAnonymousId2, OpenMode.ForRead) as BlockReference;
                                    // Если данная вставка находится на заданном слое
                                    if (lAnonymousBlockRef.LayerId.Equals(lLayerId))
                                    {
                                        lColIds.Add(lAnonymousId2);
                                    }
                                }
                            }
                        }
                    }
                }
                // Подтверждаем транзакцию
                lAcadTran.Commit();
            }
            // Возвращаем вспомогательную коллекцию
            return lColIds;
        }


        /// <summary>
        /// Выделение всех вставок указанного блока
        /// </summary>
        [CommandMethod("SelAllInsertBlock", CommandFlags.Modal | CommandFlags.Redraw)]
        public void SelAllInsertBlock()
        {
            // Получаем текущий документ, его БД и редактор
            Document lAcadDoc = Application.DocumentManager.MdiActiveDocument;
            Database lAcadDb = lAcadDoc.Database;
            Editor lAcadEd = lAcadDoc.Editor;
            // Запрашиваем вставку блока
            PromptEntityOptions lEntityOptions = new PromptEntityOptions("\nУкажите вставку блока: ");
            lEntityOptions.SetRejectMessage("\nДопустима только вставка блока ");
            lEntityOptions.AddAllowedClass(typeof(BlockReference), false);
            PromptEntityResult lSSPrompt = lAcadEd.GetEntity(lEntityOptions);
            // Если блок был выбран
            if (lSSPrompt.Status == PromptStatus.OK)
            {
                // Имя блока и его слоя 
                string lNameBlock = null;
                string lBlockNameLayer = null;
                // Открываем транзакцию
                using (Transaction lAcadTran = lAcadDb.TransactionManager.StartTransaction())
                {
                    // Получаем вставку блока
                    BlockReference lBlockReference = lAcadTran.GetObject(
                        lSSPrompt.ObjectId, OpenMode.ForRead) as BlockReference;
                    // Получаем имя блока
                    lNameBlock = (lAcadTran.GetObject(lBlockReference.IsDynamicBlock ? 
                        lBlockReference.DynamicBlockTableRecord : lBlockReference.BlockTableRecord, 
                            OpenMode.ForRead) as BlockTableRecord).Name;
                    // И имя его слоя
                    lBlockNameLayer = lBlockReference.Layer;
                    // Подтверждаем транзакцию
                    lAcadTran.Commit();
                }
                // Получаем Id всех вставок указанного блока на данном слое
                ObjectIdCollection lColIds = GetListInsertBlock(
                    lNameBlock, lBlockNameLayer, lAcadDb);
                lAcadEd.SetImpliedSelection(new ObjectId[0]);
                // Если найдена хоть одна вставка
                if (lColIds.Count > 0)
                {
                    ObjectId[] lIds = new ObjectId[lColIds.Count];
                    lColIds.CopyTo(lIds, 0);
                    lAcadEd.SetImpliedSelection(lIds);
                }
            }
        }

    }
}


Данный пример использует полученную коллекцию идентификаторов объектов лишь для выделения всех вставок данного блока на том же слое (неважно, динамический блок или обычный), а так эту коллекцию Id можно использовать для дальнейшей обработки.
Сергей812 вне форума  
 
Непрочитано 02.02.2019, 19:53
#7
Кулик Алексей aka kpblc
Moderator

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


Сергей812, а этот метод "заходит" внутрь других блоков? Ну так, просто для интересу
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 02.02.2019, 20:24
#8
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,041


Цитата:
Сообщение от Кулик Алексей aka kpblc Посмотреть сообщение
а этот метод "заходит" внутрь других блоков?
насколько понимаю из хелпа, если первый аргумент GetBlockReferenceIds directOnly=false, то будет возвращать Id и вложенных блоков при наличии. Но на практике пока не использовал в таком виде) Да и какой смысл во вложенных динблоках?
Сергей812 вне форума  
 
Непрочитано 02.02.2019, 22:16
#9
Кулик Алексей aka kpblc
Moderator

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


Я уже сталкивался с ситуациями, когда требовалось пройтись по всем вхождениям указанного динблока. Это было печально...
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 03.02.2019, 22:55
#10
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,041


Проверил, действительно при directOnly=false возвращает дополнительно идентификаторы вставок блока, внутри которых размещен искомый блок. Нашелся и подводный камень - при любом значении аргумента directOnly функция GetBlockReferenceId возвращает Id вставок искомого блока в определениях других блоков. Но это легко решаемо путем сравнения значения свойства BlockName полученного по Id вставки блока BlockReference c константами *Model_Space / *Paper_Space.
Сергей812 вне форума  
 
Автор темы   Непрочитано 04.02.2019, 05:33
#11
Кудахтыч


 
Регистрация: 28.01.2019
Сообщений: 62


Цитата:
Сообщение от Сергей812 Посмотреть сообщение
Проверил, действительно при directOnly=false возвращает дополнительно идентификаторы вставок блока, внутри которых размещен искомый блок. Нашелся и подводный камень - при любом значении аргумента directOnly функция GetBlockReferenceId возвращает Id вставок искомого блока в определениях других блоков. Но это легко решаемо путем сравнения значения свойства BlockName полученного по Id вставки блока BlockReference c константами *Model_Space / *Paper_Space.
Решил эту проблему только через цикл через цикл:
Код:
[Выделить все]
   
   For Each Obj In SelSetDinBl 'Цикл по всем объектам набора SelSetDinBl
  Set ABlockReference = Obj
  If ABlockReference.EffectiveName = nameDinBlOtm Then 'Проверка истинного имени блока EffectiveName
  End If
   Next Obj
Кудахтыч вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > VBA. Не работает групповой код 2 (имя блока) DXF в изменённых динамических блоках.

Размещение рекламы


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Имеется ли возможность ссылаться изнутри при создании блока на его же будущий номер ObjId ? Tyhig AutoCAD 6 14.08.2017 17:56
.NET C# Как правильно получить BlockDefinition зная имя блока? valerik88 .NET 12 12.05.2017 16:21
Некорректно работает операция выбор при редактировании блока. Владислав Данько AutoCAD 3 05.04.2017 09:30
Изменение единиц блока в созданных блоках Sirius2w AutoCAD 10 19.03.2015 16:56
задание имени приращению расстояния в динамических блоках olish Динамические блоки 9 09.08.2011 15:59