Форум пользователей Visio

Форум по вопросам применения и программирования в Visio
Текущее время: 23 ноя 2017, 20:43

Часовой пояс: UTC + 3 часа [ Летнее время ]


Правила форума


При размещении файлов предпочтительным является формат vsd (а не vsdx/vsdm)



Начать новую тему Ответить на тему  [ Сообщений: 15 ] 
Автор Сообщение
 Заголовок сообщения: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 25 авг 2017, 20:47 
Здравствуйте
Пишу VBA-макрос Visio для формирования текстового описания VISIO-схемы бизнес-процесса (EPC-схема).
Один из элементов описания - связи операции бизнес-процесса, входящие (условия исполнения операции) и исходящие (возможные решения исполнителя операции).
Нужно узнать наличие и параметры стрелки на каждой стороне линии, соединяющей операцию с соседними элементами.
Все элементы схемы получаю. Множество всех линий, связанных с каждым элементом тоже получаю и все пары связанных фигур определить могу. Но мне нужно направление каждой связи, а я не нашел элементы объектной модели, описывающие стрелки на линиях!
Прошу помощи. Полагаю, не знаю "базовых" принципов построения объектной модели Visio. В схемах возможно применение элементов множества типов. У каждого типа свои индивидуальные свойства и состав типов можно расширять, конструировать самостоятельно. Как VBA работает с элементами, описание которых имеет неизвестную заранее структуру? Все элементы составные из множества элементов и самый "нижний" уровень - базовые элементы? Если предположение верное, то стрелка на линии есть множество элементов (линии и/или треугольники и т.д.). Пытался найти, но не смог. Кроме того, для меня важно знать на какой стороне (на связи с каким соседним элементом) находится стрелка...
Спасибо!


Пожаловаться на это сообщение
Вернуться к началу
  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 25 авг 2017, 21:48 
Не в сети
Administrator

Зарегистрирован: 30 авг 2009, 11:02
Сообщений: 990
Очков репутации: 100578

Добавить очки репутацииУменьшить очки репутации
Цитата:
? Если предположение верное, то стрелка на линии есть множество элементов (линии и/или треугольники и т.д.).

Чаще всего неверное.
Вот на картинке показано, как управлять стрелками через шейп-лист (ShapeSheet).
Макрос как раз так и должен действовать.


Вложения:
arrow.gif
arrow.gif [ 67.23 Кб | Просмотров: 170 ]
Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 25 авг 2017, 21:51 
Не в сети
Administrator

Зарегистрирован: 30 авг 2009, 11:02
Сообщений: 990
Очков репутации: 100578

Добавить очки репутацииУменьшить очки репутации
Вот так устанавливается третий тип стрелки в начало линии.
Код:
Sub ttt()
    Dim sh As Visio.Shape
    Set sh = ActivePage.Shapes(1)
    sh.Cells("BeginArrow") = 3
End Sub

То есть в ячейку с именем "BeginArrow" записывается код типа стрелки.
Оттуда же можно и прочитать значение. Примерно так:
Код:
Debug.Print sh.Cells("BeginArrow")


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 25 авг 2017, 21:57 
Не в сети
Administrator

Зарегистрирован: 30 авг 2009, 11:02
Сообщений: 990
Очков репутации: 100578

Добавить очки репутацииУменьшить очки репутации
Цитата:
Как VBA работает с элементами, описание которых имеет неизвестную заранее структуру?

Программист старается такого не допускать.
Если объект сложный и собран из множества шейпов, то стараются данные вынести куда-нибудь в доступное именованное место, чтобы программа могла с ними общаться.
Чаще всего это user-defined секция или ShapeData.
А если большой чертеж нарисовать одними черточками, то пытаться его обработать программно практически бесполезно.


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 25 авг 2017, 22:38 
Не в сети
Ветеран
Аватара пользователя

Зарегистрирован: 28 апр 2013, 14:03
Сообщений: 547
Откуда: Вена, Австрия
Использую Visio c: 1998
Очков репутации: 100603

Добавить очки репутацииУменьшить очки репутации
К сожалению здесь все не так просто.
В Visio все соединители направленные, даже те, что не имеют никаких стрелок. Также направление соединителя "по объектной модели" может противоречить стрелкам.
У каждого соединителя есть "Begin" и "End". Стрелки в объектной модели считаются элементами декора, поэтому могут располагаться произвольно.

Так что во первых нужно решить, как ты хочешь определять направление коннектора - согласно объектной модели или же согласно стрелкам.

API довольно простой, и он есть:

shape.ConnectedShapes (<направление>)

Но он ориентируется вовсе не по стрелкам.
Для "стрелок" нужно выбрать, какие именно тебе интересны. Их куча. Например если вот такие "стрелки", куда направлено соединение?

Изображение

Мы использовали примерно вот такой вот код для определения "направления"
(числа - наше определение что является "стрелкой", определяющей направление коннектора):

Код:
enum Direction
{
   Direction_None   = 0,
   Direction_To   = 1,
   Direction_From   = 2,
   Direction_Both   = 3,
};

long GetArrowDirection(IVShapePtr shape, short side)
{
   IVCellPtr arrow_cell   = shape->GetCellsSRC(visSectionObject, visRowLine, side);
   bstr_t arrow_text      = arrow_cell->GetResultStr(long(visNone));
   long arrow            = _ttol(arrow_text);

   struct ArrowDirection { short begin; short end; short direction; };

   // Visio arrow codes
   static const ArrowDirection arrow_directions[] =
   {
      { 0,   0,   Direction_None },
      { 1,   8,   Direction_To   },
      { 9,   11,   Direction_From   },
      { 12,   19,   Direction_To   },
      { 20,   26,   Direction_From   },
      { 27,   30,   Direction_To   },
      { 31,   38,   Direction_From   },
      { 39,   40,   Direction_To   },
      { 41,   42,   Direction_From   },
      { 43,   45,   Direction_To   },
   };

   for (size_t i = 0; i < countof(arrow_directions); ++i)
   {
      const ArrowDirection& rec = arrow_directions[i];
      if (rec.begin <= arrow && arrow <= rec.end)
         return rec.direction;
   }
   return Direction_None;
}

///  ....... bla-bla-bla ..........

   long src_arrow   = GetArrowDirection(shape, visLineBeginArrow);
   long dst_arrow   = GetArrowDirection(shape, visLineEndArrow);

   if (src_arrow != Direction_None && src_arrow != Direction_Both)   
      src_arrow ^= Direction_Both;

   long direction = (src_arrow | dst_arrow);

   if (direction & Direction_To)
      /// TO

   if (direction & Direction_From)
      /// FROM


Сорри что это не VBA, переводить лениво. Основная ценность - магические числа (константы). На VBA я думаю не так сложно будет переписать :oops:


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 28 авг 2017, 14:05 
Огромное спасибо за помощь !
Однако, мне не помогло :(
Пусть переменная vShape есть анализируемый объект схемы - прямоугольник с текстом. Как его нашел - не важно.
Выполнение MsgBox(vShape.Text) подтверждает что нужный объект имеется. В схеме этот прямоугольник описывает операцию.
Теперь мне нужны соединенные с прямоугольником линии. Пока независимо от направления.
В переменную vCount = vShape.FromConnects.Count получаю количество соединений у прямоугольника.
Обратил внимание, если линия НЕ "привязана" к прямоугольнику (соединяется только визуально), такое "соединение" здесь не учитывается.
Пока нормально.
Далее цикл от 1 до vCount и vDot = vShape.FromConnects(vN) - перебираю соединения с прямоугольником.
У каждого соединения есть vDot.FromCell.Shape и vDot.ToCell.Shape.
Выбираю тот вариант, который не связан с исходным прямоугольником.
If vDot.FromCell.Shape.ID <> vShape.ID Then
Set vLine = vDot.FromCell.Shape
Else
Set vLine = vDot.ToCell.Shape
End If
Итого есть соединительная линия vLine.
Линии в схеме "надписал" и да, MsgBox(vLine.Text) выводит надписи линий.
Нормально.

Далее. Для каждой линии можно перебрать ее "соединители" на двух концах
For Each vConnect In vLine.Connects
'Один из "соединителей" привязан к моему прямоугольнику, а мне интересен противоположный.
If vConnector.FromCell.Shape.ID <> vShape.ID And vConnector.ToCell.Shape.ID <> vShape.ID Then
'Текущий "соединитель" линии НЕ связан с исходным прямоугольником - это нужный соединитель - нужная сторона линии
'Выбираю сторону "соединителя", которая связана не с линией
If vConnector.FromCell.Shape.ID <> vLine.ID Then
Set vNextShape = vConnector.FromCell.Shape
End If
If vConnector.ToCell.Shape.ID <> vLine.ID Then
Set vNextShape = vConnector.ToCell.Shape
End If

MsgBox ("Линия " & vLine.Text & " связывает анализируемый прямоугольник с блоком " & vNextShape.Text)

End If
Нормально.
НО ОСТАЛСЯ ВОПРОС.
Я могу узнать ОТСУТСТВИЕ стрелки на концах линии:
vLine.Cells("BeginArrow") = 0 ИЛИ vLine.Cells("EndArrow") = 0,
но я не могу узнать какой конец линии считается ее реальным началом. Тот который связан с анализируемым (исходным) прямоугольником или тот который связан с найденным связанным блоком.
Если узнаю сторону линии, соединенную с исходным прямоугольником, смогу проанализировать vLine.Cells("BeginArrow") = 0 ИЛИ vLine.Cells("EndArrow") = 0 и определить "входящая" связь или "исходящая".
У линии есть свойство FromCell.Shape.ID. Предположил, можно сравнить с vConnector.ID, но у vConnector нет свойства ID !
Вот такая проблема ...


Пожаловаться на это сообщение
Вернуться к началу
  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 28 авг 2017, 14:25 
Не в сети
Administrator

Зарегистрирован: 30 авг 2009, 11:02
Сообщений: 990
Очков репутации: 100578

Добавить очки репутацииУменьшить очки репутации
Цитата:
но я не могу узнать какой конец линии считается ее реальным началом.

Написано много...
Но, кажется, Вам нужно посмотреть свойства FromPart, ToPart.
Эти свойства могут принимать значения, указывающие в какое место, каким концом и т.д. присоединены шейпы.
Немного смущает понятие "реальное" начало, но скорее всего путем эксперимента Вы найдете нужное именно в Вашем случае значение.
Цитата:
Предположил, можно сравнить с vConnector.ID, но у vConnector нет свойства ID !

А вот так не бывает.
Если vConnector - шейп, то ID (который есть у всякого шейп) должен быть и у него.
==============
Извиняюсь... Это же у Вас не шейп, а объект Connect.
Но у него есть свойства FromSheet, ToSheet, указывающие на шейпы с обеих сторон (от коннекта). То есть линия и квадратик. А у шейпов есть ID.


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 28 авг 2017, 14:47 
Не в сети
Administrator

Зарегистрирован: 30 авг 2009, 11:02
Сообщений: 990
Очков репутации: 100578

Добавить очки репутацииУменьшить очки репутации
Вот это не поможет?
FromPart = 9 означает visBegin
То есть для Visio это начало линии.


Вложения:
cnct.jpg
cnct.jpg [ 56.05 Кб | Просмотров: 124 ]
Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 28 авг 2017, 15:20 
Не понял ...
У линии есть два коннектора. Возьмем первый vLine.Connects(1).
У него есть свойства FromShape, ToShape, FromPart, ToPart, но это свойства коннектора, НЕ линии !
Я этими свойствами пользуюсь в приведенном ранее коде. Одна сторона коннектора связана с линией, другая с фигурой, к которой привязан соответствующий конец линии. О направлении самой линии информацию не получу. Где я ошибаюсь?


Пожаловаться на это сообщение
Вернуться к началу
  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 28 авг 2017, 15:42 
Не в сети
Administrator

Зарегистрирован: 30 авг 2009, 11:02
Сообщений: 990
Очков репутации: 100578

Добавить очки репутацииУменьшить очки репутации
Коннектор (Connector) - это линия.
Connect - это точка, соединение.
(Это мелочи - просто поправка в терминологии).
У линии могут быть 0, 1, 2, а иногда (редко) больше объектов Connect.
Теперь возьмем первый vLine.Connects(1).
FromSheet указывает на шейп-линию. FromPart покажет начало или конец линии.
ToSheet укажет на квадрат. ToPart покажет присоединенную часть квадрата (центр, слева, справа, номер ConnectionPoint и т.д.).
То есть, мы можем понять, что данный Connect описывает соединение начала линии и первого ConnectionPoint квадрата.
Это надо было узнать?


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 28 авг 2017, 15:45 
Не в сети
Administrator

Зарегистрирован: 30 авг 2009, 11:02
Сообщений: 990
Очков репутации: 100578

Добавить очки репутацииУменьшить очки репутации
Соответственно, если подключить второй конец линии к другому квадрату и рассмотреть его Connect, то вместо значения FromPart=9 будет уже FromPart=12 - конец линии.


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 28 авг 2017, 15:52 
Не в сети
Administrator

Зарегистрирован: 30 авг 2009, 11:02
Сообщений: 990
Очков репутации: 100578

Добавить очки репутацииУменьшить очки репутации
Кстати, у нас же есть вот такой материал по анализу соединений: viewtopic.php?f=39&t=1142


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 28 авг 2017, 16:05 
Не в сети
Ветеран
Аватара пользователя

Зарегистрирован: 28 апр 2013, 14:03
Сообщений: 547
Откуда: Вена, Австрия
Использую Visio c: 1998
Очков репутации: 100603

Добавить очки репутацииУменьшить очки репутации
Направление "по API" может не совпадать со стрелками. Например, на картинке ниже все стрелки, если на них смотреть "через API", будет одинаковы.
Изображение

Если у тебя всего один тип стрелок (и пользователь не может / не должен менять стрелки "руками"),
например, имеет "правильный" коннектор на стенсиле, то вообще не стоит со стрелками заморачиваться, и использовать то что дает API.
То есть, в этом случае НЕ НУЖНО АНАЛИЗИРОВАТЬ СТРЕЛКИ ВООБЩЕ, From - это From, To - это To, и все.
В Visio так работает 99% всех встроенных функций. Так что не усложняй себе жизнь, если нет на то необходимости.

В случае, если ты хочешь с этим возиться, см. мой пост выше..
Я думаю что код решает эту задачу (определение направлния TO/FROM "коннектора" по "стрелкам", а не по объектной модели).
Просто код нужно переписать на VBA (оформить в виде функции, принимающей шейп коннектора на входе).
Как-то так:
Код:
Public Enum Direction
   Direction_None = 0
   Direction_To = 1
   Direction_From = 2
   Direction_Both = 3
End Enum

Function GetArrowDirection(shp As Shape, side As Integer) As Direction
   Dim arrow_cell As Cell
   Set arrow_cell = shp.CellsSRC(visSectionObject, visRowLine, side)
   Dim arrow As Long
   arrow = CLng(arrow_cell.ResultStr(visNone))

   If 1 <= arrow And arrow <= 8 Then
    GetArrowDirection = Direction_To
   ElseIf 9 <= arrow And arrow <= 11 Then
    GetArrowDirection = Direction_From
   ElseIf 12 <= arrow And arrow <= 19 Then
    GetArrowDirection = Direction_To
   ElseIf 20 <= arrow And arrow <= 26 Then
    GetArrowDirection = Direction_From
   ElseIf 27 <= arrow And arrow <= 30 Then
    GetArrowDirection = Direction_To
   ElseIf 31 <= arrow And arrow <= 38 Then
    GetArrowDirection = Direction_From
   ElseIf 39 <= arrow And arrow <= 40 Then
    GetArrowDirection = Direction_To
   ElseIf 41 <= arrow And arrow <= 42 Then
    GetArrowDirection = Direction_From
   ElseIf 43 <= arrow And arrow <= 45 Then
    GetArrowDirection = Direction_To
   Else
    GetArrowDirection = Direction_None
   End If
End Function

Function GetDirection(conn As Shape) As Direction
    Dim src_arrow As Direction
    src_arrow = GetArrowDirection(conn, visLineBeginArrow)
    Dim dst_arrow As Direction
    dst_arrow = GetArrowDirection(conn, visLineEndArrow)

    If src_arrow <> Direction_None And src_arrow <> Direction_Both Then
      src_arrow = src_arrow Xor Direction_Both
    End If

    Dim dir As Direction
    GetDirection = src_arrow Or dst_arrow
End Function

Sub test()

    Debug.Print GetDirection(ActivePage.Shapes(1))  ' ==> 1, TO
    Debug.Print GetDirection(ActivePage.Shapes(2))  ' ==> 2, FROM
    Debug.Print GetDirection(ActivePage.Shapes(3))  ' ==> 0, NONE
    Debug.Print GetDirection(ActivePage.Shapes(4))  ' ==> 3, BOTH

End Sub


Вложения:
Drawing3.vsd [40.5 Кб]
Скачиваний: 7
Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 28 авг 2017, 16:27 
Спасибо !
Очень неожиданной оказалась структура, где объект типа Connect хранит признак начала и окончания соединенной с ним линии. Я ожидал нужную мне информацию в свойствах линии.
Еще раз спасибо!
Получилось.


Пожаловаться на это сообщение
Вернуться к началу
  
Ответить с цитатой  
 Заголовок сообщения: Re: В макросе нужно узнать наличие и параметры стрелки у линии
СообщениеДобавлено: 28 авг 2017, 16:28 
Не в сети
Ветеран
Аватара пользователя

Зарегистрирован: 28 апр 2013, 14:03
Сообщений: 547
Откуда: Вена, Австрия
Использую Visio c: 1998
Очков репутации: 100603

Добавить очки репутацииУменьшить очки репутации
Если тебе нужны соединенные шейпы (к которым идут соединения), просто используй shape.ConnectedShapes
Она учитывает направление (по API), у нее есть для этого параметр.
Это намного проще чем .Connects и вся возня с ними.

vShape.ConnectedShapes

Пример использования там же, в MSDN.


Пожаловаться на это сообщение
Вернуться к началу
 Профиль  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 15 ] 

Часовой пояс: UTC + 3 часа [ Летнее время ]



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы можете начинать темы
Вы можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Вы можете создать форум бесплатно PHPBB3 на Getbb.Ru, Также возможно сделать готовый форум PHPBB2 на Mybb2.ru
Русская поддержка phpBB