Author |
Topic |
Victorm72
Russia
7 Posts |
Posted - 07/07/2006 : 17:45:47
|
Здравствуйте, Знатоки Visio!
Задача в кратце следующая: Вывести информацию о сущностях и их связях в Excel для дальнейшего анализа.
Просмотрел Ваши посты по программированию на VBA в Visio, нашел много полезного и вывод в таблицу информации об объектах сделал, но как быть со связями? Очень хочется их тоже сохранить! :) Пример: На диаграмме есть объекты Shape: Entity.1, Entity.2 и connector.1, который их связывает, подскажите пожалуйста, как можно программно определить связи между этими объектами Shape?
С уважением, Виктор |
Edited by - Victorm72 on 07/07/2006 17:46:33 |
|
Tumanov
Russia
1198 Posts |
Posted - 07/07/2006 : 19:49:42
|
1. С точки зрения склеивания шейпы можно различить на пассивные и активные. Пассивные - это Entity.1, Entity.2. К ним клеится нечто. Активный - connector.1. Он клеится. 2. Точка склейки - это такой объект Connect. 3. У активных шейпов объекты Connect собираются в коллекцию Connects. Свойство Connect.ToCell укажет на ячейку в пассивном шейпе, к которой приклеено. Сам шейп, естественно, можно определить через Connect.ToCell.Shape. У пассивных - они же собираются в коллекцию FromConnects. Соответственно, вместо ToCell используется Connect.FromCell, а Connect.FromCell.Shape покажет шейп-коннектор. Вот и все правила. Просматриваем в шейпах коллекции Connects и FromConnects, через объекты Connect переходим на приклееные шейпы, просматриваем их коллекции и так пока не переберем все цепочки. Важно только не перепутать, когда From, когда To. |
|
|
Victorm72
Russia
7 Posts |
Posted - 07/10/2006 : 09:42:16
|
Видимо я упустил одну очень существенную деталь - у меня Visio 2000, а эти свойства, как я понял появились в Visio 2003. Как связи реализовывались в Visio 2000?
С уважением, Виктор |
|
|
Tumanov
Russia
1198 Posts |
Posted - 07/10/2006 : 12:58:03
|
Вот уж нет... Вот цитата из DVS 2000, в которой говорится о тех же самых объектах: A Shape object has two connection-related properties: • A Connects property, which returns a Connects collection that includes a Connect object for each shape, group, or guide to which that shape is glued • A FromConnects property, which returns a Connects collection that includes a Connect object for each shape, group, or guide glued to that shape |
|
|
Victorm72
Russia
7 Posts |
Posted - 07/11/2006 : 09:05:25
|
Я был не прав - подвело незнание "мат.части"... :( На моей тестовой схеме фактически не было связей - фигуры соприкосались, но линки установленны не были... Исправил и получил правильный ответ. :)
Теперь появился следующий вопрос: как определить в сторону какого объекта направленна стрелка - в какой точке начало, а в какой конец связи? есть ли для этого соответствующие признаки? |
|
|
Tumanov
Russia
1198 Posts |
Posted - 07/11/2006 : 10:10:27
|
В Visio все есть... :) Сама связь не ориентированна, но, рассматривая части коннектора, можно понять, начало это или конец. Выше уже говорилось, что Connect.ToCell (со стороны активного шейпа) укажет на ячейку в пассивном шейпе. Но можно посмотреть и на себя - Connect.FromCell покажет свою приконнекченную ячейку. Это одна из ячеек шейпа, которые доступны через шейп-лист. Значит по имени ячейки можно понять, какая это часть шейпа. То есть Connect.FromCell.Name скажет нам либо BeginX, либо EndX. Но это не лучший способ, а только иллюстрация выхода на ячейку. Точнее пользоваться свойством FromPart. Оно указывает часть шейпа, участвующую в соединении. Для коннектора Connect.FromPart даст Вам либо visBegin (константа 9), либо visEnd (константа 12). Для пассивных шейпов разнообразие констант больше, их можно посмотреть в Help на слово FromPart (ToPart). |
|
|
Victorm72
Russia
7 Posts |
Posted - 07/11/2006 : 14:54:59
|
Разобрался. Огромное спасибо! :) Но задачи усложняются... Начал работать с реальной схемой и выяснил, что в ней кроме отсутствия некоторых точек соединения присутствует еще один не очень приятный момент - надписи относящиеся к связям выполнены в виде отдельных объектов (прямоугольников с текстом) размещенных над линией связи. Как объяснили разработчики схемы это сделано из-за невозможности правильно спозиционировать текст надписи выполненный по правилам, что снижало "читаемость схемы". Есть ли возможность программно определить "визуальное перекрытие" объектов shape, а именно коннекторов (Connector) и надписей (Sheet) не прибегая к сложным геометрическим вычислениям? |
|
|
Sign
16 Posts |
Posted - 07/11/2006 : 15:49:35
|
quote: Originally posted by Victorm72
Есть ли возможность программно определить "визуальное перекрытие" объектов shape, а именно коннекторов (Connector) и надписей (Sheet) не прибегая к сложным геометрическим вычислениям?
На счет специальных возможностей не скажу. Но и без этих возможностей сложных расчетов, думаю, производить не придется. По опыту знаю, что такие надписи, как правило, стараются поставить поближе к середине соединеля. Посему задача сведется к нахождению минимального расстояния по PinX,PinY пар твоя_надпись-соединитель. Естественно соединители брать только из тех, что "ниже" твоей надписи, с учетом ориентации текста. |
|
|
Tumanov
Russia
1198 Posts |
Posted - 07/11/2006 : 16:54:52
|
Для позиционирования таких надписей в коннектор часто вводят управляющую точку, перемещением которой задается позиция текстового блока (это если не хотят пользоваться инструментом Text Block Tool). Получается и текст в шейпе и двигается он довольно легко... А в Вашем случае придется воспользоваться свойством SpatialNeighbors, которое вернет объект Selection, содержащий коллекцию шейпов, находящихся в заданной зависимости от коннектора. В данном случае наверное следует искать шейпы с отношением "visSpatialTouching". Только нужно не забыть, что приконнекченные шейпы тоже будут включены в коллекцию. Надо будет отсеять их от надписей. Скорее всего это можно сделать по типу шейпа. Вот такой код на подключенном коннекторе с дополнительной надписью возвращает троечку. Sub ttt() Dim Sel As Visio.Selection Set Sel = ActiveWindow.Selection(1).SpatialNeighbors(visSpatialTouching, 0.2, 0) Debug.Print Sel.Count End Sub |
|
|
Victorm72
Russia
7 Posts |
Posted - 07/11/2006 : 18:58:30
|
Это то что мне нужно - интересующие меня объекты я вижу! :))) Следующим шагом я хочу избавится от пересекающихся соединений, которые тоже попадают в список объектов, каким свойством объекта мне можно воспользоваться для определения типа содержащейся в объекте фигуры? Я попробовал через Master, но столкнулся с тем, что для объектов "типа" Sheet.123 (я их идентифицирую только по имени, т.к. где на самом деле тип объекта я не знаю), значение этого свойства равно Nothing, а определить это программно мне не удается - попадаю на ошибку исполнения... :(
Sub ttt() Dim Sel As Visio.Selection Set Sel = ActiveWindow.Selection(1).SpatialNeighbors(visSpatialTouching, 0.2, 0) For Each oSel In Sel If Not IsEmpty(oSel.Master) Then MsgBox (oSel.Name & " - " & oSel.Master.Name) '- здесь валимся по ошибке End If Next End Sub
На объекте который называется Sheet.123 этот код валится, т.к. для этого объекта oSel.Master=Nothing, а я к нему обращаюсь... :((( Как этого избежать? Понятно, что не обращаться к такому объекту, но как его идентифицировать? Не по имени-же? |
|
|
Tumanov
Russia
1198 Posts |
Posted - 07/11/2006 : 19:53:11
|
А почему не по имени? Все равно имя мастера включается в имя шейпа. Если набор используемых мастеров небольшой, то вполне нормально будет работать. Кстати, коннекторы у Вас не на отдельном слое? Можно было бы еще по принадлежности к слою. Хотя... по именам все равно проще. |
|
|
Victorm72
Russia
7 Posts |
Posted - 07/12/2006 : 09:05:01
|
Очень не хочется связываться с операциями со строками... К тому-же, с точки зрения программирования проводить типизацию по имени я бы отнес к не самому удачному стилю - если кому-то придет в голову создавать объекты программно, то не факт, что они будут названы так-же как при "ручном" добавлении, или я не прав? А другого способа определить тип элемента действительно не существует? Каким условием можно обойти обращение к Nothing? |
|
|
Tumanov
Russia
1198 Posts |
Posted - 07/12/2006 : 11:27:40
|
1. Visio сам создает имена. Этот процесс не зависит от того, как создается объект (вручную или программно). 2. В данном случае слово "тип" не совсем удачно. В данном случае, как я понял, нас интересует только, существует ли у шейпа прототип-мастер. 3. Можно просто спросить у него: If oSel.Master Is Nothing Then Debug.Print "Nothing" End If |
|
|
bdfy
Belarus
267 Posts |
Posted - 08/02/2009 : 20:45:20
|
задача: 1. есть несколько шейпов. 2. запускается скрипт который заменяет эти несколько шейпов одним. при этом помещает этот новый шейп в те же коорд. с тем же углом. 3. нужно еще коннекты перенести. т.е создать для нового шейпа все склейки которые были у неск. старых (ну кроме как между собой ) замена проходит примерно так
Set vs = Application.ActiveWindow.Selection
Application.ActiveWindow.Page.Drop Application.ActiveDocument.Masters.ItemU("X"), 0, 0
Set Xsh = Application.ActiveWindow.Selection
params = Array("BeginX", "BeginY", "EndX", "EndY")
For Each p In params
Xsh(1).Cells(p) = vs(1).Cells(p)
Next p
vs.Delete т.е новому шейпу задаются коорд. первого из выдел. группы (хотя надо бы всей группы по-хорошему ). нужно еще снять пассивные и активные соед. и создать их для нового шейпа. подсмотрел тут в соседней ветке функцию возвращающую соединения
Public Function ConnectedShapes(ByVal sh As Visio.Shape)
Dim Passive() As Visio.Shape
Dim Active() As Visio.Shape
'Set sh = ActiveWindow.Selection.Item(1) 'выделенный шейп
'Активные связи 2D-шейпа
If sh.Connects.Count > 0 Then 'условие наличия активных связей
For I = 1 To sh.Connects.Count 'цикл перебора всех активных связей
ReDim Preserve Active(I)
Set Active(I - 1) = sh.Connects().ToSheet 'активные связи (к чему приклеен)
' Debug.Print "active " & Active(I - 1).Name
Next
End If
'Пассивные связи 2D-шейпа
If sh.FromConnects.Count > 0 Then 'условие наличия пассивных связей
For I = 1 To sh.FromConnects.Count 'цикл перебора всех пассивных связей
ReDim Preserve Passive(I)
Set Passive(I - 1) = sh.FromConnects(I).FromSheet 'пассивные связи (какие шейпы приклеены к выделенному)
' Debug.Print "passive " & Passive(I - 1).Name
Next
End If
ConnectedShapes = Array(Active, Passive)
End Function если вызвать ar = ConnectedShapes(sh) Active = ar(0) Passive = ar(1) я получу ячейки указывающие место склейки на другой фигуре. а место склеики на обрабатываемой где искать ? |
|
|
Tumanov
Russia
1198 Posts |
Posted - 08/03/2009 : 16:13:00
|
Если Вам нужны места склейки, то цитируемый макрос не подходит. Он пользуется свойством .ToSheet, которое возвращает шейп. sh.Connects().ToSheet А у Connect есть еще свойства ToPart и FromPart. Вот они показывают именно части шейпа. |
|
|
bdfy
Belarus
267 Posts |
Posted - 08/06/2009 : 15:56:35
|
поковырял. написал такую функцию
Public Function ConnectedCells(ByVal sh As Visio.Shape)
Dim strFrom(), strTo() As String
Dim vsoConnectTo(), vsoConnectFrom() As Visio.Shape
Set vsoConnects = sh.Connects
'For each connection, get the shape it connects to
'and the part of the shape it connects to,
'and print that information in the Immediate window.
For intCounter = 0 To vsoConnects.Count - 1
ReDim Preserve strTo(intCounter + 1), vsoConnectTo(intCounter + 1)
Set vsoConnect = vsoConnects(intCounter + 1)
Set vsoConnectTo(intCounter) = vsoConnect.ToSheet
intToData = vsoConnect.ToPart
If intToData = visConnectError Then
strTo(intCounter) = "error"
ElseIf intToData = visNone Then
strTo(intCounter) = "none"
ElseIf intToData = visGuideX Then
strTo(intCounter) = "guideX"
ElseIf intToData = visGuideY Then
strTo(intCounter) = "guideY"
ElseIf intToData = visWholeShape Then
strTo(intCounter) = "dynamic glue"
ElseIf intToData >= visConnectionPoint Then
strTo(intCounter) = "connection point " & _
CStr(intToData - visConnectionPoint + 1)
Else
strTo(intCounter) = "???"
End If
'Print the name and part of the shape the
'Connect object connects to.
' Debug.Print "To " & vsoConnectTo(intCounter).Name & " " & strTo(intCounter) & "."
Next intCounter
'For each connection, get the shape it originates from
'and the part of the shape it originates from,
'and print that information in the Immediate window.
For intCounter = 0 To vsoConnects.Count - 1
ReDim Preserve strFrom(intCounter + 1), vsoConnectFrom(intCounter + 1)
Set vsoConnect = vsoConnects(intCounter + 1)
Set vsoConnectFrom(intCounter) = vsoConnect.FromSheet
intFromData = vsoConnect.FromPart
'Debug.Print "vsoFrom " & vsoConnectFrom(intCounter).Name
'FromPart property values
If intFromData = visConnectError Then
strFrom(intCounter) = "error"
ElseIf intFromData = visNone Then
strFrom(intCounter) = "none"
ElseIf intFromData = visLeftEdge Then
strFrom(intCounter) = "left"
ElseIf intFromData = visCenterEdge Then
strFrom(intCounter) = "center"
ElseIf intFromData = visRightEdge Then
strFrom(intCounter) = "right"
ElseIf intFromData = visBottomEdge Then
strFrom(intCounter) = "bottom"
ElseIf intFromData = visMiddleEdge Then
strFrom(intCounter) = "middle"
ElseIf intFromData = visTopEdge Then
strFrom(intCounter) = "top"
ElseIf intFromData = visBeginX Then
strFrom(intCounter) = "beginX"
ElseIf intFromData = visBeginY Then
strFrom(intCounter) = "beginY"
ElseIf intFromData = visBegin Then
strFrom(intCounter) = "begin"
ElseIf intFromData = visEndX Then
strFrom(intCounter) = "endX"
ElseIf intFromData = visEndY Then
strFrom(intCounter) = "endY"
ElseIf intFromData = visEnd Then
strFrom(intCounter) = "end"
ElseIf intFromData >= visControlPoint Then
strFrom(intCounter) = "controlPt_" & _
str(intFromData - visControlPoint + 1)
Else
strFrom(intCounter) = "???"
End If
' Debug.Print "From " & vsoConnectFrom(intCounter).Name & " " & strFrom(intCounter)
Next intCounter
ConnectedCells1 = Array(vsoConnectTo, strTo, vsoConnectFrom, strFrom)
If False Then 'debug
For j = 0 To UBound(ConnectedCells1) - 1
ar = ConnectedCells1(j)
text = ""
For I = 0 To UBound(ar) - 1
text = text & ar(I) & " "
Next I
'Debug.Print j & " " & text
Next j
End If
ConnectedCells = ConnectedCells1
End Function возвращает массив указывающий на активные и пассивные соедининия. насколько я понимаю то для каждой сцепки должен быть To и From shape ? тогда почему так вот странно работает прилагаемый пример ? почему для X.260 не показывается соединение с X.300 ? вот пример http://rapidshare.de/files/48047960/glue.vsd.html выделить 24ый прямоугольник ( на нем номер) , запустить aarestore_glues. макрос покажет только одну связь : 0 line 1 connection point 1 2 X.260 3 end но очевидно же что этот шейп еще к соседнему прямугольнику привязан.
|
|
|
Topic |
|
|
|