13 Replies Latest reply on Jan 11, 2011 12:47 AM by spilon

    How to execute VBA code on a Context Change

    Claude Martineau

      In a ProcessBook context relative display, changing context is not an event on which VBA code can be executed.

       

      One way to go around this is to Hide the Module Context pane and to add a Microsoft Forms List Box on the display.  This List Box should be loaded when the display opens with all the modules that are part of the display.  When a module is selected in the Listbox, VBA code is used to set the current display context to this module.

       

      The benefits of using this mechanisn are:

      • VBA code can be launched when a new module is selected (a ListBox_Change event is avaialble)
      • The list of available module can be located where best suited on the display.  it does not have to be on the left hand side or to take the whole height.
      • The list of available module does not have to include the hierarchy (which is shown in the Module Context pane) when modules from different locations are used.
      • Adding and removing modules to the display is done the same way as usual, therefore display maintenance issues are minimised.  The modules that are part of the list box are not hard coded.
        • Re: How to execute VBA code on a Context Change

          Can you not make use of the CurrentContext property to look out for a switch?  So in the DataUpdate event (every 5 seconds) check what the currently stored context is (in a variable, text object on the display) and if it changes then call your VBA methods.  This way if OSI implement something into the standard context pane it won't be missed by using your own control.

           

          I notice there is a ContextUpdate method that can be called manually, shame this does not generate a "ContextChanged" event.

            • Re: How to execute VBA code on a Context Change
              Claude Martineau

              Thanks for your reply,

               

              I do not like the idea of using the DataUpdate event though, I try to avoid it as much as possible.  Of course, it this case the code to run is mimimal and should not impact performances. 

               

              However, the DataUpdate frequency is a setting that is defined on each client machines.  I have seen cases where clients (with lots of data over a slow WAN) were setting this to 30 or even 60 seconds. 

                • Re: How to execute VBA code on a Context Change

                  Checking the CurrentContext property in the DataUpdate event is a good and simple workaround. While this is for now the only solution using ProcessBook elements only, I would agree with Claude and be hesitant before to put anything in there: this event is most likely the one people already use for a number of operations and the DataUpdate event is by far the most resource-intensive time for ProcessBook. Plus, from a pure "Object-Oriented Programming" standpoint, it is not a good practice to run something on each and every iteration even when not necessary - as opposed to "when needed" (i.e. event-driven).

                   

                  But again, this is the only solution using ProcessBook elements only - for now...

                   

                  That said, I checked in our database and we don't seem to have any plans to address that (Claude, you apparently are the first one reporting this!) so I forwarded the request to the ProcessBook development team. I'll post an update when I hear from them.

                    • Re: How to execute VBA code on a Context Change

                      Sorry about the confusion... I have to revisit my answer. And you'll be happy about that  I must admit I feel a little bad now: I happened to have a 3.0.x version of ProcessBook installed on my PC and just didn't think of validating my statement against v3.1 (it was very early this morning and before my first coffee... )  As for the enhancement request, I finally found it: look at #7882OSI8 in the PB 3.1 Release Notes.

                       

                      Anyways, here's the solution to your problem:

                      Private WithEvents myCtxtHndlr As ContextHandler

                      Private Sub Display_Open()
                          Set myCtxtHndlr = Application.ContextHandlers(1)
                      End Sub

                       

                      Private Sub myCtxtHndlr_ContextChanged(FromDisplay As Display, FromContextHandler As ContextHandler)
                       MsgBox (myCtxtHndlr.CurrentContext(FromDisplay))
                      End Sub

                        • Re: How to execute VBA code on a Context Change
                          gpriyanka

                          Steve,

                           

                          I am trying to execute VBA code when a context is changed.  

                           

                          I am implementing something similar to http://vcampus.osisoft.com/forums/p/1059/5222.aspx where I have a parent-child display. A context change in the parent display changes the context on the child display. I want VBA code to be executed on the child diplay if the parent display changes context leading to a context change in child diplay.

                           

                          Steve Pilon

                                   Private WithEvents myCtxtHndlr As ContextHandler

                           Private Sub Display_Open()
                              Set myCtxtHndlr = Application.ContextHandlers(1)
                          End Sub

                          Private Sub myCtxtHndlr_ContextChanged(FromDisplay As Display, FromContextHandler As ContextHandler)
                           MsgBox (myCtxtHndlr.CurrentContext(FromDisplay))
                          End Sub

                           

                          I used the code that you provided in the child display but nothing is getting executed from the Sub myCtxtHndlr_ContextChanged. Is this a Processbook VBA sub or are you using the 'Change' Event? What else can I try?

                            • Re: How to execute VBA code on a Context Change
                              hanyong

                              the code snippet that Steve posted can be used in Processbook VBA, and what it does is that it would capture context change event, and allowing you to define your custom actions when the event is captured. We can break it down into 3 parts:

                               

                               Private WithEvents myCtxtHndlr As ContextHandler 

                              This defines a ContextHandler that handles events

                               

                              Private Sub Display_Open()
                                  Set myCtxtHndlr = Application.ContextHandlers(1)
                              End Sub

                              This basically references the defined ContextHandler to the 1st ContextHandler of the application, alternatively you can do something like:
                              Private Sub Display_Open()
                                  Set myCtxtHndlr = Application.ContextHandlers('E')
                              End Sub

                              to explicitly reference to the Element Relative Display (ERD) context handler.

                               

                              Private Sub myCtxtHndlr_ContextChanged(FromDisplay As Display, FromContextHandler As ContextHandler)
                               MsgBox (myCtxtHndlr.CurrentContext(FromDisplay))
                              End Sub

                              This is the event handler that gets executed when a context change is captured.

                               

                              Based on what you described, you can implement this in the parent display, such that context change event in the parent display would be captured, and you can modify the ContextChanged method to pass the context of the parent display to the child display.

                                • Re: How to execute VBA code on a Context Change
                                  gpriyanka

                                  Han,

                                   

                                  Thanks for explaining the code. I was able to change the context on the child display using the post in http://vcampus.osisoft.com/forums/p/1059/5222.aspx. What I am trying to do now is to execute some code on the child display to change the datasets when its context changes even if the display is already open. The context change in the Parent display is initiated by a Click event. As mentioned before, the code within ContextChanged in the child display is not executed when I change the context through the parent display. My code is below. Any Thoughts?

                                  
                                  

                                  'Parent Display

                                  Private Sub Text2_Click(ByVal lvarX As Long, ByVal lvarY As Long)
                                  changecontext (Text2.Contents)
                                  End Sub

                                  Sub changecontext(ChildContext As String)

                                  Dim contextpath As String
                                  contextpath = "\\PiServer\WiredCity\Servers" & "\" & ChildContext

                                  ' Define The Contexthandlers
                                  Dim MrdContextHandler As ContextHandler
                                  Set MrdContextHandler = Application.ContextHandlers("ModuleContext")
                                  Dim AliasContextHandler As ContextHandler
                                  Set AliasContextHandler = Application.ContextHandlers("Alias")
                                  Dim PropContextHandler As ContextHandler
                                  Set PropContextHandler = Application.ContextHandlers("Property")

                                  ' set current context
                                  MrdContextHandler.CurrentContext(ThisDisplay) = contextpath
                                  AliasContextHandler.CurrentContext(ThisDisplay) = contextpath
                                  PropContextHandler.CurrentContext(ThisDisplay) = contextpath

                                  ' Get the path from this display, excluding filename
                                  Dim myPath As String
                                  myPath = ThisDisplay.Path
                                  myPath = Left(myPath, InStrRev(myPath, "\", -1, vbTextCompare))

                                  Dim childdisplay As Display
                                  Set childdisplay = Application.Displays.Open(myPath & "childdisplay.PDI", True)

                                  ' Set all three contexthandlers to have the same context in Child and Parent
                                  MrdContextHandler.CurrentContext(childdisplay) = MrdContextHandler.CurrentContext(ThisDisplay)
                                  AliasContextHandler.CurrentContext(childdisplay) = AliasContextHandler.CurrentContext(ThisDisplay)
                                  PropContextHandler.CurrentContext(childdisplay) = PropContextHandler.CurrentContext(ThisDisplay)

                                  End Sub

                                  
                                  

                                  'Child Display

                                  Private WithEvents myCtxtHndlr As ContextHandler
                                  Private Sub Display_Open()
                                  Set myCtxtHndlr = Application.ContextHandlers("ModuleContext")
                                  End Sub

                                  Private Sub myCtxtHndlr_ContextChange(FromDisplay As Display, FromContextHandler As ContextHandler)
                                  resetDatasets()
                                  End Sub

                                  Sub resetDatasets()

                                  End Sub