Для русскоязычных пользователей Visio. Начинающих и профессионалов. Где взять, как сделать, что купить и т.д.

Внешняя программа для Visio

Туманов Г.Е.

Из серии статей о Visio и автоматизации

Рассмотрим, как строится программа, запускаемая вне среды Visio.

Предположим, нужно решить следующую задачу. В Excel имеется табличка, содержащая данные о структуре небольшой сети. Требуется графически отобразить эту структуру в виде html документа.

Табличка будет, например, такой

indtipconnfunccommipipx
1"Hub"0R401"Hub16"  
2"Server"1Main"Celeron/512/40" "172.18.21.1""main"
3"Workstation"1R401-1"Celeron/128/20" "172.18.21.2""mont-1"
4"Workstation"1R401-2"Celeron/128/20" "172.18.21.3""mont-2"
5"Workstation"1R401-3"P133/64/20" "172.18.21.100""boss"
6"Laser Printer"4Hewlett Packard"LJ5P"   
7"Scanner"4Mustek"ScanExpress 600 SEP"   

В столбце tip указаны несколько типов сетевых устройств. Каждое устройство должно отображаться своей картинкой. Столбец conn показывает, к какому устройству присоединено данное устройство. То есть сервер и все рабочие станции подключены к концентратору, принтер и сканер связаны с одной из рабочих станций. Эти данные дадут нам конфигурацию сети.

Столбец func несет некоторую информацию о функциональном назначении устройств. Пусть эта информация отображается в виде подписей к рисункам.

Данные из остальных столбцов хорошо бы разместить в полускрытом виде, так чтобы они не загромождали рисунок, но были всегда доступны для просмотра.

Таким образом, на входе имеется документ в формате Excel, на выходе будет html документ, в качестве промежуточного используем рисунок Visio. Ну и где-то должно быть еще приложение - программа, которая произведет все необходимые преобразования. В соответствии с темой данной статьи программа должна быть не в Visio, значит либо отдельное приложение, либо, для простоты, приложение на основе Excel. Вот последний вариант и выберем.

VBA проект в Excel

Встроенным языком программирования в Excel является также VBA. Значит и отличия от программы в Visio будут минимальны. Нужно только суметь создать экземпляр Visio (в начале работы его нет) и наладить взаимодействие с его объектами.

На создании VBA проекта в Excel задерживаться долго не будем. Открываем Excel, набираем в нем приведенную выше таблицу, через меню Сервис/Макрос запускаем редактор VBA и создаем модуль для нашей программы.

Важным моментом является подключение к проекту библиотеки типов для описания объектов Visio. Для этого в редакторе нужно воспользоваться меню Tools/References. В открывшемся диалоговом окне выбираем соответствующую библиотеку, отмечаем ее галочкой и жмем OK.

В данном случае подключена библиотека Microsoft Visio 2002 Type Library. Если этого не сделать, то в среде Excel VBA будет выдавать ошибки при упоминании объектов Visio, так как по умолчанию он их не знает.

Вводим в наш модуль текст программы, приведенный в листинге 1.

Сохраняем документ. Теперь можно выбирать в меню Сервис/Макрос/Макросы появившийся там макрос NetVis и командовать Выполнить.

Если все сделано правильно, то откроется окно с документом Visio, в нем нарисуются несколько шейпов, соединятся между собой коннекторами, окно закроется, а в каталоге C:\Мои документы появится файл NetV.htm и папка NetV_files, с дополнительными файлами. При запуске файла NetV.htm можно наблюдать результаты работы, похожие вот на это. При наведении маркера мыши на любое сетевое устройство в отдельном фрейме выводятся его свойства. Естественно, их увидят не все, так как пока мы работали только продуктами Microsoft, значит и результат, как водится, ориентирован только на IE. Но это уже другой вопрос, а имея соответствующий исходный материал в папке NetV_files, веб-дизайнер всегда может опубликовать его в нормальном виде.

Разбор листинга.

Теперь посмотрим подробнее, как все происходит.

Первая часть программы не касается Visio, а только переносит данные из таблицы Excel в массивы VBA. При этом определяется размер заполненной области и устанавливаются соответствующие размерности массивов.

Затем следует объявление переменных, используемых для доступа к объектам Visio.

Собственно работа с Visio начинается с создания экземпляра Visio

Set appVisio = CreateObject("visio.application")

Когда приложение строилось в среде Visio, этого не требовалось, потому что при запуске программы оно было уже открыто. В данном случае создание экземпляра Visio является обязательным элементом.

Возможны некоторые модификации. Если предполагается, что Visio на момент запуска программы уже должен быть открыт, то можно получить ссылку на открытый экземпляр и работать с ним. Это выполняется командой GetObject

Set appVisio = GetObject(, "Visio.Application")

Иногда требуется открыть невидимый экземпляр Visio. Для этого используется специальная модификация команды.

Set appVisio = CreateObject("Visio.InvisibleApp")

Visio будет существовать до тех пор, пока не будет вызван метод Quit.

appVisio.Quit

Ну а как только появился доступ к приложению Visio, доступ к остальным объектам не составляет труда. Наша программа создает новый документ на основе шаблона Basic Network.vst, открывает его первую страницу и выбирает для работы один из встроенных в шаблон трафаретов Basic Network Shapes.vss.

Далее нужно собственно отобразить на рисунке заданную сеть. Для этого каждому типу устройства ставится в соответствие свой мастер-шейп в трафарете. В принципе можно было бы нарисовать свои оригинальные мастер-шейпы или воспользоваться богатейшей коллекцией шейпов сетевых устройств, но нас сейчас интересует не столько богатство типов, сколько принципы отображения, поэтому просто выбраны похожие шейпы с одного из базовых трафаретов. Единственное условие - можно использовать только мастер-шейпы, имеющиеся в трафарете. Основные операции следующие:

Set mastObj = docObj.Masters("Server") из коллекции мастер-шейпов выбирается шейп с именем "Server"
Set SetComp = pagObj.Drop(mastObj, x, y) переносится на страницу в точку с нужными координатами
SetComp.Text = name заполняется текстовый блок шейпа (подпись)

Принцип размещения тоже несложен - линейка концентраторов, линейка компьютеров и линейка периферии. Каждый следующий шейп помещается на полтора дюйма правее.

Одновременно с прорисовкой шейпов набирается массив шейпов elements() для удобства последующего их соединения.

Все имеющиеся в трафарете мастер-шейпы имеют пользовательские свойства. Изображения шейпов нам подходят, а вот свойства хотелось бы иметь другие, чтобы отобразить имеющиеся в таблице Excel сведения о сетевых устройствах. Каждое свойство состоит из метки и значения. Доступ к ним осуществляется через ячейки шейп-листа. Команда

Set cell1 = Shp.CellsSRC(visSectionProp, visRowProp + 0, visCustPropsLabel)

дает нам ссылку на метку первого пользовательского свойства шейпа Shp. А следующая команда заносит в эту ячейку значение метки (строковая переменная заключается в тройные кавычки).

cell1.Formula = """Тип"""

Изменение значения свойства производится примерно так же, только используется другая константа - visCustPropsValue.

Set cel1 = elements(i).CellsSRC(visSectionProp, visRowProp + 0, visCustPropsValue)
cel1.Formula = tip(i)

Остальные свойства (кроме первых четырех) для простоты не трогаем.

Для соединения шейпов перебираем созданный на предыдущем шаге массив шейпов и каждый шейп соединяем мастер-шейпом "Dynamic connector" с другим, номер которого находится в массиве conn. Процесс состоит из следующих шагов:

Выбираем коннектор
Set mastObj = stnObj.Masters("Dynamic connector")
Опускаем его на страницу в некоторую точку
Set shpConnector = pagObj.Drop(mastObj, 4.25, 9)
Размещаем последним, чтобы он не перекрывал изображение устройств
shpConnector.SendToBack
Задаем цвет
shpConnector.Cells("LineColor") = 0
И толщину в дюймах
shpConnector.Cells("LineWeight") = 0.02
Получаем ссылку на ячейку шейп-листа, с значением начала коннектора
Set celBeginX = shpConnector.CellsSRC(visSectionObject, visRowXForm1D, vis1DBeginX)
Приклеиваем его к текущему шейпу
celBeginX.GlueTo elements(i).CellsSRC(visSectionObject, visRowXFormOut, visXFormPinX)
Получаем ссылку на ячейку шейп-листа с значением конца коннектора
Set celEndX = shpConnector.CellsSRC(visSectionObject, visRowXForm1D, vis1DEndX)
Приклеиваем его шейпу, индекс которого установлен в массиве conn
celEndX.GlueTo elements(conn(i) - 1).CellsSRC(visSectionObject, visRowXFormOut, visXFormPinX)

Теперь рисунок готов, остается только сохранить его в нужном виде.

Сохранение рисунка в формате Visio производится методом SaveAs

docObj.SaveAs "С:\Мои документы\NetV.vsd"

Для сохранения в html виде такая команда не подходит. Нужно использовать метод Export соответствующего объекта. Можно экспортировать одиночный шейп или всю страницу рисунка. В нашем случае больше подходит последнее, поэтому экспортируется объект pagObj.

pagObj.Export " С:\Мои документы\NetV.htm"

Тип преобразования определяется расширением файла (в данном случае htm). Существует еще одна тонкость - как видим, команда практически не содержит настроек. В случае программного экспорта Visio использует те настройки, которые были заданы при последнем ручном экспорте соответствующего типа. То есть если вы получили не то, что хотели, откройте Visio вручную (произвольный рисунок) и выполните преобразование такого же типа с нужными параметрами. Затем закрывайте Visio и вновь запускайте вашу программу. Теперь преобразование пойдет по сохранившимся настройкам.

В процессе сохранения в html формате Visio создает головной документ с заданным именем и дополнительную папку с множеством файлов. Здесь и странички для отображения в фреймах, и рисунки gif или png, и css, и скрипт, и система навигации на случай использования многостраничных документов, и структура документа в виде xml. Для каждого конкретного случая явный избыток, но выкинуть лишнее - не проблема.

Подобный подход можно использовать как при непосредственном размещении приложения на сервере (тогда обновление изображения, доступного через веб-интерфейс, будет производиться одним нажатием кнопки), так и при удаленном размещении (с использованием какого-либо механизма публикации).

Все исходные материалы и результаты работы обсуждаемого примера можно взять для подробного рассмотрения в zip-архиве.


Контакты: Туманов Геннадий Евгеньевич   gCroc@yandex.ru