Smarter Paste between Pages


The Visio Product Team uses Visio for a number of tasks.  A common task is creating storyboards to show how a user might construct a diagram.  If you’ve ever seen one of those “behind the scenes” documentaries for a movie, you’ve seen the storyboarding process.  Each step the user takes is captured on a separate page in a Visio drawing.  Then the entire document is shown as a presentation to replay the construction of the diagram.


It seems that quite a few people use Visio for this sort of task.  Visio is a pretty good tool for mocking up application or web interfaces.  One common request is to make copying between pages work better.  In these types of documents, each page is almost identical to the one before it.  One of the nicer touches in PowerPoint is that objects copied from one page (slide) to another are pasted in exactly the same position.  In Visio objects are pasted to the center of the screen making repositioning a chore.  Visio needs a smarter paste behavior.


A little bit of code can solve the problem for Visio.  Actually, there are two ways to solve the problem.  You could write your own procedures to perform copy and paste with better logic for positioning.  Alternatively, you could handle the event notifications from Visio when copy and paste occur and fix up the positioning after the fact.  The attached Visio document has VBA code to illustrate both methods.


Create your own copy / paste commands


When invoking Visio’s Copy and Paste command through automation, Visio allows you to specify whether the position of the selection on the page should be preserved using the visCopyPasteNoTranslate flag.  Thus you can create your own macros that do copy and paste:


Public Sub CopyNoTranslate()


   


    Application.ActiveWindow.Selection.Copy (visCopyPasteNoTranslate)


 


End Sub


 


Public Sub PasteNoTranslate()


   


    Application.ActivePage.Paste (visCopyPasteNoTranslate)


 


End Sub


In fact you can assign Ctrl-C and Ctrl-V as the accelerator keys for these macros to override Visio’s copy / paste.  If the real goal is to support copying to a new page, this macro will perform the necessary steps:


Public Sub CopyToNewPage()


   


    Dim vsoSelection As Visio.Selection


   


    'Make sure we are in a drawing window


    If Application.ActiveWindow.Type = Visio.VisWinTypes.visDrawing Then


   


        'If there is no selection, select all shapes on the page


        Set vsoSelection = Application.ActiveWindow.Selection


        vsoSelection.IterationMode = 0


        If vsoSelection.Count = 0 Then


            vsoSelection.SelectAll


        End If


       


        'Copy selection to new page


        vsoSelection.Copy Visio.visCopyPasteNoTranslate


        Application.ActiveDocument.Pages.Add


        Application.ActivePage.Paste Visio.visCopyPasteNoTranslate


       


    End If


   


End Sub


Respond to Visio’s copy / paste events


This method uses an event handler to detect copy and paste actions.  The position of the selection is read during the copy action.  The new position of the selection (which will be placed in the center of the window) is read during the paste action.  The current page is recorded during each action as well.  If the copy and paste actions occur on different pages, the code moves the selection back to its previous coordinates following the paste action.


Private Sub vsoApp_EnterScope(ByVal app As IVApplication, ByVal nScopeID As Long, ByVal bstrDescription As String)


 


    'Check for Copy action in a drawing window


    If nScopeID = 1021 And app.ActiveWindow.Type = Visio.VisWinTypes.visDrawing Then


   


        Dim vsoSelection As Visio.Selection


        Set vsoSelection = app.ActiveWindow.Selection


       


        If vsoSelection.Count > 0 Then


       


            'Find the shape in the selection at the bottom of the z-order


            Dim bottomShape As Integer


            bottomShape = GetBottomShape(vsoSelection)


           


            'Record scope ID and selection information


            nCopyScopeID = nScopeID


            gCopyPageID = app.ActivePage.PageSheet.UniqueID(Visio.visGetOrMakeGUID)


            dShapePosX = vsoSelection(bottomShape).CellsU("PinX").ResultIU


            dShapePosY = vsoSelection(bottomShape).CellsU("PinY").ResultIU


           


        End If


   


    End If


   


End Sub


 


Private Sub vsoApp_ExitScope(ByVal app As IVApplication, ByVal nScopeID As Long, ByVal bstrDescription As String, ByVal bErrOrCancelled As Boolean)


 


    'Check for Paste action in a drawing window


    If nScopeID = 1022 And app.ActiveWindow.Type = Visio.VisWinTypes.visDrawing Then


   


        If nCopyScopeID <> 0 Then


       


            Dim vsoSelection As Visio.Selection


            Set vsoSelection = app.ActiveWindow.Selection


           


            Dim activePageID As String


            activePageID = app.ActivePage.PageSheet.UniqueID(Visio.visGetOrMakeGUID)


           


            If vsoSelection.Count > 0 And gCopyPageID <> activePageID Then


           


                'Find the shape in the selection at the bottom of the z-order


                Dim bottomShape As Integer


                bottomShape = GetBottomShape(vsoSelection)


           


                'Fix up position of selection by offsetting from the bottom shape


                Dim posX As Double, posY As Double


                posX = vsoSelection(bottomShape).CellsU("PinX").ResultIU


                posY = vsoSelection(bottomShape).CellsU("PinY").ResultIU


               


                vsoSelection.Move dShapePosX - posX, dShapePosY - posY


               


            End If


       


        End If


       


    End If


       


End Sub


The full code for this method is found in the attached document.  We use the EnterScope and ExitScope events to detect the copy and paste actions.  The key problem to solve is recording the current position of the selected shapes.  Visio selections do not have coordinates associated with them, so the coordinates of one of the shapes within the selection must be used.  The trick is to make sure that the same shape is scanned in both the copy and paste actions.  Visio does not necessarily preserve the order of shapes in the selection during paste.  This code finds the bottommost shape in the z-order (layering order) to ensure that the same shape is scanned each time.


To use this method, open the SmartPaste.vsd file in Visio along with the other documents you are working on.  Once you enable macros for the file, SmartPaste will work with your regular Copy  and Paste actions.



If you find this type of behavior useful or find it counter-productive, please let us know.

SmartPaste.vsd