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

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > VBA SelectionSet

VBA SelectionSet

Ответ
Поиск в этой теме
Непрочитано 27.02.2008, 23:59 #1
VBA SelectionSet
Mikha
 
Highway Design
 
Tver
Регистрация: 16.09.2007
Сообщений: 27

'Задача:
'Есть некоторый набор Selection as AcadSelectionSet
'Данный набор создается выбором на экране
'Selection.SelectOnScreen
'Выбор внутри полигона и т.п. не подходит
'Затем на его основе необходимо создать множество наборов по фильтру, т.е нужна функция
'Function GetSelectionByFilter(Selection As AcadSelectionSet, FilterType() As Integer, FilterData() As Variant) As AcadSelectionSet
'Смысл функции в том, чтобы один раз выбрать объекты на экране, а затем применить к ним несколько различных фильтров
'
'Есть вариант решения этой задачи с использованием фильтра c кодом 5 (Handle), но фильтр с данным кодом не работает в VBA
'Код, приведенный ниже, вызывает ошибку: Invalid argument filter list in Select
Sub f1()
Dim Selection As AcadSelectionSet
Dim FilterType(0) As Integer
Dim FilterData(0) As Variant

On Error Resume Next
ThisDrawing.SelectionSets.Item("ms").Delete
Set Selection = ThisDrawing.SelectionSets.Add("ms")
On Error GoTo 0

FilterType(0) = 5
FilterData(0) = "F5"
Selection.Select acSelectionSetAll, , , FilterType, FilterData
MsgBox Selection.Count
End Sub
'Вариант 2: можно копировать первоначально выбранные объекты в новый слой (или документ),
'a затем выбирать с помощью
'Selection.Select acSelectionSetAll, , , FilterType, FilterData
добавив в фильтр условие нахождения объектов в созданном слое (или документе)
'после выбора удалить копии объектов и новый слой (или документ)
'Вариант 3: Для каждого нового фильтра проверять каждый элемент набора в цикле
'Вариант 1 не работает, Вариант 2 и 3 при большом количестве объектов работает очень медленно.
'Как бы мне решить эту проблему?
Просмотров: 11526
 
Непрочитано 28.02.2008, 00:13
#2
Кулик Алексей aka kpblc
Moderator

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


А почему бы не сделать сам набор, а потом через For Each не проходить по нему и не выполнять нужные действия?
Возможно, в самой постановке задачи неверно что-то определено.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 28.02.2008, 00:30
#3
Mikha

Highway Design
 
Регистрация: 16.09.2007
Tver
Сообщений: 27


>>Кулик Алексей aka kpblc
То, что ты предлагаешь, я подразумевал под вариантом №3.
Количество объектов порядка 100 000, количество отдельных фильтров около 100. Работать будет очень медленно. С помощью FilterType, FilterData выбор в разы быстрее.
Mikha вне форума  
 
Непрочитано 28.02.2008, 00:35
#4
C1


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


С handel тоже не вышло. А по типу объекта работает
Код:
[Выделить все]
Sub f1()
    Dim Selection As AcadSelectionSet
    Dim FilterType(0) As Integer
    Dim FilterData(0) As Variant
    
    On Error Resume Next
    ThisDrawing.SelectionSets.Item("ms").Delete
    Set Selection = ThisDrawing.SelectionSets.Add("ms")
    On Error GoTo 0
    
    FilterType(0) = 0
    FilterData(0) = "Circle"

    'Этого не хватает:
    Dim groupCode As Variant, dataCode As Variant
    groupCode = FilterType
    dataCode = FilterData
    
    Selection.Select acSelectionSetAll, , , groupCode, dataCode
    MsgBox Selection.Count
0:
End Sub
C1 вне форума  
 
Автор темы   Непрочитано 28.02.2008, 00:49
#5
Mikha

Highway Design
 
Регистрация: 16.09.2007
Tver
Сообщений: 27


>>C1
Убрал, чего "не хватает" и "0:" в самом конце. У меня работает.
Sub f2()
Dim Selection As AcadSelectionSet
Dim FilterType(0) As Integer
Dim FilterData(0) As Variant

On Error Resume Next
ThisDrawing.SelectionSets.Item("ms").Delete
Set Selection = ThisDrawing.SelectionSets.Add("ms")
On Error GoTo 0

FilterType(0) = 0
FilterData(0) = "Circle"

Selection.Select acSelectionSetAll, , , FilterType, FilterData
MsgBox Selection.Count
End Sub
Но смысл не в этом.
Завтра выложу подробный код, чтобы было понятнее, чего хочу добиться.
Mikha вне форума  
 
Непрочитано 28.02.2008, 00:53
#6
Кулик Алексей aka kpblc
Moderator

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


Я вообще-то имел в виду следующее (при контроле, например, цвета примитива):
Код:
[Выделить все]
Public Sub fun01(ByRef selset As AcadSelectionSet)
Dim EntCount As AcadEntity
  For Each EntCount In selset
    Select Case EntCount.color
      Case 1
      Case 3
      Case 154
    End Select
  Next EntCount
End Sub
Мне почему-то кажется, что либо так надо делать, либо разбивать задачку на несколько мелких функций, в которых выполнять обработку примитивов, либо менять постановку задачи (вот бы ее услышать полностью - начиная с "зачем все это понадобилось")
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 28.02.2008, 10:24
#7
C1


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


К объекту через Handle можно добраться с помощью HandleToObject

Код:
[Выделить все]
    Dim tempObj As AcadObject
    Set tempObj = ThisDrawing.HandleToObject("2B")
    MsgBox tempObj.Handle
C1 вне форума  
 
Непрочитано 28.02.2008, 11:39
#8
Кулик Алексей aka kpblc
Moderator

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


Только фильтровать по хендлам, ИМХО - безнадега полная.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 28.02.2008, 12:14
#9
Mikha

Highway Design
 
Регистрация: 16.09.2007
Tver
Сообщений: 27


>>C1
Цитата:
К объекту через Handle можно добраться с помощью HandleToObject
Объекты мы конечно получим, но потом их нужно еще фильтровать.
>>Кулик Алексей aka kpblc
Цитата:
Только фильтровать по хендлам, ИМХО - безнадега полная.
Фильтр осуществлялся бы не только по хендлам.
1.Выбираем объекты на экране и запоминаем их хендлы
2.Формируем требуемый фильтр, добавляем в него фильтр по хендлам и выбираем все элементы чертежа:
Selection.Select acSelectionSetAll, , , FilterType, FilterData
3.Считаем то, что нам нужно
Result = Fun(Selection)
и опять шаг 2 пока не закончатся строки в таблице
Проблема в том, что фильтр с кодом 5 не работает.
>>
Вот схема того, что я хочу получить (картинкой не получилось, см. вложения)

A это рабочий вариант кода:
Код:
[Выделить все]
Private Sub bbSelect_Click()
Dim pLine As AcadLWPolyline 'Объект полилиния
Dim pPoint As Variant 'Точка указания при выборе полилинии
Dim coords As Variant 'Массив координат вершин полилинии
Dim VertexNumber As Long 'Количество вершин полилинии
Dim i As Integer 'Счетчик линий
Dim f As DistFilter 'Фильтр строки

On Error Resume Next
frmTable.Hide
ThisDrawing.Utility.GetEntity pLine, pPoint, "Укажите полилинию"
If Err.Number <> 0 Then
    Exit Sub
End If
On Error GoTo 0
'Получаем координаты полигона
coords = pLine.Coordinates
'Приводим координаты к 3D виду
coords = D2toD3(coords, 0)

For i = 0 To lstT.ListCount - 1 'Перебираем все строки в таблице
    f = MakeFilter(False, Trim(lstT.List(i, 2)), Trim(lstT.List(i, 3))) 'Создаем фильтр для строки
    'Выбираем элементы в соответствии с фильтром
    If f.CriteriaNumber = -1 Then
        Selection.SelectByPolygon acSelectionSetWindowPolygon, coords
    Else
        Selection.SelectByPolygon acSelectionSetWindowPolygon, coords, f.FilterType, f.FilterData
    End If
    'Результат записываем в таблицу
    lstT.List(i, 5) = CStr(Round(FUN1(Selection), PRECISION))
    'Сбрасываем набор и фильтр
    Selection.Clear
    ReDim f.FilterType(0) As Integer
    ReDim f.FilterData(0) As Variant
Next i
frmTable.Show
End Sub
'Все работает, но выбор объектов в данном случае осуществляется с помощью полигона, а нужен выбор на экране
'Selection.SelectOnScreen
'Думаю, что свою конкретную задачу я все-таки решу с помощью цикла, что-то вроде этого
'(работать будет медленно, но верно):
Код:
[Выделить все]
For Each Obj In Selection
    If isSpecified(Obj, f(i)) Then 'Проверяем, удовлетворяют ли свойства объекта условиям фильтра F(i)
        Result = Result + fun(Obj)
    End If
Next Obj
'При этом сама проблема осталась не решенной:
'Как применить встроенный механизм фильтрации (FilterType, FilterData) к уже существующему набору.
Вложения
Тип файла: dwg
DWG 2004
FlowChart.dwg (28.8 Кб, 1342 просмотров)
Mikha вне форума  
 
Непрочитано 28.02.2008, 12:48
#10
C1


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


Ну если работают все фильтры кроме по handle - можно же после фильтра по всем признакам кроме handle проверить по handle в обычном цикле. Или если объектов все равно останется много проверить по свойствам каждый объект отобранный через HandleToObject тоже в цикле.
C1 вне форума  
 
Непрочитано 28.02.2008, 12:51
#11
Кулик Алексей aka kpblc
Moderator

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


что за таблица? Откуда она берется и заполняется?
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 28.02.2008, 13:55
#12
Mikha

Highway Design
 
Регистрация: 16.09.2007
Tver
Сообщений: 27


>>C1
Цитата:
если работают все фильтры кроме по handle - можно же после фильтра по всем признакам кроме handle проверить по handle в обычном цикле
Хорошая идея, обязательно попробую.
>>Кулик Алексей aka kpblc
Приложение будет предназначено для определения объемов работ при строительстве линейных объектов (например установка бортовых камней, дорожных ограждений, перильных ограждений, дорожная разметка, трубопроводы и т.п.)
Таблица заполняется пользователем (или загружается из файла, если была создана ранее) и имеет следующие поля
№:
Наименование: просто строка
Имя слоя: имя слоя выбранное из списка слоев документа
Тип линии: также выбирается из списка
...
Результат: в простейшем случае просто длина линий, находящихся в слое и имеющих определенный тип линии. В более общем случае результатом будут объемы работ. Причем Объем = Fun(Длина линии)
Mikha вне форума  
 
Непрочитано 28.02.2008, 13:57
#13
Кулик Алексей aka kpblc
Moderator

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


Я бы организовывал вложенные циклы - наружний по набору; внутренний - по критериям отбора (он-то всяко короче будет). Мелькнула мысль насчет использования Collection, но я в них особо не секу
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Автор темы   Непрочитано 28.02.2008, 14:24
#14
Mikha

Highway Design
 
Регистрация: 16.09.2007
Tver
Сообщений: 27


Кулик Алексей aka kpblc
Цитата:
Я бы организовывал вложенные циклы - наружний по набору; внутренний - по критериям отбора
и плюс совет C1.
В итоге думаю поступить так:
1.Выбираем объекты на экране
Selection.SelectOnScreen
(Так как меня интересуют только длины, то тут же применим фильтр на выбор только линейных объектов),
запоминаем их Handle.
2.Формируем фильтр F(i) для строки
3.Выбираем все элементы чертежа по данному фильтру
Selection.Select acSelectionSetAll, , , FilterType, FilterData
4.В цикле сверяем Handle объекта, с теми, что запомнили в п.1:
Код:
[Выделить все]
For Each Obj In Selection
    for i = 0 to uBound(Handle)
        if Obj.handle = Handle(i) then Делаем то, что нам надо
    next i    
Next Obj
5.Переходим к п.2 и считаем новую строку
Mikha вне форума  
 
Непрочитано 09.09.2008, 15:08
#15
stas_org


 
Регистрация: 05.04.2007
Самара
Сообщений: 1,199


Объясните люди добрые, что нужно присвоить FilterType и FilterData, чтобы (к примеру) только блоки выбирались?
stas_org вне форума  
 
Непрочитано 10.09.2008, 09:27
#16
Vildar

AutoCAD
 
Регистрация: 26.07.2007
Москва
Сообщений: 1,064


0 и insert, и смотри справку по dxf-кодам
Vildar вне форума  
 
Непрочитано 10.09.2008, 09:54
#17
stas_org


 
Регистрация: 05.04.2007
Самара
Сообщений: 1,199


Не найду справку по dxf-кодам, где она?
stas_org вне форума  
 
Непрочитано 10.09.2008, 10:19
#18
Vildar

AutoCAD
 
Регистрация: 26.07.2007
Москва
Сообщений: 1,064


В справке для разработчиков.
Для блоков - ENTITIES Section -> INSERT
ну и общие коды для примитивов - Common Group Codes for Entities
Vildar вне форума  
 
Непрочитано 10.09.2008, 10:31
#19
Кулик Алексей aka kpblc
Moderator

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


DXF Reference
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 10.09.2008, 10:36
#20
stas_org


 
Регистрация: 05.04.2007
Самара
Сообщений: 1,199


У меня в справке по DXF только создание контекстных меню, межет неполная какая, так и называется DXF-коды?
stas_org вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > VBA SelectionSet

Размещение рекламы
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Пароль к VBA karp_b Программирование 24 29.08.2013 12:43
ActiveX Automation из VBA karp_b Программирование 5 14.09.2007 18:05
VBA vs LISP Kosenko Sasha LISP 23 06.03.2007 02:56
VBA пароль при открытии Dima_kr Программирование 3 05.02.2007 16:52
Не могу найти коды DXF для selectionset в VBA... ssn Программирование 4 06.12.2003 17:19