Site icon bVisual

Automating Page.DropLegend in Visio 2010

Visio 2007 introduced Data Graphics but, in my opinion, didn’t provide any automatic legends for the icons and colour by value options. That is why I wrote DataLegends (see http://www.bvisual.net/Products/DataLegends.aspx ) as an add-in for Visio 2007 several years ago. This oversight was remedied in Visio 2010 when Microsoft introduced their own legends (which were not totally dissimilar to my own), and also added a method (Page.DropLegend) for programmers to automate this task.

Visio also has VBA built-in, and you can record actions with it too, so I recorded dropping a Vertical legend into my page, and here is the recorded macro:

Public Sub AddLegend()

    'Enable diagram services
    Dim DiagramServices As Integer
    DiagramServices = ActiveDocument.DiagramServicesEnabled
    ActiveDocument.DiagramServicesEnabled = visServiceVersion140

    Dim vsoDoc1 As Visio.Document
    Set vsoDoc1 = Application.Documents.OpenEx(Application.GetBuiltInStencilFile(visBuiltInStencilLegends, visMSMetric), visOpenHidden)
    ActivePage.DropLegend vsoDoc1.Masters.ItemU("Outer list"), vsoDoc1.Masters.ItemU("Field container"), visLegendPopulate
    
    vsoDoc1.Close

    'Restore diagram services
    ActiveDocument.DiagramServicesEnabled = DiagramServices

End Sub

So, then I deleted the legend that I had just dropped, and ran the macro. It dropped a horizontal legend … not quite what I wanted. So, I recorded dropping a horizontal legend too see if there was any difference … nope, just the same. So, the macro would be great if I always wanted a horizontal legend, but almost useless if I want a vertical one.

I examined the ShapeSheet of the containers for each orientation of the legend, and found that User.msvSDListDirection is 2 for vertical, and 1 for horizontal. However, just changing the value of after the legend has been created is no good because it has already been populated.

I tried using the Event Monitor from the Visio SDK to see if there was any additional parameters being passed from the ribbon, but I could not spot one, so I needed a different strategy. Closer examination of the VBA code shows that a built-in stencil is opened hidden, then two masters are used, “Outer list” and “Field container”, before the stencil is closed. Sure enough, those two masters now exist in my local document stencil, so I could modify them, and the code.

I edited the Outer list master and put the formula =GUARD(2) in the User.msvSDListDirection value cell, and then I ensured that the Match master by name on drop Behavior property was ticked. In fact, I did this for Field container, Inner list, CBV item, Icon item and Text item too. This tells Visio to use these named masters rather than add new versions in the future. The GUARD(..) function is required because it prevents the DropLegend action from forcing a 1 value into the cell.

I then amended the macro so it used the local copy of the masters in the DropLegend action :

Public Sub AddLegend()

    'Enable diagram services
    Dim DiagramServices As Integer
    DiagramServices = ActiveDocument.DiagramServicesEnabled
    ActiveDocument.DiagramServicesEnabled = visServiceVersion140

    ActivePage.DropLegend ActiveDocument.Masters.ItemU("Outer list"), ActiveDocument.Masters.ItemU("Field container"), visLegendPopulate
    
    'Restore diagram services
    ActiveDocument.DiagramServicesEnabled = DiagramServices

End Sub

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

I now have a macro that drops me a vertical legend as required. QED.

Exit mobile version