4 Replies Latest reply on Jun 14, 2016 12:08 PM by pthivierge

    Multi-state a String using VBA

    Mikeconnors

      Hi All,

       

      I'm wondering how to go about multi-stating a rectangle so that when particular PI tags trigger, it changes color. The tricky part is that I need it to trigger based on String values and I don't see why you can't do that in VBA. I am quite new to VBA and the biggest problem I'm having is where to actually put the damn function once I've written it (I learnt to multi-state a Label using a different thread and want to apply the same logic, that thread is here: Create a multi-state of a value in a Form using VBA ). should it be written directly in ThisDisplay, or should I create a Class? below is what I have so far and it doesn't work. I've tried to create a class but it doesn't compile

       

       

      Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) ' Library containing sleep function
      
      Dim Flash As Boolean
      Dim tagnameAllBuffStat As String
      Dim tagvalueAllBuffStat As String
      
      Dim tag As PIPoint
      Dim mysrv As Server
      
      Flash = True
      Set mysrv = PISDK.Servers.Item("WAIOHistorianSandbox")
      
      tagnameAllBuffStat = mysrv.PIPoints("Perth.EasternRidge.AF.All_Buffer_Status")
      tagvalueAllBuffStat = mysrv.PIPoints(tagnameAllBuffStat).Data.Snapshot
      
      Public Function ErrorStatus(ByVal Flash)
      
            ' Infinite loop to flash between red and blue if statement is true (Multi-state)
              Do While Flash = True
         
             'Set conditions for multi-state
              If buttonEasternRidge.BackgroundColor = RGB(0, 0, 128) And tagvalueAllBuffStat = "OK" Then
                 Me.buttonEasternRidge.BackgroundColor = RGB(100, 0, 0)
             
              Else: Me.buttonEasternRidge.BackgroundColor = RGB(0, 0, 128)
           
              End If
              Sleep (300)
              DoEvents
          Loop
      
      End Function
      

       

       

      Thanks for your help, let me know if you need more details.

       

      Michael

        • Re: Multi-state a String using VBA
          John Messinger

          Michael,

           

          You can place all of this code on the ThisDisplay VB Editor object. For simplicity, let's assume that all this code with be on ThisDisplay. First things first, I assume that the following variable are intended to be global:

          Dim Flash As Boolean
          Dim tagnameAllBuffStat As String
          Dim tagvalueAllBuffStat As String
          
          Dim tag As PIPoint
          Dim mysrv As Server
          

           

          The next chunk of code needs to live within a sub or function. As you are initialising your variables, I would put them in the Display_Open() subroutine:

          Private Sub Display_Open()
          
              Flash = True
              Set mysrv = PISDK.Servers.Item("WAIOHistorianSandbox")
          
              tagnameAllBuffStat = mysrv.PIPoints("Perth.EasternRidge.AF.All_Buffer_Status")
              tagvalueAllBuffStat = mysrv.PIPoints(tagnameAllBuffStat).Data.Snapshot
              
          End Sub
          

           

          Finally, your ErrorStatus function needs to live within its own code block:

          Public Function ErrorStatus(ByVal Flash)
          
           ' Infinite loop to flash between red and blue if statement is true (Multi-state)
             Do While Flash = True
                 'Set conditions for multi-state
                 If buttonEasternRidge.BackgroundColor = RGB(0, 0, 128) And tagvalueAllBuffStat = "OK" Then
                     Me.buttonEasternRidge.BackgroundColor = RGB(100, 0, 0)
            
                 Else: Me.buttonEasternRidge.BackgroundColor = RGB(0, 0, 128)
          
                 End If
                 Sleep (300)
                 DoEvents
             Loop
          
          End Function
          

           

          You would call the ErrorStatus function from another code block. As you are testing on the value of a specific tag (tagvalueAllBuffStat), using the Display_DataUpdate() event is a reasonable place to do so, as this event is called every time the display requests new data (every 5 seconds by default).

           

          So your final code might look like the following:

          Option Explicit
          
          Dim Flash As Boolean
          Dim tagnameAllBuffStat As String
          Dim tagvalueAllBuffStat As String
          
          Dim tag As PIPoint
          Dim mysrv As Server
          
          Private Sub Display_DataUpdate()
          
              Call ErrorStatus(Flash)
              
          End Sub
          
          Private Sub Display_Open()
          
              Flash = True
              Set mysrv = PISDK.Servers.Item("WAIOHistorianSandbox")
          
              tagnameAllBuffStat = mysrv.PIPoints("Perth.EasternRidge.AF.All_Buffer_Status")
              tagvalueAllBuffStat = mysrv.PIPoints(tagnameAllBuffStat).Data.Snapshot
              
          End Sub
          
          Public Function ErrorStatus(ByVal Flash)
          
           ' Infinite loop to flash between red and blue if statement is true (Multi-state)
             Do While Flash = True
          
                 'Set conditions for multi-state
                 If buttonEasternRidge.BackgroundColor = RGB(0, 0, 128) And tagvalueAllBuffStat = "OK" Then
                     Me.buttonEasternRidge.BackgroundColor = RGB(100, 0, 0)
            
                 Else: Me.buttonEasternRidge.BackgroundColor = RGB(0, 0, 128)
          
                 End If
                 Sleep (300)
                 DoEvents
             Loop
          
          End Function
          

           

          Hope this helps.

           

          Regards,

          John

          tagvalueAllBuffStat

          3 of 3 people found this helpful
            • Re: Multi-state a String using VBA
              Mikeconnors

              Hi John, that is really helpful thanks. Exactly the answer I was looking for. However If I am to have multiple multi-stated buttons on my screen with multiple tags linked to each one, ThisDisplay gets really big and messy quite quickly. I'm much more familiar with C programming that VBA, is it possible to create separate files with each buttons actions and call them into ThisDisplay a bit like a main file? or is that the wrong way of thinking with VBA?

               

              Also on an unrelated note, how do you paste code into the forum in that format? it's so much nicer to look at.

               

              Cheers,

              Michael

                • Re: Multi-state a String using VBA
                  John Messinger

                  So ordinarily I would suggest looking at parameterising your code to handle this, where you might pass in the name of the object to be modified, as well as the name of the associated tag. Another option is to use code modules (not class modules). In this way, you could separate the code to be executed for each button, and keep ThisDisplay less cluttered if you want. Even with doing this though, it would be better to look at coding such that you reduce the amount of repeated code and logic where the only real differentiator is the button name and/or tag names. How you might do this depends various factors, such as what type of objects you have on the display, what your overall intention is etc. Like all programming languages and projects, once you have the basic functionality working in your ProcessBook VBA, you refactor to improve code quality and readability. But code modules for each button might be a good start for tidying things up, even if just using a single code module with multiple functions, one for each button on the display. Those functions can then be called from thisDisplay using the same syntax - Call SomeFunction().

                   

                  In answer to your other question, use the advanced editor from the link at the top right corner of your post editor box, and then use the syntax highlighting option available from the Insert button (>>) on the toolbar.

                   

                  Regards,

                  John

                  • Re: Multi-state a String using VBA
                    pthivierge

                    If we are talking about code refactoring, one nice way of using classes with VBA is to pass it your object.

                     

                    Example: clsButton

                    Public WithEvents ToggleButton As CommandButton ' this allows you to select events of this object from the class module.
                    
                    Private Sub ToggleButton_Click()
                        Debug.Print "clicked from class"
                    End Sub
                    
                    Public Sub Init(btn as CommandButton)
                        Set ToggleButton = btn
                    End Sub
                    
                    

                     

                    When declaring an object as WithEvents, you are getting access to all the events available for this object.

                     

                    Scenario: Imagine you want to encapsulate the bahavior of many buttons into the same code logic.

                    You then use instances of the same class so each object can behave on its own, based on the same code (class).:

                    Private button1Handler As New clsButton
                    Private button1Handler As New clsButton
                    Public Sub EncapsulateButtonsLogic()
                         button1Handler.Init ThisDisplay.btn1
                         button1Handler.Init ThisDisplay.btn2
                         '...
                    End Sub
                    

                     

                    I believe this is a quite elegant approach

                     

                    Hope this helps,

                    ' this allows yo

                    u to select events of this object from the class module.

                    1 of 1 people found this helpful