6 Replies Latest reply on Jul 31, 2013 12:03 PM by Marcos Vainer Loeff

    PI ProcessBook Element Relative Display Open

    Fran

      Hi,

       

      I am trying to do the following i ProcessBook with VBA.

       

      In an Element Relative Display, I want to open a distinct pdi depending on the selected node (there is one AF Attribute which contains this information.

       

      The problem is that if I try to close the old pdi and assign the correct node in the new display, it works, but the ERD Dock Window on the left, always shows the root hierarchy node.

       

      is there any way to decide what the contexthanlder should show? Is it possible opening anew display inthe same windows as with the PB Button (not openm new and close the old) ?

       
      Dim CurrentOpenPDI As String
      Dim CurrentOpenPDIPath As String
      
      Private Sub svg_Path_DataUpdate()
          Check_Display
      End Sub
      
      Private Sub Check_Display()
          Dim vrDate As Variant
          Dim vrStatus As Variant
          Dim NewDisplay As Display
          Dim OldContextPath As String
      
          ' gets the currently open pdi
          CurrentOpenPDI = ThisDisplay.Path
          SplitPath = Split(CurrentOpenPDI, "\", , vbTextCompare)
          CurrentOpenPDI = SplitPath(UBound(SplitPath))
          CurrentOpenPDIPath = Replace(ThisDisplay.Path, "\" & CurrentOpenPDI, "")
          
          'gets the path selected in the context handler
          Dim AFContext As ContextHandler
          Set AFContext = Application.ContextHandlers("E")
          OldContextPath = AFContext.CurrentContext(ThisDisplay)
          
          'gets from a PBValue with the attribute for the new pdi the pdi to open
          newpdipath = svg_Path.GetValue(vrDate, vrStatus)
          If newpdipath <> "" Then
              SplitPath = Split(newpdipath, "/", , vbTextCompare)
              newpdipath = SplitPath(UBound(SplitPath))
          Else
              GoTo NoDisplayChange
          End If
      
          'if the new and old display are different, open it
          If newpdipath <> CurrentOpenPDI Then
              Dim NewDisplayPath As String
              Dim OldDisplay As Display
              On Error GoTo NoDisplayChange
              Set OldDisplay = ThisDisplay
              NewDisplayPath = CurrentOpenPDIPath & "\" & newpdipath
              Set NewDisplay = Application.Displays.Open(NewDisplayPath, True)
              AFContext.CurrentContext(NewDisplay) = OldContextPath
      
              'here is the problem, closing the old pdi, will imply that root node is selected  in the contexthandler
              OldDisplay.Close (False)
          End If
          End
      NoDisplayChange:
          Debug.Print ("Display cannot be found " & NewDisplayPath)
      End Sub
      

      Thank you in advance for suggestion,

       

      Fran

        • Re: PI ProcessBook Element Relative Display Open

          Hello Fran,

           

          I believe you are running into a timing issue. Have you tried storing the ContextPath to a Global variable and to set the Context via VBA within the display just opened e.g. when Display.DataUpdate fires for the first time?

           

          Here is another thread with a similar question.

            • Re: PI ProcessBook Element Relative Display Open

              Sorry Fran,

               

              Setting the Context within a display is a single line of code

               

               

               
              Application.ContextHandlers("E").CurrentContext(ThisDisplay) = sContextPath
              

               but requires that sContextPath is defined somewhere outside.

               

              You are dealing with an "OldDisplay" (to be closed) and a "NewDisplay" to be opened. I am wondering where you've placed your code. If it's within the "OldDisplay" I could imagine that closing it causes an issue with code execution namely setting the Context for the new display. You could try if inserting a pause before closing "OldDisplay" helps.

               

              What should work in any case is storing the ContextPath outside ProcessBook i.e. into a text file. Then you can use the Display.DataUpdate within "NewDisplay" to evaluate if it has fired for the first time. If so, read the context from the file, compare it against the current selected context and set the context if different.

                • Re: PI ProcessBook Element Relative Display Open
                  Marcos Vainer Loeff

                  Hello Fran,

                   

                  Please change your code using Gregor's suggestion. It will result on the code snippet below. The context chosen when the new display is opened will be last one selected on the old display. It has worked for me pretty well!

                   

                   

                   
                  If newpdipath <> CurrentOpenPDI Then
                          Dim NewDisplayPath As String
                          Dim OldDisplay As Display
                          On Error GoTo NoDisplayChange
                          Set OldDisplay = ThisDisplay
                          NewDisplayPath = CurrentOpenPDIPath & "\" & newpdipath
                          Set NewDisplay = Application.Displays.Open(NewDisplayPath, True)
                          Application.ContextHandlers("E").CurrentContext(NewDisplay) = OldContextPath
                          'AFContext.CurrentContext(NewDisplay) = OldContextPath
                   
                          'here is the problem, closing the old pdi, will imply that root node is selected  in the contexthandler
                          OldDisplay.Close (False)
                  

                   

                   

                  Hope this helps you!

                    • Re: PI ProcessBook Element Relative Display Open
                      Fran

                      Thank you for the rapid answers.

                       

                      I had previously tried putting the CuurentContext setting in both positions with success.

                       

                      I set the new Display context from the old display, so probably I will need the new display to change it and close the old one, but I am trying to figure out how to achieve it.

                       

                      I will let you know if I come to an answer.

                       

                      Regards,

                       

                      Fran

                        • Re: PI ProcessBook Element Relative Display Open
                          Fran

                          Here goes the soultion I found based on vcampus.osisoft.com/.../1628.aspx.

                           

                          The Old Display passes its context to the new display and then closes itself. Then OnActivate() the new display sets its context to the one passed by the old one before.

                           

                           Hore goes the code:

                           
                          Dim CurrentOpenPDI As String    'Name of the open pdi
                          Dim CurrentOpenPDIPath As String    'Path of the currently open pdi
                          Dim ContextfromOutside As String    'Contextto use as coming from the calling pdi
                          
                          Private Sub Display_Activate()
                          ' after the display is open, if it is from n external pdi,
                          ' apply the AF Context as in ContextfromOutside
                              If ContextfromOutside <> "" Then
                                  application.ContextHandlers("E").CurrentContext(ThisDisplay) = ContextfromOutside
                                  ContextfromOutside = "" 'to avoid "reactivations" and subsequent context resets
                              End If
                          End Sub
                          
                          Private Sub Display_BeforeSave(ByVal bSaveAsUi As Boolean, bCancel As Boolean)
                              ThisDisplay.Close (False)
                          End Sub
                          
                          Private Sub svg_Path_DataUpdate()
                          ' when the svg\pdi hidden value is changed check if a different pdi must be open
                              Check_Display
                          End Sub
                          
                          Public Sub SetContextfromOutside(inContext As String)
                          ' to be called from previous pdi to set the context to go at activation
                              ContextfromOutside = inContext
                          End Sub
                          
                          Private Sub Check_Display()
                              Dim vrDate As Variant 'date for the Value symbol
                              Dim vrStatus As Variant 'Status for the Value symbol
                              Dim NewDisplay As Display 'New display to eventually open
                              Dim OldContextPath As String 'AF Context of the current display
                              
                              CurrentOpenPDI = ThisDisplay.Path 'gets path of thisdisplay
                              'the following is to get the path of the folder where ThisDisplay is
                              SplitPath = Split(CurrentOpenPDI, "\", , vbTextCompare)
                              CurrentOpenPDI = SplitPath(UBound(SplitPath))
                              CurrentOpenPDI = Replace(CurrentOpenPDI, ".svg", ".pdi")
                              CurrentOpenPDI = Replace(CurrentOpenPDI, "%20", " ")
                              CurrentOpenPDIPath = Replace(ThisDisplay.Path, "\" & CurrentOpenPDI, "")
                              
                              'Gets the current context
                              Dim AFContext As ContextHandler
                              Set AFContext = application.ContextHandlers("E")
                              'to be used on display close
                              If AFContext = "" Then
                                  GoTo ClosingDisplay
                              End If
                              'gets the current context
                              OldContextPath = AFContext.CurrentContext(ThisDisplay)
                              'gets the new pdi name from a Value symbol
                              '(actually it is the address of a svg with the same name as the new pdi to open)
                              newpdipath = svg_Path.GetValue(vrDate, vrStatus)
                              If newpdipath <> "" Then
                                  SplitPath = Split(newpdipath, "/", , vbTextCompare)
                                  newpdipath = SplitPath(UBound(SplitPath))
                                  newpdipath = Replace(newpdipath, ".svg", ".pdi")
                                  newpdipath = Replace(newpdipath, "%20", " ")
                              Else
                                  GoTo NoDisplayChange
                              End If
                              ' if the new pdi's name and current pdi's name are different, open the new display
                              If newpdipath <> CurrentOpenPDI Then
                                  Dim NewDisplayPath As String 'Path of the display to open
                                  Dim OldDisplay As Display 'OldDisplay object
                                  On Error GoTo NoDisplayChange
                                  Set OldDisplay = ThisDisplay 'acquires the currently open display
                                  NewDisplayPath = CurrentOpenPDIPath & "\" & newpdipath 'gets the new display to open path
                                  Set NewDisplay = application.Displays.Open(NewDisplayPath, True) 'opens the new display
                                  'sets the new display's initial AF Context
                                  Call NewDisplay.SetContextfromOutside(OldContextPath)
                                  OldDisplay.Close (False) 'close this display
                              End If
                              Exit Sub
                          NoDisplayChange:
                              Debug.Print ("Display cannot be found " & NewDisplayPath)
                              Exit Sub
                          ClosingDisplay:
                              Debug.Print ("AFContext is null, closing display")
                              Exit Sub
                          End Sub