Форум пользователей Visio
http://visio.getbb.ru/

Поиск шейпов при определённом событии
http://visio.getbb.ru/viewtopic.php?f=6&t=1041
Страница 1 из 3

Автор:  Machestro [ 20 окт 2016, 10:21 ]
Заголовок сообщения:  Поиск шейпов при определённом событии

Продолжаю тему начатую в viewtopic.php?f=6&t=1038
Задач поставил себе много, будем постепенно их реализовывать.

Первое, что я хотел сделать - научиться искать шейпы во всём документе при изменении определённой ячейки в Shape Data.
Собственно вот мой первый код

Код:
Private WithEvents vsoApplication As Visio.Application
Public Sub CellChanged_Example()
    Set vsoApplication = Application
End Sub

Private Sub vsoApplication_CellChanged(ByVal vsoCell As IVCell)
    Dim shChanged As Shape 'Шейп в котором произошли изменения
    Dim strSubject As String 'То, что будем искать

    Set shChanged = vsoCell.Shape

    If vsoCell.RowName = "Row_1" Then
        strSubject = shChanged.Cells("Prop.Row_1.value").ResultStr(0)
        SearchShapes (strSubject)
        'MsgBox strSubject
    End If

End Sub

Function SearchShapes(strSubject As String)
    Dim sh As Shape 'Один проверяемый шейп
    Dim vsoShapes As Visio.Shapes 'Набор шейпов на странице
    Dim shapeCell As String 'Проверяемая ячейка
    Dim vsoPages As Visio.Pages 'Все страницы документа

    Dim intCounter As Integer 'Счётчик шейпов
    Dim intPageCounter As Integer 'Счётчик страниц
    Dim totalShapes As Integer 'Кол-во шейпов на странице
    Dim numOfPages As Integer 'Число страниц в документе

    numOfPages = ActiveDocument.Pages.Count

    For intPageCounter = 1 To numOfPages 'перебераем страницы
        Set vsoShapes = ActiveDocument.Pages.Item(intPageCounter).Shapes 'для каждой страницы определяем набор вставленных шейпов.
        totalShapes = vsoShapes.Count 'Определяем кол-во шейпов на странице
        If totalShapes > 0 Then ' Если есть шейпы на странице то продолжаем перебирать их
            For intCounter = 1 To totalShapes
                Set sh = vsoShapes.Item(intCounter) 'Выбираем один из шейпов
                If sh.CellExists("Prop.Row_1.value", 1) Then 'Есть ли вообще нужная ячейка
                    shapeCell = sh.Cells("Prop.Row_1.value").ResultStr(0) 'если да, то берём её значение в виде String
                        If shapeCell = strSubject Then 'Если значение равно искомому
                        MsgBox "You did it :)"
                    Else
                        MsgBox "This shape Doesn' have " & strSubject
                    End If
                End If
            Next intCounter ' переходим к следующему шейпу
        Else
            MsgBox "No Shapes on Page №" & intPageCounter
        End If
    Next intPageCounter ' переходим к следующей странице
End Function

Краткое пояснение. Если возникло изменение в ячейке Prop.Row_1 любого шейпа, то запускается сканер, который ищет шейпы на всех страницах с таким же значением в Prop.Row_1.Value.
На удивление код работает, хотя он скорее относится к разряду "говнокод".
Однако если добавляется новая страница, то возникает ошибка Run-time error '-2032466967 (86db03e9)': Непредвиденный конец файла.

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

Автор:  9rey [ 20 окт 2016, 11:05 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

совет:
лучше использовать for each Page in Pages и for each Shape in Shapes
чтобы не связываться с индексами. может поэтому ошибка вылезает, хотя не вникал.

Автор:  Shishok [ 20 окт 2016, 11:07 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

У тебя возникает ошибка так как на новом листе нет шейпов. И shChanged становится страницей(это тоже как бы шейп :) ). И Id у страницы = 0. Как исправить? Ну например. Добавь в процедуру vsoApplication_CellChanged вот это:
Код:
If shChanged.ID = 0 Then Exit Sub

после строки:
Код:
Set shChanged = vsoCell.Shape

Автор:  Surrogate [ 20 окт 2016, 11:09 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

нет визио под рукой потестить код. сразу бросилось в глаза, не хватает рекурсии !
Код:
Set vsoShapes = ActiveDocument.Pages.Item(intPageCounter).Shapes 'для каждой страницы определяем набор вставленных шейпов.
        totalShapes = vsoShapes.Count 'Определяем кол-во шейпов на странице
        If totalShapes > 0 Then ' Если есть шейпы на странице то продолжаем перебирать их
            For intCounter = 1 To totalShapes
очень часто бывает, что шейпы сгруппированы !
Код:
    numOfPages = ActiveDocument.Pages.Count

    For intPageCounter = 1 To numOfPages
можно заменить на перебор страниц
Код:
Dim AP as Page
For Each AP in ActiveDocument.Pages ' перебор всех страниц в активном документе

Автор:  Surrogate [ 20 окт 2016, 11:37 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

таки зашел с планшета на рабочий ноут по RDP! потестил немного. по мере добавления свойств к шейпу первый раз мессадж-бокс вылезает несколько раз !

Вложения:
Комментарий к файлу: gif
01010.gif
01010.gif [ 568.94 Кб | Просмотров: 956 ]

Автор:  nbelyh [ 20 окт 2016, 11:40 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

Ещё один совет - лучше использовать FormulaChanged (если данные меняет только пользователь), потому что CellChanged вызывается на каждый чих (пользователь перемещает фигуру например). Не будет работать (скорее всего повиснет) на мало-мальски реальной диаграмме (имеющей пару десятков фигур например, о сотнях или тысячах вообще речи нет).

Автор:  Surrogate [ 20 окт 2016, 11:50 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

nbelyh писал(а):
Ещё один совет - лучше использовать FormulaChanged (если данные меняет только пользователь), потому что CellChanged вызывается на каждый чих (пользователь перемещает фигуру например)
золотые слова ! как раз в моем примере MsgBox вылетал ровно столько раз, сколько фигур на листе !
Machestro писал(а):
Краткое пояснение. Если возникло изменение в ячейке Prop.Row_1 любого шейпа, то запускается сканер, который ищет шейпы на всех страницах с таким же значением в Prop.Row_1.Value.
ага, всё же столько раз сколько шейпов имеющих prop.row_1.

Автор:  nbelyh [ 20 окт 2016, 11:56 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

Ещё штука в том что CellChanged триггерится для PinX, PinY, Width, Height и подобных, Которые меняются сотнями-тысячами при простейших действиях пользователя (move-resize), особенно если фигуры составные (эти события генерируются также для вложенных фигур). В результате будешь иметь сотни-тысячи "холостых" вызовов Oncellchanged.

Автор:  Surrogate [ 20 окт 2016, 12:00 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

честно говоря непонятно зачем, 100500 раз выводить сообщения о содержимом ячейки prop.row_1 ? может лучше как-то визуально их показывать ?
например вставив строчку
Код:
ActiveWindow.Select sh, visSelect
перед
Код:
MsgBox "You did it :)"

Автор:  Shishok [ 20 окт 2016, 12:14 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

Интересно, за каким чертом генерится событие FormulaChanged(или CellChanged) при добавлении нового листа?
Причем два раза. А при вставке фоновой страницы - не возникает этих событий!

Автор:  Surrogate [ 20 окт 2016, 12:16 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

Shishok писал(а):
генерится событие FormulaChanged(или CellChanged) при добавлении нового листа?
думаю, в процессе добавления какая-нибудь ячейка да изменится Изображение может и не раз Изображение

Автор:  Tumanov [ 20 окт 2016, 12:29 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

!!!!!!!
Цитата:
Не будет работать (скорее всего повиснет) на мало-мальски реальной диаграмме (имеющей пару десятков фигур например, о сотнях или тысячах вообще речи нет).

Самый существенный момент!
Использовать FormulaChanged, CellChanged нужно вообще в крайних случаях. Когда других вариантов нет.
А здесь они скорее всего есть.
Попробовать прицепиться к обновлению источника или завершению редактирования конкретных шейпов.
То есть "поучиться" такому приему конечно можно. Но вставлять его в CAD-решение крайне нежелательно.

Автор:  9rey [ 20 окт 2016, 12:42 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

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

Автор:  Machestro [ 20 окт 2016, 12:49 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

Пытаюсь переварить всё это, за что спасибо.

Хочу я следующее. Если у Шейпа изменилось значение конкретной ячейки, например в Shape Data есть строка Prop.Row_1 и изменилось значение в Value. В этом случае нужно посмотреть есть ли Шейпы с этим же значением в этой же ячейке во всём документе

Автор:  Surrogate [ 20 окт 2016, 12:57 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

Machestro писал(а):
Если у Шейпа изменилось значение конкретной ячейки, например в Shape Data есть строка Prop.Row_1 и изменилось значение в Value
это отлавливание изменений должно постоянно происходить в процессе работы с документом ? Изображение. или уже при финальном редактировании документа ?
Machestro писал(а):
В этом случае нужно посмотреть есть ли Шейпы с этим же значением в этой же ячейке во всём документе
тогда можно формировать список таких шейпов, указанием листа и имени шейпа! Просто MsgBox что у какого-то шейпа (не явно указанного) есть свойство prop.row_1 и совпадает/не совпадает с искомым значением - абсолютно не информативно IMHO

Автор:  Machestro [ 20 окт 2016, 13:01 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

Surrogate писал(а):
это отлавливание изменений должно происходить в процессе работы с документом ? Изображение. или уже при финальном редактировании документа ?
- Да при работе с документом

Я понимаю, что MSBox это не информативно, просто это для меня был самый простой способ показать себе что есть ещё такие шейпы. Это же не финальная функция, я диш пытаюсь понять принцип и реализовать его

Автор:  Surrogate [ 20 окт 2016, 13:01 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

Machestro писал(а):
- Да
это за какой вариант ?

Автор:  Machestro [ 20 окт 2016, 13:03 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

Surrogate писал(а):
Machestro писал(а):
- Да
это за какой вариант ?

Изменил свой комент.
Вообщем при работе с документом

Автор:  Surrogate [ 20 окт 2016, 13:06 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

Machestro писал(а):
Вообщем при работе с документом
а насколько велика вероятность что совпадения значения у разных шейпов в пределах документа ?

Автор:  Machestro [ 20 окт 2016, 13:08 ]
Заголовок сообщения:  Re: Поиск шейпов при определённом событии

Совпадения будут происходить регулярно

Страница 1 из 3 Часовой пояс: UTC + 3 часа [ Летнее время ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/