Creating a Custom Org Chart Template with Extra Properties

A Visio user recently asked how to add a salary amount for an Org Chart person automatically, based on their selected Level. I thought it was a bit long to answer in the forum, so I have written my answer below. It demonstrates how you can have your own custom template that works with the Organization Chart add-on in Visio.

My approach to creating a custom template that still uses the Organization Chart Add-On is to create a new drawing from the built-in template, and then to add extra properties to it.

First, select Show Document Stencil to view all of the local copies of the built-in master shapes. If they are not there, then simply drag and drop them from the built-in stencil on to the first page, and then delete the shapes on the page. This will not delete the local copies of the masters.

image

You should check that the Match master by name on drop property is ticked for each master in the Document Stencil, otherwise the Org Chart Add-On may decide to use the original Organization Chart Shapes stencil master with the same name.

image

Open the ShapeSheet of the Document by using the Show ShapeSheet drop-down menu on the Developer tab.

image

Add two extra rows to the User-defined Cells section called LevelList and SalaryList, with the Value formulas:

=”Exec;Sr;Assoc;Jr;Vacant”

and

=”70000;50000;35000;30000;0″

Note that the salaries are entered as numbers without the currency symbol.

image

Now, each of the relevant master shapes need to be updated with the new properties.

So, open up the Executive master shape in edit mode, and add two new Shape Data rows (Level and Salary), and then one new User-defined cell (SalaryTrigger):

image

The Prop.Level Shape Data row has type formula =GUARD(1) because it is a fixed list, the Format formula is =TheDoc!User.LevelList , and the Value formula was created by selecting Vacant from the Shape Data window.

The Prop.Salary Shape Data row has type formula =GUARD(7) because it is a currency, and the Value formula will be created by selecting any Level value from the Shape Data window.

The SalaryTrigger User-defined cell Value formula is:

=SETF(GetRef(Prop.Salary),”=INDEX(LOOKUP(Prop.Level,Prop.Level.Format),TheDoc!User.SalaryList)”)

This will update the value of the Salary cell when a new Level is selected, and, moreover, the value will change if you update the User.SalaryList values in the Document ShapeSheet.

The above trigger formula will allow for local editing of the salary on individual shapes, but if you want to make the salary read-only then insert the GUARD() function as below:

=SETF(GetRef(Prop.Salary),”=GUARD(INDEX(LOOKUP(Prop.Level,Prop.Level.Format),TheDoc!User.SalaryList)))”

Now, you can save your Executive master, and it will have the updated functionality. However, there are seven almost identical masters for Position Type in the Organization Chart stencil, and each of these need to be updated identically!

image

Now, you can manually make all of the changes to the other six Position Type masters (Manager, Position, Consultant, Vacancy, Assistant, and Staff) , or you could use the VBA code below to make the changes for you (note that this has been updated from my original post):

Option Explicit

Public Sub UpdatePositionTypeMastersFromExcecutive()
Dim mstExec As Visio.Master
Dim mst As Visio.Master
Dim mstCopy As Visio.Master
Dim shpExec As Visio.Shape
Dim shpCopy As Visio.Shape
'Get the Executive master
For Each mst In ActiveDocument.Masters
    If mst.Name = "Executive" Then
        Set mstExec = mst
        Set shpExec = mstExec.Shapes(1)
        Exit For
    End If
Next mst
'Abort if not found
If mstExec Is Nothing Then Exit Sub

Dim iRow As Integer
Dim iColumn As Integer

'Loop through each master
'and filter to include those with the Prop.Name Shape Data row
For Each mst In ActiveDocument.Masters
    If Not mst.Name = "Executive" _
        And mst.Shapes(1).CellExists("Prop.Name", Visio.visExistsAnywhere) Then
        Debug.Print "Updating " & mst.Name
        Set mstCopy = mst.Open  'Open the master for editing
        Set shpCopy = mstCopy.Shapes(1) 'Get the group shape
        'Loop through Shape Data rows to find extra ones
        For iRow = 0 To shpExec.RowCount(visSectionProp) - 1
            If shpCopy.CellsSRCExists(visSectionProp, iRow, 0, visExistsAnywhere) = 0 Then
                'Add the row
                Debug.Print , "Adding " & shpExec.CellsSRC(visSectionProp, iRow, 0).rowName
                shpCopy.AddNamedRow visSectionProp, shpExec.CellsSRC(visSectionProp, iRow, 0).rowName, 0
                For iColumn = 0 To shpExec.RowsCellCount(visSectionProp, iRow) - 1
                    If Len(shpExec.CellsSRC(visSectionProp, iRow, iColumn).Formula) > 2 Then
                        'Add the formulas
                        Debug.Print , , iColumn, shpExec.CellsSRC(visSectionProp, iRow, iColumn).Formula
                        shpCopy.CellsSRC(visSectionProp, iRow, iColumn).FormulaU = _
                            shpExec.CellsSRC(visSectionProp, iRow, iColumn).FormulaU
                    End If
                Next iColumn
            End If
        Next

        'Loop through User-defined cells rows to find extra ones
Dim rowName As String
Dim newRow As Integer
        For iRow = 0 To shpExec.RowCount(visSectionUser) - 1
            rowName = shpExec.CellsSRC(visSectionUser, iRow, 0).rowName
            If shpCopy.CellExists("User." & rowName, visExistsAnywhere) = 0 Then
                'Add the row
                Debug.Print , "Adding " & shpExec.CellsSRC(visSectionUser, iRow, 0).rowName
                newRow = shpCopy.AddNamedRow(visSectionUser, shpExec.CellsSRC(visSectionUser, iRow, 0).rowName, 0)
                For iColumn = 0 To shpExec.RowsCellCount(visSectionUser, iRow) - 1
                    If Len(shpExec.CellsSRC(visSectionUser, iRow, iColumn).Formula) > 2 Then
                    'Add the formulas
                        Debug.Print , , iColumn, shpExec.CellsSRC(visSectionUser, iRow, iColumn).Formula
                        shpCopy.CellsSRC(visSectionUser, newRow, iColumn).FormulaU = _
                            shpExec.CellsSRC(visSectionUser, iRow, iColumn).FormulaU
                    End If
                Next iColumn
            End If
        Next
        mstCopy.Close

    End If
Next mst

End Sub

All you need to do now is save your drawing as a Visio template, and you are ready to create Organization Charts from your new template!

Addendum (how to write a report to total the Salary by Level):

If you copying the XML below into a file called TotalSalaryCost.vrd (for example) using Notepad, then run Shape Reports, and then browse for the file, andRun as a Visio Shape …. you should get an embedded Excel worksheet that sums up the salary cost for each level, and get an overall total :-) :

<?xml version="1.0" encoding="utf-8"?> 
<VisioReportDefinition xmlns="urn:schemas-microsoft-com:office:visio:reportdefinition" ReportExists="1" SelectDrawingDataMethod="1" 
Description="" Precision="0" ShowUnits="1" CaseSensitive="0" UserCells="0" HiddenProperties="0" AdvancedFilter="0" FilterExpression="" Version="3">
<Name>Total Salary Cost</Name>
<Title>TotalCost</Title>
<VisioRptDefField ID="1" Display="1" DisplayOrder="1" Type="0" SummaryTypes="1" Tag="2">
<Name>Level</Name>
<DisplayName>Level</DisplayName>
</VisioRptDefField>
<VisioRptDefField ID="2" Display="1" DisplayOrder="2" Type="7" SummaryTypes="2" Tag="2">
<Name>Salary</Name>
<DisplayName>Salary</DisplayName>
</VisioRptDefField>
<VisioRptDefGroup ID="0" GroupingField="1" ItemDisplay="1" GrandSummary="1" ExcludeDuplicates="0"/>
</VisioReportDefinition>

Visio Date Format Pictures Affect Data Entry via the Calendar Popup

I have been creating roadmaps in Visio lately, and the client is only concerned with the months and years, so I thought it would be sensible to use a Date Format Picture to display only the month and year in the Shape Data window. What I did not expect is that the mere existence of this Date Format Picture would alter the actual date stored in the cell. In this blog, I layout my concerns about the Calendar popup that is provided for Date type Shape Data rows.

In the following example, I have created a shape, coloured pale orange below, and added 25 Date type Shape Data rows. I have not applied any format to Property1, but then I have applied each of the 17 suggested Date Format Patterns provided on a drop-down list in the Define Shape Data dialog. Finally, I added a further 7 patterns manually. I then selected Today as the value for every single Shape Data row:

image

When I examined the ShapeSheet for the Shape Data rows, I noticed that values for Property11 and Property12 were both storing 12th April 2012, even though Today is 26th April 2012, and the Property15, 16, 17 and 18 all store the minimum DATETIME value, which is 3oth December 1899. The extra 7 custom formats all stored a different Date value to the selected Today date.

image

I then inserted the value of Property1 (Prop.Row_1) 25 times, and applied the same Date Format Patterns that I had applied to each of the Shape Data rows.

image

So, the Date Format Picture applied to the Shape Data row does modify the data stored, when the Calendar popup is used (dates entered manually via the keyboard are not modified). But why and how? Each of the values are stored with the DATETIME(n) function, where n is the number of days since 30th Dec 1899.

Firstly, it is worth noting that the current Calendar control does not provide a Time selector, thus it can only be used to select dates …. even though the data type is DateTime!

The following is an extract from the Visio 2010 SDK for the DATTIME function:

Syntax

DATETIME(“datetime“|expression[,lcid])

Parameters

Name Required/Optional
Data Type Description
datetime Required String Any string commonly recognized as a date and time or a reference to a cell containing a date and time.
expression Required String Any expression that yields a date and time.
lcid Optional Number Specifies the locale identifier to be used in evaluating a non-local datetime. The locale identifier is a number described in the system header files.

Return Value
Datetime

Remarks

If datetime is missing or cannot be interpreted as a valid date or time, DATETIME returns a #VALUE! error.

The returned value is formatted according to the short date style and time style in the system’s current Regional Settings.

The DATETIME function also accepts a single number value for expression where the integer portion of the result represents the number of days since December 30, 1899, and the decimal portion represents the fraction of a day since midnight.

 

I created some User-defined cells to apply some formulas, by entering the stored values in the first 4 rows, and then testing the effect of 4 significant digits after the decimal point, in the last 4 rows :

image

When I looked at the values, I actually had an error for the User.Row_4.Prompt until I added the INT() function.

image

My conclusion is that using the popup Calendar control in a Date type Shape Data row will apply the Date Format Picture before storing the value in the cell, thus modifying the value in some instances!

Unfortunately, I do not know anyway to prevent the Calendar control from being available, or replacing the default control with a better one, without creating your own custom control.

There are nicer Date and Time controls available in WPF, for example, so I use them where possible, but users can still find the Shape Data window….

For more information, see About Format Pictures (http://office.microsoft.com/en-us/visio-help/HV080400010.aspx)

How to have six icons in a Visio Data Graphic Icon Set

I was recently asked to represent the values of Key Performance Indicators (KPIs) in Visio. Great, I thought, this is just what Visio’s Data Graphic Icon Sets are for! Only trouble was, that there were six possible values for the KPI, but all the example Icon Sets have a maximum of five icons in them. So, I had to come up with a way of displaying six icons …

In the following example, I have defined a Shape Data row with a Fixed List type that can have a value from the list “3;2;1;-1;-2;-3

image

I applied the Faces Icon Set, and set icons for each value, except for –1:

image

Consequently, when I dropped six shapes, each with one of the possible values, then there is no icon shown for the –1 value:

image

So, I explored the Faces icon set to see if I could display an icon if the value does not match one of the assigned matched values in the icon set. (Note that the sixth icon will not be for the value –1 specifically, but for any value that is not matched already).

First of all, I opened the Drawing Explorer (from the Developer tab when in Developer Mode), and ticked the Match master by name on drop property. This ensures that Visio will not attempt to use the original Faces icon set master (provided that any changes are not too drastic).:

image

I then selected Edit Master Shape, and viewed the ShapeSheet of the main group shape, Sheet.5 :

image

Notice that the Geometry1.NoShow and the HideText cells have the formula

=IF(User.msvCalloutIconNumber=-1,TRUE,FALSE)

I opened the ShapeSheet of the sub-shape, Sheet.78, and noticed that there are many Geometry sections, each of which have their NoShow formula linked to the value 0 to 4 for the User.msvCalloutIconNumber cell, which references the User.msvCalloutIconNumber cell in the parent group shape.

image

Therefore, all that is needed is to amend the formulas to display geometry if there is no matched value.

So, I manually edited the value of the User.msvCalloutIconNumber  in Sheet.5 to –1. This switched off the display of all graphics:

image

I then changed the formula in the NoShow cell of Geometry sections 7, 12 and 13 from:

=IF(User.visCalloutIconNumber=2,FALSE,TRUE)

to:

=IF(LOOKUP(User.visCalloutIconNumber,”0;1;3;4″)>-1,TRUE,FALSE)

This gave me two eyes and a mouth:

image

I decided to give the mouth a slant in order to distinguish it from the case when the value = 2. So, I changed the formula for the Geometry7.Y2 from:

=Height*0.341

to:

=IF(User.visCalloutIconNumber=2,Height*0.341,Height*0.25)

image

All that remains is to edit the Geometry1.NoShow cell formula of Sheet.5 to =FALSE :

image

Finally, I closed the master shape window to save the icon set.

I then refreshed the displayed icon set by selecting another one, applying, then back to the Faces icon set. Now I get an icon for each of the six values in my KPI Shape Data row:

image

Note that these edited icon sets are in the document stencil. You can download this example from : https://skydrive.live.com/redir.aspx?cid=3350d61bc93733a9&resid=3350D61BC93733A9!2514&parid=3350D61BC93733A9!197

I have shown how you can modify one of the built-in icon sets in Visio 2007/2010, and you can apply the same principle to all of the other built-in icon sets, or you can build your own icon sets.

Make Your Own Data Graphic – Icon Sets at http://blogs.msdn.com/b/visio/archive/2007/07/20/make-your-own-data-graphic-icon-sets.aspx

Create your own Icon-Sets for Data Graphics at http://blogs.msdn.com/b/chhopkin/archive/2009/02/03/create-your-own-icon-sets-for-data-graphics.aspx 

Using Data Graphics to Reinforce Information at http://www.visualizinginformation.com/chapters/chapter07/chapter.aspx

In the next blog, I will be showing you how to create new icon sets from existing shapes … automatically.

Follow

Get every new post delivered to your Inbox.

Join 45 other followers