пятница, 22 августа 2014 г.

Интерактивные методы. Часть 2. Фрагмент программы.

Это приложение к предыдущей статье "Интерактивные методы размещения данных". Для интересующихся конкретной реализацией.
Полностью программа здесь не приводится. Дело в том, что сама по себе задача формирования перечня элементов по ЕСКД достаточно сложна. Там несколько уровней вложенной сортировки. Плюс разные особенности с группировкой данных. Да еще и реализацию пришлось делать двухступенчатой: один экзешник выбирает данные о составе из PDM-системы и сбрасывает их в XML-файл; другой работает чисто на форматирование - принимает данные из XML и выводит в Visio.
Ниже приводятся основные фрагменты из второй, форматирующей части.
Функции Proc1 и Proc2 - обработчики меню для вывода "в глубину" и "в ширину". Практически одинаковые и обращаются к одной и той же процедуре DrawCollection, только с разными параметрами.
DrawCollection в зависимости от режима создает новую страницу либо через процедуру SiblPage (когда страницы наращиваются вбок), либо через AddPage (когда нужно создать физическую страницу).
А реальное заполнение страницы идет через одну и ту же процедуру WriteCurrRow_2. 

'Форматирование вывода по умолчанию. Автомат.
Function Proc1() As Integer
    Proc1 = -1   'Неопознанная ошибка
    On Error GoTo Proc1Err
    AddLog "Создаем Visio.Application - " & Now
    Set VSo = CreateObject("Visio.Application")
    AddLog "Создаем документ по шаблону - " & Now
    Set VSdoc = VSo.Documents.Add(ApplicationPath & "\PE3-v3.vst")
    DrawCollection 1
    
    AddPage "Lr"  'Последняя страница - "лист регистрации изменений"
    Proc1 = 0   'Нормальное завершение
Proc1Err:
    On Error Resume Next
    Set VSdoc = Nothing
    Set VSo = Nothing
End Function

'Форматирование лентой. Интерактивная нарезка
Function Proc2() As Integer
    Proc2 = -1   'Неопознанная ошибка
    On Error GoTo Proc2Err
    AddLog "Создаем Visio.Application - " & Now
    Set VSo = CreateObject("Visio.Application")
    AddLog "Создаем документ по шаблону - " & Now
    Set VSdoc = VSo.Documents.Add(ApplicationPath & "\PE3-v3.vst")

    DrawCollection 2
    
    Proc2 = 0   'Нормальное завершение
    Exit Function
Proc2Err:
    On Error Resume Next
    Set VSdoc = Nothing
    Set VSo = Nothing
End Function

Sub DrawCollection(ByVal Md As Integer)
    Set ListCollection = New Collection 'Создается коллекция листов перечня
    Set tmpListItm = New ListIt
    tmpListItm.XPos = (420 + 20) * (ListCollection.Count) / 50.8
    tmpListItm.YPos = 292 / 50.8
    ListCollection.Add tmpListItm
    CurrList = ListCollection.Count
    AddLog "Заполняем штамп первого листа - " & Now
    WriteFirstPageData     'Заполнение штампов первого листа
    CriticalErorr = False
    nList = 1
    For i = 1 To peMain.OutColl.Count
        WriteCurrRow_2 peMain.OutColl(i), i, 1
        
        If PageFull Then    'Получено сообщение о достижении конца текущей страницы
            'UndoRow     'Отмена не уместившейся строки
            nList = nList + 1
            If Md = 1 Then
                CreateNextPage  'Второй лист на следующей странице
            Else
                SiblPage  'Создание бланка "Второй лист" справа на том же листе
            End If
            'AddPage
            WriteCurrRow_2 peMain.OutColl(i), i, 1
        End If
'        If CriticalErorr Then GoTo Proc2Err
    Next
End Sub

'Добавить страницу справа на том же листе
Public Sub SiblPage()
    Dim Bl As Visio.Master
    Set Bl = VSdoc.Masters("Blank2")
    Set ShBlank = VSo.ActivePage.Drop(Bl, 202 / 50.8 + (420 + 20) * (nList - 1) / 50.8, 292 / 50.8)
    WriteNextPageData 2
End Sub

Private Sub AddPage(ByVal Mast As String)
    Dim oPage As Visio.Page
    Dim Bl As Visio.Master
    Dim ShBlank As Visio.Shape
    Set oPage = VSdoc.Pages.Add
    Set Bl = VSdoc.Masters(Mast)
    Set ShBlank = VSo.ActivePage.Drop(Bl, 202 / 50.8, 292 / 50.8)
End Sub

Private Sub WriteCurrRow_2(ByVal Nd As Object, ByVal id As Integer, LineMode As Integer)
    Dim shpObj As Visio.Shape
    'На листе есть ограничивающая координата. Если шейп после заполнения текстом пересекает ее,
    'он выбрасывается и лист считается заполненным.
On Error GoTo StructError
    Set pagObj = VSo.ActivePage
'    x = pagObj.Shapes("Title").Cells("PinX") 'Большого значения не имеет, так как потом все равно подвинется при привязке
    x = ListCollection(ListCollection.Count).XPos + 17 / 25.4
    
    If Nd.rType = 1 Then
        Set mastObj = VSdoc.Masters("Row")
        Set shpObj = pagObj.Drop(mastObj, x, CurrentPos)
        shpObj.Cells("Prop.rowID") = id
        If (Nd.Prim = "") Or (InStr(1, Nd.Prim, "Из состава") > 0) Then
            shpObj.Shapes(1).Text = Nd.PozOboz
        Else
            shpObj.Shapes(1).Text = Nd.PozOboz & "*"
        End If
        shpObj.Shapes(2).Text = Nd.Naimen
        shpObj.Shapes(3).Text = Nd.Kol
        shpObj.Shapes(4).Text = Nd.Prim
    Else
        Set mastObj = VSdoc.Masters("RowCentr")
        Set shpObj = pagObj.Drop(mastObj, x, CurrentPos)
        shpObj.Cells("Prop.rowID") = id
        shpObj.Shapes(1).Text = ""
        shpObj.Shapes(2).Text = Nd.Zag
        shpObj.Shapes(3).Text = ""
        shpObj.Shapes(4).Text = ""
    End If
    'Проверка, не опустился ли новый шейп ниже ограничителя
    DoEvents    'Замедляет процесс, но без этого многострочные элементы не успевают развернуться до анализа переполнения
    tmpPos = CurrentPos - shpObj.Cells("Height")
    If LineMode = 1 Then
        If ListCollection.Count > 1 Then
            If tmpPos < BottomNext / 25.4 Then    'Проверка на переполнение
                shpObj.Delete
                PageFull = True
                Exit Sub
            End If
        Else
            If tmpPos < BottomFirst / 25.4 Then
                shpObj.Delete
                PageFull = True
                Exit Sub
            End If
        End If
    Else
    
    End If
    'Присоединить новый шейп к предыдущему, нарастить коллекцию и сместить текущую позицию
    If PageRows.Count > 0 Then
        Set PrecShp = PageRows.Item(PageRows.Count)
        ConnShRow shpObj, PrecShp
    End If
    PageRows.Add shpObj
    CurrentPos = shpObj.Cells("PinY") - shpObj.Cells("Height")    'Низ последнего шейпа
    'Забрасывать шейп в коллекцию шейпов лучше здесь, когда уже точно ясно, что он останется.
    ListCollection(CurrList).RowColl.Add shpObj 'Добавили вновь созданный шейп к коллекции шейпов листа
    
Exit Sub
StructError:
    MsgBox "Ошибка в структуре входного файла"
    CriticalErorr = True
End Sub

четверг, 21 августа 2014 г.

Использование дополнения Visio в качестве графического интерфейса PDM системы

Об одном не слишком распространенном способе применения Visio.
Традиционный интерфейс PDM системы предполагает отображение информации о составе изделий в виде дерева или таблицы. Тяжело придумать что-либо другое, имея в качестве инструмента окошко на экране монитора. То есть чаще всего пользователь видит примерно такое изображение.
В этом плане Visio позволяет существенно расширить наблюдаемое поле. Размеры страницы практически не ограничены, масштаб изменяется легко, плюс возможности поиска. То есть появляется возможность отобразить сразу все дерево состава сложного изделия и наблюдать на этом фоне какую-то нужную информацию.
В данном случае речь идет о таком использовании Visio для PDM STEP Suite (НИЦ CALS-технологий "Прикладная логистика"). Собственно тип PDM системы в данном случае не очень и важен. Важно то, что в этой системе внешняя прикладная программа может добраться до данных о составе через представления Oracle, то есть с использованием ADODB. Дальше задействуется привычный метод связи Visio с внешними данными и можно смотреть, что получается.
Дополнение представляет собой шаблон Visio с несколькими макросами, выполняющими выборку внешних данных через ADODB, размещение их на странице рисунка, в том числе управляемое. Действия вызываются через дополнительное меню (в нем перечислены практически все функции дополнения).
Основой связи с данными является довольно простой шейп, снабженный данными шейпа (Custom Properties) вот такой конфигурации.
Для максимального сжатия информации шейп компактно отображает сразу несколько полей пользовательских данных. Уникальным идентификатором для связи с базой является InstanceID.
Работа начинается с того, что на листе отображается дерево состава изделия или нужный его фрагмент. Для этого имеются функции "Выбрать компоненты" и "Нарисовать все".
Первая выбирает составные части, непосредственно входящие в состав указанного изделия, вторая - рекурсивно выбирает и отрисовывает все дерево. То есть после их применения из исходного изображения
получится такое изображение (Выбрать компоненты)
или такое (Нарисовать все)

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


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

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

Набор таких функций можно наращивать по мере возникновения необходимости в отображении той или иной информации. Каждая новая функция - это всего лишь новый запрос к данным, который пристраивается к уже существующему механизму обхода шейпов на рисунке и изменения закраски.
Ненужная подкраска снимается функцией "Убрать подкраску".
Такой рисунок сохраняется в виде файла Visio, естественно сохраняя связи с базой данных. То есть схему состава обычно приходится строить один раз, а пользоваться можно многократно.
Естественно, со временем состав изделия изменяется. Для отслеживания изменений имеются макросы "Сравнить" и "Сравнить все". Первый действует на один текущий уровень входимости от выбранного изделия (шейпа). Второй - на весь куст, расположенный ниже выбранного шейпа.
Макрос обходит дерево, изображенное на рисунке, повторно запрашивая из базы состав для каждого узла дерева и сравнивая его с составом, полученным из рисунка по связям между шейпами. Обнаруженные отличия отображаются опять же цветом. Красным подкрашиваются изделия, удаленные из базы, синим - сборки, состав которых в базе отличается от приведенного на рисунке. То есть может получиться примерно такое изображение.

В зависимости от количества расхождений пользователь выбирает дальнейшие действия: подправить отдельные фрагменты изображения (если их мало) либо опять воспользоваться функцией "Нарисовать все".
Функции выборки и отображения работают с учетом контекстов. В данном решении для каждого контекста используется свой тип мастер-шейпа, а так как дерево состава строится от какого-то корня, то тип этого корня определит фильтрацию данных последующего отображения. В принципе, на одном листе могут быть отображены несколько деревьев состава изделия в разных конекстах.
Другая возможность фильтрации позволяет учитывать в дереве состава покупные изделия либо работать только с изготавливаемыми.
В итоге получилось приложение Visio под следующий сценарий работы. Создается и хранится файл Visio со схемой состава разрабатываемого сложного изделия. Когда возникает необходимость оценить состояние разработки, файл открывается, автоматически проверяется его актуальность, затем также автоматически подкраской отображается запрошенная информация. Схема позволяет быстро оценить и количество проблемных мест, и их расположение в структуре изделия.
Некоторым недостатком такого сценария применения является необходимость установки Visio. Несмотря на то, что можно обойтись самой дешевой версией (Standard), это оказалось неудобно. Поэтому реально схемы состава наиболее актуальных изделий используются не на локальных рабочих станциях, а коллективно. Скрипт, ежедневно запускаемый по расписанию, открывает по очереди все схемы, запускает в них макросы сравнения, отображения состояния и публикации в формате PDF на сайте SharePoint. В результате на сайте ежедневно обновляется комплект схем с нанесенными данными в формате PDF.
Если пользователя устраивает предложенный формат отображения, он пользуется данными с сайта. Если хочется чего-то своего, устанавливает Visio и работает в соответствии со своими предпочтениями.
Это приложение не задумывалось как универсальное, а делалось под конкретные условия для решения конкретных задач. Однако подход универсален и типичен для Visio. Значит нечто аналогичное легко может быть создано и в других условиях. Если, конечно, PDM система обеспечивает внешний доступ к данным.

Интерактивные методы размещения данных

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

При этом пользователь видит весь текст, включая последствия всех перемещений. Дальше начинается интерактивная подгонка: добавление межстрочных интервалов, перемещение блоков текста, даже вынос некоторой общей части текста в заголовок (при этом для заголовка создается новая запись). Набор команд для такого редактирования собран на одной экранной форме.

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

Так как все редактирование сохранялось в коллекции, данные распределяются по листам точно так же, но уже не "в ширину", а "в глубину".
После некоторой практики оптимальным был признан следующий набор команд редактирования (для перечня элементов):
- проредить - селектируется запись начала блока данных, запись конца блока данных и нажимается кнопка команды. В результате после каждой записи в этом блоке добавляется одна пустая запись;
- добавить - несколько пустых строк после каждой записи. Селектируется несколько записей, не обязательно подряд. После выполнения команды за каждой селектированной записью появляется заданное количество пустышек;
- удалить - чаще всего применяется к неудачно вставленным пробелам. Селектированные записи удаляются;
- перенести - селектируются три записи: начало и конец переносимого блока и точка вставки. Блок переносится в новое место.
Остальные операции (для групп) - это специфика перечня элементов, здесь ее можно не рассматривать.
Еще одна тонкость кроется в конструкции шейпа и соединении шейпов. Шейп, в который выводится одна запись, представляет собой группу из нескольких шейпов-колонок. Каждая колонка не только саморегулирующаяся (по высоте) в зависимости от количества текста, но и воздействует на высоту всей группы. То есть, если хотя бы в одной колонке количество строк увеличится, оно увеличится и во всей записи. А так как группы сцеплены в гирлянду, то ниж-ние записи автоматически сдвигаются на нужное расстояние. Этот эффект просматривается в последней строке примера.




Кстати, при попытках отслеживать изменение размеров в зависимости от количества текста в других приложениях (в том же Excel) почти все известные решения когда-нибудь, да ошибаются. Для Visio это "родная" задача, поэтому тут ошибок не бывает.
Скорее всего прием с "фантомными" страницами применим не только в таких документах, как перечень. Предпосылками к его применению являются:
1. Необходимость совмещения автоматического построения многостраничного документа с интерактивным редактированием.
2. Возможность сохранения связи между данными в промежуточном хранилище и "фантомным" размещением, чтобы отредактированное размещение можно было перенести на физические страницы.

пятница, 15 августа 2014 г.

Связь с данными для профессиональных версий Visio

Завершил шпаргалку на тему работы Visio с внешними данными. Получилось шесть вот таких листов. (формат pdf).
Пытался свести сюда все, что нужно для успешного решения задач не программистом. Естественно, это применимо только для версий Professional и в рамках возможностей штатных средств.
Для получения более широких возможностей (в том числе и в версиях Standard) нужно либо обладать хотя бы минимальными знаниями в области программирования (на VBA), либо иметь в организации хотя бы одного программиста, либо не бояться прибегать к услугам программистов на стороне.
Добавочка - две коротких демонстрашки про старые визарды:


Демонстрашки короткие (порядка минуты) и без звука. Живые иллюстрации к страницам 4 и 5 шпаргалки.


понедельник, 4 августа 2014 г.

Связь рисунков Visio с данными

Варианты обеспечения связи

В последнее время в некоторых (даже весьма уважаемых) источниках появляются примерно такие утверждения:
"Рисунки, связанные с данными – это функция Visio профессиональный 2013 и Visio Pro для Office 365 и она недоступна в Visio стандартный 2013".
"Обновление данных работает только в одну сторону (из базы на диаграмму), т.е. штатными средствами обновление данных в источнике не сделать".
Неправда все это! Вернее это бывает правдой в определенных случаях. Но начинающий пользователь не всегда может разобраться в тонкостях, поэтому такие утверждения сплошь и рядом его обманывают.
Любая версия Visio всегда обеспечивала как минимум несколько способов связи рисунка с данными. Вот основные из них.

Возможность разработки своего дополнения, обеспечивающего связь рисунка Visio с листом Excel или таблицей базы данных, существовала всегда (по крайней мере, последние 15 лет). Это работало и в простейших и в самых профессиональных версиях. Причем дополнение могло писать данные в любую ячейку шейп-листа, то есть в любой атрибут шейпа (фигуры). Естественно, этот путь работает и сейчас, в том числе и в Visio 2013. Только он не для всех удобен, потому что требует навыков разработки дополнения (или написания макросов).
Со временем Microsoft написала более-менее универсальное дополнение и стало включать его в комплект поставки. Это 5 визардов (помощников) для работы с БД. Визарды появились где-то в районе Visio 2000. Они считались ценными и включались в состав только профессиональных, дорогих версий. В Visio 2013 они тоже есть (только в профессиональном и Pro для Office365).
Дополнение не было в должной мере документировано, поэтому осваивается непросто. По сравнению с произвольным дополнением набор функций был конечно ограничен, но достаточно широк для решения многих универсальных задач. Передача данных поддерживается в обе стороны – из БД в шейпы и из шейпов в БД.
В качестве основного приемника данных в шейпах используются данные шейпа (Shape Data или несколько ранее Custom Properties). Хотя могут использоваться и другие атрибуты шейпов.
С введением этого дополнения стала возможным связь рисунка Visio с источником данных без программирования, только с помощью настроек.
В Visio 2007 введен еще более "продвинутый" элемент – окно "Внешние данные" и поддерживающий его транспорт данных. Принцип "без программирования" стал выражен еще ярче. Количество настроек снизилось. Количество выполняемых функций – тоже.
Новая технология стала однонаправленной. Теперь данные движутся только от базы данных в рисунок Visio. Обратный путь не обеспечивается. Дополнение работает только в профессиональных версиях Visio.
Одновременно введен еще и специальный элемент для отображения внешних данных Data Graphics – специальные выноски, которые могут автоматически прилепляться к любому шейпу после связывания его с внешними данными.
И как всегда, наиболее широко рекламируется самое последнее достижение. В случае Visio им как раз и стала связка окна "Внешние данные" и отображение в Data Graphics. То есть наиболее простая для пользователя технология с минимум функций. Именно она обладает указанными в начале свойствами – однонаправленность передачи данных и поставка только с профессиональными версиями.
Но забывать про наличие ранних, более мощных технологий – это большая ошибка. Да, они осваиваются чуть тяжелее. Зато их возможности намного превышают последний урезанный вариант. И, что тоже очень существенно, свое дополнение позволяет обойтись минимальной комплектацией Visio, а это может сэкономить (для Visio 2013) до 10 000 руб. на каждой лицензии.

Технология "Рисунки, связанные с данными"

Про эту технологию в последнее время сказано достаточно много. Вот несколько ссылок:
Связывание схем с внешними данными – пошаговый пример настройки связи между Visio 2010 и листом Excel. Тема Data Graphics не затрагивается.
Создание новых рисунков, связанных с данными – пошаговый пример добавления к шейпам предыдущей схемы элементов Data Graphics для отображения внешних данных.
Trilogy-meter Data Graphics Part I, Part II, Part III, – к сожалению, только на английском. Подробное описание решения задачи с использованием связи Visio с внешними данными. В трех последовательных статьях показан как сам процесс настройки связи с данными, так и решение сопутствующих задач (создание своих элементов Data Graphics, импорт изображений, технология обновления данных). Создавалось еще в 2009 г. для Visio 2007.
Building Custom Data Graphics for Visio 2007 – базовая статья Марка Нельсона о том, что такое Data Graphics, какие они бывают, как их создавать и как применять. Тоже на английском. От 2006 г., когда Data Graphics только зарождались.
Creating custom data graphics in Visio – современный пошаговый пример создания собственных значков. На английском.
Особенности технологии: данные двигаются только в одном направлении – из БД в рисунок Visio; технология доступна только в профессиональных версиях Visio.
Подробности
Начиная с Visio 2007 объект документ Visio содержит коллекцию объектов DataRecordSet. Объект DataRecordSet отвечает за передачу данных из БД в Visio.
Данные из DataRecordSet отображаются в окне "Внешние данные". Именно это окно пользователь видит и использует для настройки связи внешних данных с шейпами. Но программист имеет доступ и к самому объекту DataRecordSet, что позволяет использовать его в своих дополнениях, обеспечивающих, например, автоматическое соединение внешних данных с шейпами по определенному алгоритму.
В момент создания связи строки внешних данных с шейпом в шейпе автоматически создаются строки данных шейпа (Shape Data), соответствующие полям внешних данных. Строки добавляются только в том случае, если шейп не имеет строк данных с нужными наименованиями. То есть, если нужные поля создать заранее, они будут найдены и заполнены автоматически.
Область применения
Сокращенные возможности технологии предполагают и соответствующее сужение области применения. Технология применяется там, где нужно быстро добавить индикацию внешних данных на каком-либо готовом рисунке.
Яркий пример использования приведен на странице Карта Российских регионов. Здесь к основе (множество шейпов, составляющих карту) подключаются данные с сайта переписи населения в формате Excel. В результате на карте появляются в виде индикаторов данные о составе населения. Естественно, к одной и той же основе могут быть подключены различные источники данных для отображения нужной информации.
Основа не обязательно создается вручную. Она может быть получена другим дополнением Visio, например, путем автоматического построения оргсхемы организации. То есть сначала с помощью визарда оргсхем изображается структура организации, потом на нее накладывается нужная текущая информация из другой базы или файла.
Технология не обязательно заканчивается на Data Graphics. Для многих применений достаточно того, что данные появляются в Shape Data. При этом они легко могут просматриваться в интерактивном режиме через окно "Данные шейпа".
Наконец после появления внешних данных в Shape Data они могут отображаться не только в индикаторах, добавляемых к шейпу-основе. Этот шейп сам по себе может быть выполнен по технологии смарт-шейпа и изменяться в зависимости от данных. Вот пример, в котором смарт-шейпы применены в качестве таких сложных индикаторов, отображающих интенсивность использования веб-сервисов на предприятии.

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

Технология DataBase визардов

Пример подключения внешних данных из Excel к рисунку Visio 2003 рассмотрен в статье Связь шейпов Visio с данными в Excel. Пример охватывает подготовку файла в Excel, настройку связи, настройку шейпов для отображения данных, прямое и обратное обновление данных. Как уже отмечалось, по этой технологии передача данных осуществляется в обе стороны.
Через меню Add-Ons / Visio Extras в Visio 2007 доступны следующие дополнения:

  • Database Export Wizard
  • Database Refresh
  • Database Settings...
  • Database Update
  • Database Wizard
  • Export to Database...
  • Link to ODBC Database.

Два из них (Database Refresh и Database Update) являются простыми исполняющими дополнениями, а остальные 5 выполнены по типу визардов, подразумевающих настройку выполняемых операций.
Совсем не обязательно использовать весь этот комплект дополнений полностью. В описанном выше примере понадобились только Database Settings, Link to ODBC Database, Database Refresh и Database Update. В других задачах могут быть задействованы другие комбинации.
Общая схема передачи данных следующая


DataBase дополнение использует выбираемый при настройке ODBC драйвер, связывающий его с нужным источником – таблицей БД или файлом Excel. В рисунке Visio данные поставляются в секцию Shape Data.
Так же как и в вышеописанной технологии, целевой шейп может быть автоматически подстроен для приема данных в момент настройки соединения. В секцию добавляются именованные строки для приема данных, существующих в присоединяемой таблице.
Технология в основном рассчитана на ручную работу, хотя синхронизирующие дополнения Refresh и Update, как и любое дополнение могут быть вызваны программным путем из некоторого пользовательского приложения.
Область применения
Технология в принципе могла бы использоваться везде, где сейчас используется технология с окном "Внешних данных", и дополнительно в тех случаях, когда нужна обратная передача данных. Она тоже не требует знания программирования.
Тем не менее, широкого распространения она не получила. Причина скорее всего в том, что она уже вызывала трудности освоения у неподготовленного пользователя и в то же время не давала той свободы, которую предоставляет технология с разработкой своих дополнений.
Существенным ограничением является то, что связь устанавливается между конкретным шейпом и конкретной таблицей БД. Связываемые объекты должны появиться заранее и не поддерживаются сложные связки данных.

Разработка своих дополнений

Главное отличие этой технологии в том, что во всех остальных пользователю приходилось подстраиваться под функции, предоставляемые чужим дополнением. В этой технологии подстраиваться не надо, сделать можно все, что угодно.
Для связи с базой данных обычно используется ADODB, предоставляющий всю мощь SQL, произвольные запросы к любым таблицам БД.


К рисунку Visio доступ осуществляется через объектную модель Visio, то есть к произвольным объектам.
Но большие возможности сопровождаются большим разнообразием решений. Единственная типовая схема приложения типа окна "Внешние данные" уже не сможет закрыть всего этого разнообразия.
Один из возможных примеров, в котором Visio выступает в качестве графического редактора данных, находящихся в базе, показан в статье Пример приложения для двустороннего обмена данными с базой данных. О других примерах, различных областях применения и возможных схемах приложений, пожалуй, лучше поговорить отдельно.

воскресенье, 3 августа 2014 г.

Пример приложения для двустороннего обмена данными с базой данных

Как это выглядит

Для более предметного разговора о том, как может обеспечиваться двустороняя синхронизация данных между Visio и базой данных, было создано приложение-пример, выполняющее такую функцию.
В качестве базы использован файл Excel 2007. Само приложение выполнено в виде набора макросов в Visio 2007. Для его функционирования достаточно версии Standard (Стандартная).
Задача приложения - создать и поддерживать базу различных компоновок мебели в помещении. То есть в таблице базы данных хранится множество проектов, а Visio используется для их редактирования.
Данные простейшие: тип мебели, координаты и угол поворота.
Небольшое видео, демонстрирующее работу приложения - файл AVI.

Основные технические решения

Возможности приложения видно из дополнительного пользовательского меню.

Для реализации задачи понадобились две функции работы с проектами:
Загрузить проект - строит рисунок по данным, выбранным из базы.
Сохранить новый проект - сохраняет в базе данные одного рисунка.
И три сервисных функции:
Проверить - сравнить данные из базы с рисунком и показать различия.
Обновить базу - привести данные текущего проекта в базе в соответствие с текущим состоянием рисунка.
Обновить документ - обратная передача, скорректировать рисунок по данным базы.
Вся индикация различий при сравнении выполняется в графической форме путем подкраски шейпов. В результате редактирования могут измениться (в данном примере) координаты и угол поворота объекта. Кроме того могут быть добавлены новые объекты или удалены имеющиеся. Соответственно, при выполнении функции "Проверить" измененные шейпы красятся зеленым цветом, новые красным, а вместо удаленных временно рисуются фантомы по данным базы. После обновления рисунка или базы раскраска и фантомы исчезают.

Структура данных

Фрагмент базы данных (в данном случае листа Excel) показан на рисунке.

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

Структура приложения

Статическая структура приложения показана на рисунке

Рисунок получен реинжинирингом созданного набора макросов с помощью штатного дополнения Visio для работы с UML диаграммами.
Весь набор макросов размещен в четырех модулях. ThisDocument содержит макросы для навески пользовательского меню и обработчики для меню. Модуль Scheme хранит глобальные переменные и пару функций для работы с базой. Основной функционал собран в двух классах: специализированной коллекции Project и члене этой коллекции fItem, ответственном за одну запись в базе или одну единицу мебели на рисунке. Класс fItem содержит не только передаваемые атрибуты (идентификатор, координаты), но и ссылку Shape на шейп, размещаемый на странице Visio.
Аналогичный подход, кстати, используется в подобных приложениях довольно часто. Над объектной моделью Visio надстраиваются прикладные объекты, включающие при необходимости "штатные" объекты Visio. Они могут быть очень простыми, как в данном примере, и сложными, в том числе со своей иерархией, в более серьезных приложениях.
В итоге при работе приложения две коллекции (BasCol с данными, полученными из базы, и DocCol с данными, полученными из документа). Все операции сравнения и изменения данных выполняются методами входящих объектов.

Подробности выполнения операций с данными

Для связи между документом и базой используется ADODB. Все взаимодействие происходит через два основных объекта: ConnectionString и RecordSet. Первый отвечает за подключение, второй - за передачу данных.
Фрагмент макроса (метода объекта fItem), выбирающий из базы данные одного проекта и складывающий их в коллекцию.
    Set rs1 = New ADODB.Recordset
    strSQL1 = "Select * from [Sheet1$] Where InstanceID > 0 and ProjectName like '" & ProjName & "'"
    rs1.Open strSQL1, cn1, adOpenStatic, adLockOptimistic
    For i = 1 To rs1.RecordCount
        Dim tmpItem As fItem
        Set tmpItem = New fItem
        tmpItem.InstanceID = rs1.Fields("InstanceID").Value
        tmpItem.fType = rs1.Fields("fType").Value
        tmpItem.x = rs1.Fields("x").Value
        tmpItem.y = rs1.Fields("y").Value
        tmpItem.ang = rs1.Fields("ang").Value
        Item.Add tmpItem
        rs1.MoveNext
    Next
    rs1.Close
Фрагмент кода для выборки из базы максимального имеющегося значения уникального идентификатора.
    strSQL1 = "Select Max(InstanceID) From [Sheet1$]"
    Set rs1 = New ADODB.Recordset
    rs1.Open strSQL1, cn1, adOpenStatic, adLockOptimistic
    GetMaxInstanceID = rs1.Fields(0).Value
Метод прорисовки шейпа по данным объекта fItem.
Public Sub Draw()
    Dim sh As Visio.Shape
    Dim Mas As Visio.Master
    Set Mas = ActiveDocument.Masters(fType)
    Set sh = ActivePage.Drop(Mas, 1, 1)
    sh.Cells("PinX") = x
    sh.Cells("PinY") = y
    sh.Cells("Prop.ID").Formula = Chr(34) & InstanceID & Chr(34)
    sh.Cells("Angle") = ang
    Set Shape = sh
End Sub
В целом основной объем функционального кода, содержащийся в модулях Project и fItem, занимает порядка 450 строк кода. Это с учетом того, что решение делалось для примера и не подвергалось серьезной оптимизации.

Резюме

Таким образом, в примере продемонстрирована реализация простейшей задачи синхронизации рисунка Visio с базой данных через механизм ADODB.
В этом решении Visio используется для редактирования содержимого базы данных графическими методами.
Факт, что для реализации решения потребовалось порядка 450 строк кода подтверждает эффективность метода для использования в сложных решениях, связанных с внешними данными.