Visio Guy

Visio Discussions => General Visio => Topic started by: kevsor1 on February 26, 2013, 01:10:04 PM

Title: Sort the "Assign to Layer" list
Post by: kevsor1 on February 26, 2013, 01:10:04 PM
Hi Experts,

I've got a very complex visio with lots of layers and VBA code that manipulates when certain layers are shown. 

The problem is that as I continue adding objects and layers to my diagrams, when I want to assign layers to a new object, it's becoming very time-consuming to find the right layer in the "Assign to Layer..." dialogue box because they're not sorted in any intelligible manner (I think it uses creation order, which is a mess in my case).   :( 

Is there a way to alphabetize the list of layers in the "Assign to Layer..." dialogue box (without deleting the layers and adding them in alphabetical order)?

Thanks,
Kevin
Title: Re: Sort the "Assign to Layer" list
Post by: Compy on May 04, 2022, 12:46:22 PM
Hi Experts,

I've got a very complex visio with lots of layers and VBA code that manipulates when certain layers are shown. 

The problem is that as I continue adding objects and layers to my diagrams, when I want to assign layers to a new object, it's becoming very time-consuming to find the right layer in the "Assign to Layer..." dialogue box because they're not sorted in any intelligible manner (I think it uses creation order, which is a mess in my case).   :( 

Is there a way to alphabetize the list of layers in the "Assign to Layer..." dialogue box (without deleting the layers and adding them in alphabetical order)?

Thanks,
Kevin
Given the date and lack of an answer to this question do I assume that its not possible?
Title: Re: Sort the "Assign to Layer" list
Post by: Paul Herber on May 04, 2022, 03:45:09 PM
The layer index property is read-only so that suggests it's not possible to re-order them.
Title: Re: Sort the "Assign to Layer" list
Post by: Yacine on May 05, 2022, 01:09:02 AM
You can write your own VBA form in which you can populate a sorted listbox with the layers of the page.
Title: Re: Sort the "Assign to Layer" list
Post by: Mouthpear on May 06, 2022, 06:44:29 AM
You can write your own VBA form in which you can populate a sorted listbox with the layers of the page.

How would you write that code? Example?
Title: Re: Sort the "Assign to Layer" list
Post by: wapperdude on May 06, 2022, 09:03:10 AM
Ohhhh. 🤔😥

That seems like a lot of work...
  1) setting up the form to have all the correct columns
  2) Adding Check boxes for each line item
  3) enabling individual check box selection / deselection, plus select / deselect all
  4) allowing code to build / populate the list (each time code is run ???) for the active page, and then bring up the list
  5) easy part is making the form non-modal

Granted, writing code only needs to be done once.  But not a trivial task.
Title: Re: Sort the "Assign to Layer" list
Post by: Nikolay on May 06, 2022, 11:23:40 AM
BTW, there is already a good tool by David Parker / bVisual:
https://bvisual.net/products/layermanager/
Title: Re: Sort the "Assign to Layer" list
Post by: Paul Herber on May 06, 2022, 11:28:39 AM
I had better withdraw my offer then.
Title: Re: Sort the "Assign to Layer" list
Post by: Nikolay on May 06, 2022, 11:32:21 AM
I have also built one a while ago, but it turned to be of little use to me (basically was to test my printer (https://www.youtube.com/watch?v=p_OGQtzpPBU) test the sciter library (https://sciter.com/))  ;D
https://github.com/nbelyh/LayerHelper
Title: Re: Sort the "Assign to Layer" list
Post by: wapperdude on May 06, 2022, 01:50:42 PM
The development by David Parker looks to be outstanding.  Not cheap, but looks to be well conceived and implemented.  He's elevated the whole Visio layers scheme to a new level.
Title: Re: Sort the "Assign to Layer" list
Post by: Mouthpear on May 06, 2022, 07:13:35 PM
BTW, there is already a good tool by David Parker / bVisual:
https://bvisual.net/products/layermanager/

Looks like all those buttons for layers in his add-in take up too much space. More important, this does not even do the one thing the OP is looking for. HOW TO REORDER THE LAYERS so that they are in alphabetical order.
Title: Re: Sort the "Assign to Layer" list
Post by: Compy on May 07, 2022, 03:10:41 AM
Thanks to all who have contributed.
I have tried the bvisual tool and cannot see a sort for the list in here. Please correct me if I am wrong.
I am not a VBA programmer, so the VBA option for me becomes even more involved than suggested.  - Point 0 added to the list, Learn VBA. Although this may be interesting it is not really the objective!
Paul, what was or is the offer you have withdrawn?
Thanks
Title: Re: Sort the "Assign to Layer" list
Post by: wapperdude on May 08, 2022, 01:51:23 PM
Actually, when you bring up the layers dialog box, if you click the "NAME" header, it will sort the list
Title: Re: Sort the "Assign to Layer" list
Post by: wapperdude on May 08, 2022, 05:59:19 PM
Some observations that are rarely mentioned wrt layers:
1) The order that the layers are presented in the Assign to Layers list is the order found in the Layers Section of the page shapesheet.  So, if there's a VBA (or whatever snake oil you prefer), that does alphbetizing, this is where it would need to happen.

2)  Layers do not have a hierarchical structure.  That is, you cannot great a group dediccated to, say, plumbing or electrical.  While I haven't explored it, David Parkers development may do that.  That could simplify layer selection on a functional basis.

3) A quasi-ordering can be acchived via a more rigorous/elaborate layer naming convention.  To wit, electrical switches might be:
  > Elec.sw.spst
  > Elec.sw.dpdt
  > Elect.sw.mon.no  (electrical, switches, momentary, normally open)

From what I can tell, such indulged names are permissible.
Title: Re: Sort the "Assign to Layer" list
Post by: wapperdude on May 08, 2022, 08:47:01 PM
After realizing that the alphabetizing of the Assign to Layers was merely a matter of re-ordering the rows in the Layers section of the Page shapesheet, I reworked an online piece of code to solve the problem at hand.

@Paul Herber:  code ready for your Utilities  ;)
Here's the code:
Code
Sub Bubble_SortArray()
'Alphabetize order of layers
'An approach that eliminates need to open Page shapesheet

    Dim tmpStr As String
    Dim pgLyrs As Visio.Layers
    Dim arrLyrs() As Variant
    Dim RCnt As Long
    Dim i As Long
   
    Dim vShp As Visio.Shape
    Dim vShps As Visio.Shapes
    Dim actPg As Visio.Page
   
'Initializations
    Set actPg = ActivePage
    Set vShps = actPg.Shapes
    Set vShp = vShps("ThePage")
   
    Set pgLyrs = actPg.Layers
    RCnt = pgLyrs.Count
    ReDim arrLyrs(RCnt - 1)
    i = LBound(arrLyrs)
   
'Fetch all the layer names & store in array
    For Each pgLyr In pgLyrs
        arrLyrs(i) = pgLyr.Name
        i = i + 1
    Next

'Alphabetize Sheet Names in Array List
    For i = LBound(arrLyrs) To UBound(arrLyrs)
        For j = i To UBound(arrLyrs)
            If UCase(arrLyrs(j)) < UCase(arrLyrs(i)) Then
                tmpStr = arrLyrs(i)
                arrLyrs(i) = arrLyrs(j)
                arrLyrs(j) = tmpStr
            End If
        Next j
    Next i
   
'Transfer corrected sequence to the page shapesheet
    For i = LBound(arrLyrs) To UBound(arrLyrs)
        vShp.CellsSRC(visSectionLayer, i, visLayerName).FormulaU = Chr(34) + arrLyrs(i) + Chr(34)
    Next
   
End Sub
Title: Re: Sort the "Assign to Layer" list
Post by: wapperdude on May 16, 2022, 07:29:46 PM
YIKES :o >:( :-[

Paul Herber spotted a problem.  Sorting the names does not include moving the various properties with them.  That is definitely bad!!!  So, each original row needs to be placed in an array, wuch that property values track with layer name.  Then after sorting, both the layer name and its properties and entered back into the shapesheet.

Ah.  Close but no cigar!
Title: Re: Sort the "Assign to Layer" list
Post by: Surrogate on May 17, 2022, 02:01:44 AM
Then after sorting, both the layer name and its properties and entered back into the shapesheet.
IMHO it is impossible ! In the ShapeSheet, layers are sorted as they are added to the sheet. We can't re-order this list !
Title: Re: Sort the "Assign to Layer" list
Post by: wapperdude on May 17, 2022, 09:17:34 AM
I'd say, nearly impossible. 

Besides the issue that Paul observed, there is one more issue.  For each shape, the list of assigned layers is based upon layer position, not layer name.  So, ialphabetizing the names changes the layer that they represent.  That is, if originally, 4th layer, had name "A", but after sorting, "A" is first layer, i.e. layer "0".  A new shape, assigned to "A" is actually point to a different layer than a previously assigned shape with layer A.  So, if previous shape, layer "A" would show up as "3" in its shapesheet, but in a new shape, after sorting, layer "A" would be listed as "0".  This is a total mess!!! 

Not only do you have to move the layer properties with the layer names, but you must, additionally, unassign and re-assign  the layers for each shape.  Thus, this become a much more involved task.  But, not impossible.  Unfortunate. 
Title: Re: Sort the "Assign to Layer" list
Post by: Surrogate on May 17, 2022, 09:42:55 AM
Not only do you have to move the layer properties with the layer names, but you must, additionally, unassign and re-assign  the layers for each shape.  Thus, this become a much more involved task.  But, not impossible.
+1 !
Another point that complicates things a bit.
The layer numbers in the Page's PageSheet start with 1.
And for the shapes in the LayerMembership cell, the layer numbers start with 0.
Title: Re: Sort the "Assign to Layer" list
Post by: Paul Herber on May 17, 2022, 10:11:08 AM
 ... and any other formulae that refers to the layers cells, could even be on other pages, unlikely but possible.
Title: Re: Sort the "Assign to Layer" list
Post by: Yacine on May 17, 2022, 11:58:23 PM
If I understood the original post correctly, the poster is complaining about not having the layers in alphabetical order when assigning layers to the shapes.
There is no request for ordering the layer structure itself.
A simple assigning form with Wapperdude's sorted list should suffice for the task.


I'm myself busy on another project, but any other "helper" or the poster himself can set this up very easily.
Title: Re: Sort the "Assign to Layer" list
Post by: wapperdude on May 18, 2022, 10:38:26 AM
@Yacine:  Strictly speaking, you're correct.  But, to change the order of names only has some issues.  As this was done via the page's shapesheet, the technique doesn't cause the layer properties to track with the name.  Plus, it doesn't change the delineated list of layer row assignments within a shape's shapesheet.  That means there are multiple places of erroneous, confusing info.

For what it doesn't do,  I do not recommend using this macro. 
Title: Re: Sort the "Assign to Layer" list
Post by: Yacine on May 19, 2022, 05:19:42 AM
Hi Wayne,
I did not explain myself properly and I saw it in your code.
You were trying to order the layers themselves. With the possible advantage of re-using the original layers dialog. Difficult ... for many reasons.
What I am saying, is that it is absolutely legit to use an auxiliary form which displays the layers in alphabetical order.
The assignment would however not be the name but the index of this layer, stored in a second column of the list.


I modified your code a little bit, in so far as it does not modify the layers, but returns a sorted array of tuples (layer name, layer index). I then use this array to populate a list.
The list will have the layer name as first column and the index as a second one. The bound column will be the second as to return only the index.

Code of helper routine:
Code
Option Explicit

Sub showForm()
    formAssignToLayer.Show
End Sub

Sub createLayers()
    Dim lyr As Layer
    Dim pg As Page
    Dim i As Integer
    Dim j As Integer
    Dim t As String
   
    Set pg = ActivePage
   
    For i = 1 To 100
        t = ""
        Do
            t = t & Chr(65 + Int(Rnd * 26))
        Loop Until Rnd > 0.9
        pg.Layers.Add t
    Next i
End Sub


Sub deleteAllLayers()
    Dim lyr As Layer
    Dim pg As Page
    Dim i As Integer
   
    Set pg = ActivePage
    pg.PageSheet.DeleteSection visSectionLayer
End Sub


Function Bubble_SortArray() As Variant
'Alphabetize order of layers '
'An approach that eliminates need to open Page shapesheet '


    Dim tmpStr As String
    Dim pgLyrs As Visio.Layers
    Dim pgLyr As Layer
    Dim arrLyrs() As Variant
    Dim RCnt As Long
    Dim i As Long, j As Long
   
    Dim vShp As Visio.Shape
    Dim vShps As Visio.Shapes
    Dim actPg As Visio.Page
   
'Initializations '
    Set actPg = ActivePage
    Set vShps = actPg.Shapes
    Set vShp = vShps("ThePage")
   
    Set pgLyrs = actPg.Layers
    RCnt = pgLyrs.Count
    If RCnt = 0 Then
        Exit Function
    End If
    ReDim arrLyrs(RCnt - 1)
    i = LBound(arrLyrs)
   
'Fetch all the layer names & store in array '
    For Each pgLyr In pgLyrs
        arrLyrs(i) = pgLyr.Name & "|" & pgLyr.Index
        i = i + 1
    Next


'Alphabetize Sheet Names in Array List '
    For i = LBound(arrLyrs) To UBound(arrLyrs)
        For j = i To UBound(arrLyrs)
            If UCase(arrLyrs(j)) < UCase(arrLyrs(i)) Then
                tmpStr = arrLyrs(i)
                arrLyrs(i) = arrLyrs(j)
                arrLyrs(j) = tmpStr
            End If
        Next j
    Next i
   
'Transfer corrected sequence to the page shapesheet '
    Bubble_SortArray = arrLyrs
End Function


Sub testBubbleSortArray()
    Dim arLyrs As Variant
    Dim lyr As Variant
    Dim v As Variant
    Dim t1 As String, t2 As String
    Dim lyr_num As Integer
   
    arLyrs = Bubble_SortArray
    If IsEmpty(arLyrs) Then
        Exit Sub
    End If
    For Each lyr In arLyrs
        v = Split(lyr, "|")
        t1 = v(0)
        t2 = v(1)
        Debug.Print t1, t2
    Next lyr
End Sub

That's it. Now assign this number to the selection's membership and you're done.

Code of the form:
Code
Option Explicit

Public currentLyr As Layer

Sub populateLayersList()

    Dim arLyrs As Variant
    Dim lyr As Variant
    Dim v As Variant
    Dim t1 As String, t2 As String
    Dim lyr_num As Integer
   
    listLyrs.Clear
   
    arLyrs = Bubble_SortArray
    If IsEmpty(arLyrs) Then
        Exit Sub
    End If
    For Each lyr In arLyrs
        v = Split(lyr, "|")
        t1 = v(0)
        t2 = v(1)
        listLyrs.AddItem
        listLyrs.List(listLyrs.ListCount - 1, 0) = t1
        listLyrs.List(listLyrs.ListCount - 1, 1) = t2
    Next lyr
End Sub

Private Sub cmAssign_Click()
    Dim shp As Shape
    Dim lyr_num As Integer
   
    lyr_num = listLyrs.Value - 1
    Debug.Print lyr_num
    For Each shp In ActiveWindow.Selection
        shp.CellsSRC(visSectionObject, visRowLayerMem, visLayerMember).FormulaForceU = Chr(34) & Str(lyr_num) & Chr(34)
    Next shp
End Sub

Private Sub cmUpdate_Click()
    populateLayersList
End Sub


Private Sub listLyrs_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
    Set currentLyr = ActivePage.Layers.Item(Int(listLyrs.Value))
    Debug.Print currentLyr.Name, currentLyr.Index
    formEditLayer.Show
    formEditLayer.refresh
End Sub

Private Sub UserForm_Initialize()
    populateLayersList
End Sub



I was procrastinating enough ;) to find the time to add a form for editing a layer's properties. But it is only a stub.


P.S.: You may argument that the sorting is not perfect. I sort over "name"|"index", which may result in slightly disrupted sort orders. Fine enough for the purpose of this post.
An optimized sorting would require a sorting over the names only and the subsequent addition of the index. ... an aesthetical problem.
Title: Re: Sort the "Assign to Layer" list
Post by: wapperdude on May 19, 2022, 09:15:52 AM
@Yacine:  Got it.  Nice.  My bad...you did mention early on of creating a separate form.  I forgot.