Selection.Duplicate returns Nothing

Started by Thomas Winkel, July 13, 2019, 03:58:38 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Thomas Winkel

Hi,

this method should return an selection object:
https://docs.microsoft.com/de-de/office/vba/api/visio.selection.duplicate
But the demo code below returns Nothing.
I would expect a selection of the created shapes.

Any idea?

Best regards,
Thomas



Sub testDuplicate()
    Dim sel As Visio.Selection
    Set sel = ActiveWindow.Selection.Duplicate
    MsgBox sel.Count 'sel = Nothing
End Sub

wapperdude

#1
Well, the code is mostly working.  It does duplicate the selection.  If you view the drawing page and the VBA window, step thru code with <f8>, you see that your selection gets duplicated when the line Set sel = is executed.  The sel.count doesn't work.

Here's link to selection.duplicate:  https://docs.microsoft.com/en-us/office/vba/api/visio.selection.duplicate

Note:  the code line:  Debug.Print ActiveWindow.Selection.Count works either before or after the set  as the former gives count of the original selection and the latter gives count of the duplicated selection. 

Visio 2019 Pro

Thomas Winkel

Hi,

the small testDuplicate sub is only to demonstrate the error.
Regarding to the documentation that you linked the return value of Duplicate() should be a selection.
But actually the method returns Noting.
Even though the duplicate operation itself works.
So I guess that this is a bug in the Visio API.

Using ActiveWindow.Selection after duplicate() can only be a workaround for some cases.

Maybe the following example illustrates the problem better.
You need minimum 2 pages and minimum 1 shape per page.


Sub testDuplicate()
    Dim pge As Visio.Page
    Dim shp As Visio.Shape
    Dim sel As Visio.Selection
    Dim selCopy As Visio.Selection
   
    Set sel = ActivePage.CreateSelection(visSelTypeEmpty)
   
    For Each pge In ActiveDocument.Pages
        If pge <> ActivePage Then Exit For
    Next pge
   
    For Each shp In pge.Shapes
        sel.Select shp, visSelect
        Exit For
    Next shp
   
    Set selCopy = sel.Duplicate
   
    'This will crash because selCopy is Nothing.
    Debug.Print selCopy.Count
End Sub

wapperdude

#3
I interpret it more like <cntl>+ D.  Granted, the "selection" protocol seems to give quantities, but not in this case.

So, in your code, the "set" line actually executes a duplicate command.  It can either be a specified shape or a selection of shapes.  In this case, "selection" is treated like a singular, temporary, physical object.  Whatever it is, is duplicated,  & remains selected. Hence, ActiveWindow.Selection.Count does give quantity of interest.  Just change the code for the debug.print, (or msgbox as you initially used), and you'll get the count and no errors.

Well, the ".duplicate" is what it is. 
Visio 2019 Pro

Thomas Winkel

In my last example the selection contains only one shape from another page, not the ActivePage.
So ActiveWindow.Selection cannot be used.
The Visio.Selection object has nothing to do with the selected items in the Visio drawing window.
The Visio.Shape object also implements a duplicate method. And here the return value is functional.
The following function does what I expect from the Selection.Duplicate() method.
It duplicates a selection and returns the copy as selection object, so that can be processed by further code.


Public Function Duplicate(selection As Visio.selection) As selection
    Dim shp As Visio.Shape
    Dim sel As Visio.selection
   
    Set sel = selection.ContainingPage.CreateSelection(visSelTypeEmpty)
   
    For Each shp In selection
        sel.Select shp.Duplicate, visSelect
    Next shp
   
    Set Duplicate = sel
End Function

Sub testDuplicate()
    Dim sel As Visio.selection
    Set sel = Duplicate(ActiveWindow.selection)
    sel.Group
End Sub

wapperdude

Sorry...failed to recognize that you went to non-active window.  My bad.

Here's an alternative approach to leverage the .duplicate method.  Yes, it requires making the selected page active.  Was lazy, didn't declare everything...


Sub testDuplicate()
    Dim pge As Visio.Page
    Dim shp As Visio.Shape
    Dim sel As Visio.Selection
    Dim selCopy As Visio.Selection
   
    For Each pge In ActiveDocument.Pages
        If pge <> ActivePage Then Exit For
    Next pge
   
    Set sel = pge.CreateSelection(visSelTypeAll)   'again lazy, didn't try to filter the selected shapes.
    Debug.Print sel.Count
    ActiveWindow.Page = pge     'this needs to be before the sel.Duplicate line, otherwise, Visio will "forget" what's selected upon page change.  This could be a bug.
   
    Set selCopy = sel.Duplicate     'Visio remembers what was duplicated, but, window needs to be active for this to be useful.
    Set vsoSel = ActiveWindow.Selection 
    Debug.Print vsoSel.Count
   
End Sub

Hope this is helpful.

Visio 2019 Pro