14 Replies Latest reply on Oct 3, 2016 2:50 PM by jaroberts

    A couple of Processbook VBA tips...

    AlistairFrith

      Thought I would post a couple of nuggets I have discovered since I seem to be asking a lot of questions at the moment.

       

      If you try this

      Application.ActiveDisplay.Symbols.Add(pbSymbolComposite)

      you will get a message saying that you cannot create a composite object programatically (along with a few other tasks). However what you can do is copy an existing composite object. so I have the following function:

       

      ' We can't create a composite object programmatically but we can copy one from the
      ' macros display to the current display
      Function NewComposite() As Composite
         Dim dMacros As Display
         Dim dCurrent As Display
         Dim sComp As Composite

         Set dMacros = builderDisplay() '<-- this function finds a display that has a specific composite symbol
         Set dCurrent = Application.ActiveDisplay

         ' just make sure there is nothing selected
         Do While dMacros.SelectedSymbols.count > 0
           dMacros.SelectedSymbols.Remove (1)
         Loop

         dMacros.Symbols("TemplateComposite").selected = True
         dMacros.Copy
         Dim tries As Integer
         Do While sComp Is Nothing And tries < 5  '
      <-- can't remember why I had to retry this bit!
           tries = tries + 1
           dCurrent.Paste
           On Error Resume Next
           Set sComp = dCurrent.Symbols("TemplateComposite")
           On Error GoTo 0
         Loop

         ' Extract the dummy objects in the composite and delete them
         Do While sComp.GroupedSymbols.count > 0
           sComp.GroupedSymbols.Remove (1)
         Loop
         dCurrent.Symbols.Remove ("TempCompRect1")
         dCurrent.Symbols.Remove ("TempCompRect2")

         Set NewComposite = sComp
      End Function

       

      Another thing you cannot do in VBA is change the Z-order of the symbols on the display. However, what you can do is add them to a composite object and then remove them again. This will put them back in the display's symbols collection at the top of the Z-order.

       

      Hope these tips are useful to people.

       

      --- Alistair.

       

       

        • Re: A couple of Processbook VBA tips...

          Alistair,

          It is quite true that you cannot create a new composite via Symbols.Add as you can't supply the symbols to form the composite symbol.  You need to select the symbols and then group them, the returned object is a composite symbol.

           

          Example (assumes 2 rectangles on the display):

           

          Dim s As Symbol
          For Each s In ThisDisplay.Symbols: s.Selected = False: Next s
             
          ThisDisplay.Symbols("Rectangle1").Selected = True
          ThisDisplay.Symbols("Rectangle2").Selected = True
             
          Dim MyComp As Composite
          Set MyComp = ThisDisplay.SelectedSymbols.Group

          2 of 2 people found this helpful
            • Re: A couple of Processbook VBA tips...
              AlistairFrith

              And there was I thinking I was providing a handy tip!

               

              What about the Z-ordering workaround? Is there a better way to do that as well?

               

              --- Alistair.

                • Re: A couple of Processbook VBA tips...

                  Nope, to my knowledge OSI didn't expose z ordering for symbols (PBControls).  The nearest we get to this is in the latest version of ProcessBook with the use of layers but still you don't get to access the z order of the symbols within a layer.  A shame as with Excel VBA for example you can manipulate the z order of shapes.

                    • Re: A couple of Processbook VBA tips...
                      mweiss

                      The zorder is the order the symbols were created in. There isn't any other way via automation to change this order.

                       

                      So, for example, if you had to add a symbol via automation that was under all other symbols you would have to delete all the symbols, add this new one, and then re-add all the symbols you deleted. Which, obviously, is not something you should even consider doing!

                       

                       

                        • Re: A couple of Processbook VBA tips...

                          Michael Weiss

                          The zorder is the order the symbols were created in. There isn't any other way via automation to change this order.

                           

                          So, for example, if you had to add a symbol via automation that was under all other symbols you would have to delete all the symbols, add this new one, and then re-add all the symbols you deleted. Which, obviously, is not something you should even consider doing!

                           

                           

                          Precisely.

                           

                          Was there a specific reason this was omitted from doing this via automation seen as though you can rotate & flip a symbol?

                           

                          You can change the z order manually using the arrange menu.

                           

                           

                            • Re: A couple of Processbook VBA tips...
                              MikeReid

                              If you want to bring an object to the front, just get the object from the Symbols collection into a symbol object variable, remove it from the collection and add it back in - you don't need to use any other grouping for a single object.

                               

                              Anything other than bring to the front is harder becasue you need to rearrange the whole collection.

                               

                              One other gotcha if you use Virtual PC (as I did when I investigateed this first) - the Virtual Machine causes some sort of conflict. Can't remember the exact solution, but you can modify the VM configuration to allow it.

                               

                              If you do a lot of object manipulation - remember to switch off application redrawing while your doing it - it's much faster.

                              • Re: A couple of Processbook VBA tips...
                                mweiss

                                Rhys @ RJK Solutions

                                Was there a specific reason this was omitted from doing this via automation seen as though you can rotate & flip a symbol?

                                 

                                You can change the z order manually using the arrange menu.

                                 

                                I don't know why this was left out. I'm not sure if there were technical reasons or just an oversight.

                          • Re: A couple of Processbook VBA tips...
                            jimps

                            I'm not sure if it is "better" but there is a way to use Arrange/Send To Back and Arrange/Bring To Front with Automation.  Below is some code to illustrate this.  It is also sometimes useful to keep a list of symbol names in an array to later use for sorting/stacking purposes.  Then you can build some code to reset the z-order of everything on the display by just bumping them to the top or bottom of the z-order stack.

                            
                            

                            Dim myArrangeBringToFront As Object, myArrangeBringToFront As Object, myCmdBar As Object
                               
                                ' Setup Arrange, Bring To Front and Send To Back commands
                                ' Use custom toolbar for custom buttons
                               
                                Set myCmdBar = Nothing
                                Set myCmdBar = Application.CommandBars("MyCmdBar")
                                If myCmdBar Is Nothing Then
                                    ' If the command bar does not exist, create it
                                    Set myCmdBar = Application.CommandBars.Add("MyCmdBar")
                                End If
                               
                                ' Test to see if we already have the buttons created on our command bar (maybe they already exist)
                                Set myArrangeBringToFront = Nothing
                                Set myArrangeSendToBack = Nothing
                                For X = 1 To myCmdBar.Controls.Count
                                    If myCmdBar.Controls.Item(X).Id = 32837 Then ' Bring To Front
                                        Set myArrangeBringToFront = myCmdBar.Controls.Item(X)
                                    ElseIf myCmdBar.Controls.Item(X).Id = 32838 Then ' Send To Back
                                        Set myArrangeSendToBack = myCmdBar.Controls.Item(X)
                                    End If
                                Next X
                               
                                If myArrangeBringToFront Is Nothing Then
                                    Set myArrangeBringToFront = myCmdBar.Controls.Add(pbControlButton, 32837)   ' Bring To Front
                                End If
                                ' User does not need to see the button
                                myArrangeBringToFront.Visible = False

                                If myArrangeSendToBack Is Nothing Then
                                    Set myArrangeSendToBack = myCmdBar.Controls.Add(pbControlButton, 32838)   ' Send To Back
                                End If
                                ' User does not need to see the button
                                myArrangeSendToBack.Visible = False
                               
                               
                               
                               
                               
                                ' Programmatically select symbol(s)
                                ' I use the SelectedSymbols object to make sure everything else is unselected
                               
                                ThisDisplay.SelectedSymbols.RemoveAll ' This just removes symbols from the SelectedSymbols object, which unselects everything
                                ThisDisplay.Symbols("Rectangle1").Selected = True
                               
                                ' "Click" the custom command button
                                myArrangeBringToFront.Execute ' This is the automated way to manually click the Arrange/Bring To Front menu item
                               
                                ' or
                               
                                myArrangeSendToBack.Execute ' This is the automated way to manually click the Arrange/Send To Back menu item
                               
                               
                               
                               
                                ' Of course remember to remove the objects when finished
                                If Not myArrangeBringToFront Is Nothing Then
                                    myArrangeBringToFront.Delete
                                    Set myArrangeBringToFront = Nothing
                                End If
                               
                                If Not myArrangeSendToBack Is Nothing Then
                                    myArrangeSendToBack.Delete
                                    Set myArrangeSendToBack = Nothing
                                End If
                               
                                If Not myCmdBar Is Nothing Then
                                    myCmdBar.Delete
                                    Set myCmdBar = Nothing
                                End If

                             

                            Charles. (First post!) 

                        • Re: A couple of Processbook VBA tips...
                          pthivierge

                           Hi Guys, 

                           

                          I had to work on this lately and I was struggling a lot to find the good thing, I wanted simple code.  But finally I ended up with this code which is really easy to use and really simple.  Just put it in a module.  Before send to back or bring to front you need to select the objects first:

                           

                           

                           
                          ThisDisplay.SelectedSymbols.RemoveAll
                          ThisDisplay.Button1.Selected=True
                          ...
                          

                           

                           

                          Then you can call one of the two to bring to front or send to back:

                           
                          Public Sub SendToBack()
                              Dim oCmdbar As Object
                              Set oCmdbar = Application.CommandBars("Default Menu Bar")
                              oCmdbar.Controls("&Arrange").Controls("&Send To Back").Execute
                          End Sub
                          
                          Public Sub BringToFront()
                              Dim oCmdbar As Object
                              Set oCmdbar = Application.CommandBars("Default Menu Bar")
                              oCmdbar.Controls("&Arrange").Controls("Bring To Fron&t").Execute
                          End Sub
                          

                           

                           

                          I did use this link to inspire me the solution using process book: http://stackoverflow.com/questions/8218245/execute-menu-commands-in-powerpoint

                           

                          I really hope this helps and I am sure this snippet can be reused to any command that sits in the PI ProcessBook Menu bar.  To know what is in the menu bar you could use this snippet, this is necessary because you need to call the "Controls" collection with the right string, and this is the only way to display it.

                           

                           

                           
                          Sub ShowMenuNames()
                              Dim oCmdbar As Object
                              Dim oCtl As Object
                              ' for example, let's look at the Standard toolbar:
                              Set oCmdbar = Application.CommandBars("Default Menu Bar")
                          
                              For Each ctrl In oCmdbar.Controls()
                                  Debug.Print ctrl.Caption
                              Next
                          End Sub
                          
                          Sub ShowTheControlNames()
                              Dim oCmdbar As Object
                              Dim oCtl As Object
                              ' for example, let's look at the Standard toolbar:
                              Set oCmdbar = Application.CommandBars("Default Menu Bar")
                          
                              For Each ctrl In oCmdbar.Controls("&File").Controls()
                                  Debug.Print ctrl.Caption
                              Next
                          End Sub
                          

                           

                            • Re: A couple of Processbook VBA tips...

                              Hello Patrice,

                               

                              Thanks a lot for sharing and especially for the attitude this proves

                               

                               

                               

                              Edit: proofs replaced with proves.  

                              • Re: A couple of Processbook VBA tips...
                                zge

                                Hi Patrice,

                                 

                                I got some problem running the send to back and bring to front snippets. They work fine under debugging, but in run mode (no break point), the tool bar functions does not work. I'm running this code in VM and I wonder if this code runs as is expected in other environments.

                                 

                                I came up with a workaround for the Bring To Front function - use the SelectedSymbols.Group. Create a dummy symbol, group, ungroup, and delete the dummy:

                                 

                                Set MySymbol = Symbols.Add(pbSymbolText)
                                MySymbol.SetName ("Dummy")
                                MySymbol.Selected = True
                                
                                SelectedSymbols.Group
                                SelectedSymbols.Ungroup
                                SelectedSymbols.RemoveAll
                                
                                Symbols.Remove ("Dummy")
                                
                                  • Re: A couple of Processbook VBA tips...
                                    jaroberts

                                    Hi Zhenqi,

                                    I realize this is an old thread, but I recently had a case escalated to me regarding this issue.  If you're interested, here's what I found:

                                    • Send To Back and Bring To Front are not available in Run mode.  This is true in the GUI as well as programmatically.  I get around this in the PDI by going to Build mode, then going back to Run mode once finished.
                                    • The positioning of the ampersand (&) in the control captions seems a bit random--usually it's in the front, but not always.  Example:  Bring To Fron&t.  This is because the ampersand always precedes the shortcut character.  Since t is the shortcut character for Bring To Front, that's why the ampersand goes right before the t rather than at the beginning.

                                    • ProcessBook handles the Execute method on a command bar button by posting a Windows message; this places a command – just as if a user had clicked the menu option - in the message loop. However, the message will not be processed by the message loop until the VBA code has executed. By that time the VBA code has switched back to run mode, so the command has no effect.  Either adding a DoEvents call immediately after the call to Execute or commenting out the call to Application.RunMode = true at the end of BringToFront or SendToBack avoids this issue, as DoEvents allows the message loop to run.
                                    • As Patrice Thivierge commented, this approach is extremely versatile.  By simply changing the commandbar and control names, you can call any control using this approach.

                                    My PDI is available here as an example file download from the Tech Support website.  It also includes sample subs to loop through commandbars and controls to figure out the appropriate name to call when extending this functionality to other commands.

                                     

                                    Public Sub SendToBack()

                                        'Send to back not available in run mode

                                        Application.RunMode = False

                                       

                                        'Select object(s)

                                        ThisDisplay.SelectedSymbols.RemoveAll

                                        ThisDisplay.Symbols.Item("Rectangle2").Selected = True

                                       

                                        'Send to back

                                        Dim oCmdbar As Object

                                        Set oCmdbar = Application.CommandBars("Display Menu Bar")

                                        oCmdbar.Controls("&Arrange").Controls("&Send To Back").Execute

                                        'Execute method posts a Windows message, which isn't processed before switching back to Run mode.  DoEvents forces the message loop to run

                                        DoEvents

                                       

                                        'Back to run mode

                                        Application.RunMode = True

                                       

                                    End Sub

                                    1 of 1 people found this helpful