Introduction to Validation Rules in Visio Premium 2010

Summary:  Learn about the new diagram validation feature in Microsoft Visio Premium 2010 and how to use the Validation API to create your own rules and rule sets to validate Visio 2010 diagrams.

Applies to: Office 2010 | SharePoint Server 2010 | Visio 2010 | Visio Premium 2010

In this article
Overview
Prerequisites
User Experience
Structured Diagrams
Validation API Overview
Validating Structured Diagrams
Reviewing Existing Rules
Creating a New Rule Set
Example: Creating a Fault Tree Analysis Rule Set
Publishing Rules
Conclusion
Additional Resources
About the Author

Published:  July 2010

Provided by:  MVP ContributorDavid J. Parker, bVisual Ltd | About the Author

Contents

  • Overview

  • Prerequisites

  • User Experience

  • Structured Diagrams

  • Validation API Overview

  • Validating Structured Diagrams

  • Reviewing Existing Rules

  • Creating a New Rule Set

  • Example: Creating a Fault Tree Analysis Rule Set

  • Publishing Rules

  • Conclusion

  • Additional Resources

Overview

Microsoft Visio Premium 2010 introduced an extension to the Visio Type Library called the Validation API. By using the Validation API, you can validate a Visio diagram to ensure that its construction complies with a set of rules (for example, industry-standard diagram rules, or custom rules designed for a particular company). Organizations are able to use this new feature to encapsulate business logic as validation rules, grouped within rule sets. Visio Premium 2010 contains default rule sets for use with Basic and Cross-Functional Flowcharts, Business Process Modeling Notation (BPMN) Diagrams, and SharePoint Workflow Designer diagrams.

Prerequisites

This article uses the Validation API that is found only in Microsoft Visio Premium 2010. The reader should either have experience in, or have the willingness to learn about, Visio ShapeSheet formula construction. Additional Resources are provided at the end of the article.

The rule-set development methodology described in this article uses Visual Basic for Applications (VBA) macros. Therefore, macros must be enabled in Visio.

To enable macros in Visio

  1. On the File tab, click Options, click Trust Center, and then click Trust Center Settings.

  2. In the Trust Center dialog box, click the Macros Settings tab.

  3. Under Developer Macro Settings, select Trust access to the VBA project object model.

User Experience

Visio Premium 2010 contains an additional tab, Process (in the ribbon component of the Microsoft Office Fluent user interface, as shown in Figure 1), that provides access to the visible parts of the Validation API in the Diagram Validation group.

Figure 1. Process tab

Process tab

The user clicks the Check Diagram button to validate the whole document against the currently enabled rule sets in the document. The Issues window, shown in Figure 2, displays any issues that the validation process raises. To easily find shapes that have issues, click an issue, and Visio selects the corresponding shape.

Figure 2. Issues window

Issues window

Visio Premium 2010 provides validation support for several diagram templates, including the new BPMN Diagram and Microsoft SharePoint Workflow templates, and the improved Basic Flowchart and Cross-Functional Flowchart templates—all of which are found in the Flowchart category.

Structured Diagrams

There are many types of diagrams that can be considered as structured. A process flow diagram is one type of structured diagram, but there are many other diagrams that structure can be applied to.

A structured diagram is one where there is a set of logical relationships between shapes. Relationships bring visual organization to diagrams, and they can provide special interaction capabilities.

Visio 2010 (all editions) introduced some new features that make it easy for users to form these relationships. The containers, lists, and callouts in Visio 2010 enable shapes to determine containment, order, and association, respectively. This is in addition to the connectivity relationships that have always been possible in Visio, but are now easier to understand and navigate with the new Connectivity API.

Containment

The Containers feature in Visio 2010 makes it easy to add a visual boundary around shapes, including a label, as shown in Figure 3. Visio does all the work to maintain the relationship between the container and its contents.

Figure 3. Diagram containment

Diagram containment

Order

Shapes that are added to a list are automatically arranged adjacent to one another. In Figure 4, the swimlanes are the list shapes in the Cross-Functional Flowchart (CFF) container shape.

Figure 4. Diagram order

Diagram order

Association

A callout shape moves when its target shape is moved. In Figure 5, the Evaluate Discussion Progress task shape has an associated callout that contains descriptive text.

Figure 5. Diagram association

Diagram association

Connectivity

Visio has always provided the capability to create connections between shapes. Originally this was only possible by using a one-dimensional (1-D) shape to connect two-dimensional (2-D) shapes together. The 1-D shape, often referred to as a connector, has a beginning and an end. Therefore, the 2-D shape glued to the beginning of a 1-D shape has an outward connector, and the 2-D shape glued to the end of the 1-D shape has an inward connector, as shown in Figure 6.

Figure 6. Connections between shapes

Connections between shapes

The direction of flow along a 1-D connector can be important for visual and programmatic comprehension. Therefore, it is often necessary to check that shapes are glued to the correct end of the connector.

Note

Lines in Visio can have arrows, and other types of line ends, at either end, both ends, or at neither end. Therefore, you cannot always assume that an arrow on a line indicates the direction of the line.

Later versions of Visio introduced the ability for two 2-D shapes (for example, the work surfaces in the Office Layout template) to be glued to one another, or even for two 1-D shapes to be glued together (for example, the pipelines in the Process Flow template).

Validation API Overview

The key objects, methods, and properties for validation are shown in Figure 7.

Figure 7. Key Validation objects, methods, and properties

Key Validation objects, methods, and properties

The Validation API is based on three main concepts: rule sets, rules, and issues. A validation rule, or a rule, represents one type of error that can occur in your diagram. Each rule has underlying business logic that determines when the rule is broken. An issue is one case in your diagram where the validation rule is broken. Depending on your diagram, there may be multiple issues associated with the same rule. For example, if the rule requires that all shapes be labeled, validation will display an issue for each shape that is missing a label. Rule sets are logical grouping of rules, such as the BPMN and Flowchart rule sets.

Key Validation Objects and Properties

Rules sets, rules, and issues each have corresponding API objects: ValidationRuleSet, ValidationRule, and ValidationIssue, respectively. In the following sections, the key properties for each of these objects are described.

ValidationRuleSet

Every rule set has a unique NameU property that represents the universal name of the rule set. You should also specify a Description property value for each rule set. Other properties are set by default, and you have to modify them only if you want a different behavior. The key properties of the ValidationRuleSet object are shown in Table 1.

Table 1. Key ValidationRuleSet properties

Property

Description

Description

Specifies the description of the rule set.

Enabled

Determines whether the rule set is active or inactive. Only rules that belong to active rule sets are checked when validation is triggered. By default, rule sets are enabled.

Name

Specifies the name of the rule set that appears in the user interface (UI). By default, it is the same as the value of NameU.

NameU

Specifies the universal name of the rule set.

Rules

Itemizes the rules in the rule set.

RuleSetFlags

Determines whether the rule set appears in the UI. By default, rule sets are visible in the UI.

ValidationRule

Every rule has a unique NameU property that represents the universal name of the rule. You should also specify a Category and Description property value for each rule, because these properties are used in the UI. The Category value should inform the user about the type of issue, and may be used to determine the rule set that triggered the issue. The Description value should be explicit enough to explain the issue so that a user can address it. The key properties of the ValidationRule object are shown in Table 2.

Table 2. Key ValidationRule properties

Property

Description

Category

Represents the text that is displayed in the Category column of the Issues window.

Description

Specifies the description of the rule that appears in the Issues window.

FilterExpression

Specifies the logical expression that determines whether the validation rule should be applied to a target object.

Ignored

Determines whether the validation rule is currently ignored. By default, rules are not ignored.

NameU

Specifies the universal name of the rule.

RuleSet

Returns the rule set that contains the rule.

TargetType

Determines the target type of the rule. A rule can target documents, pages, or shapes.

The TargetType property value must be one of the following VisRuleTargets constants:

  • visRuleTargetShape = 0

  • visRuleTargetPage = 1

  • visRuleTargetDocument = 2

TestExpression

Specifies the logical expression that determines whether the target object satisfies the rule.

ValidationIssue

Every issue has an associated rule that specifies the description and category that is displayed in the Issues window. When a user clicks an issue in the Issues window, Visio displays the page that contains the issue (if the issue targets a page or shape) and selects the target shape (if the issue targets a shape). The TargetPage, TargetPageID, and TargetShape properties are used to determine the page to display and the shape to select. The key properties of the ValidationIssue object are shown in Table 3.

Table 3. Key ValidationIssue properties

Property

Description

Ignored

Determines whether the issue is currently ignored.

Rule

Specifies the rule that generated the issue.

TargetPage

Specifies the page that is associated with the issue.

TargetPageID

Specifies the ID of the page that is associated with the validation issue.

TargetShape

Specifies the shape that is associated with the validation issue.

Validating Structured Diagrams

A document can contain multiple rule sets, each of which can be enabled or disabled for the purposes of validating the structure. Visio Premium 2010 contains a Flowchart rule set that is used in the Basic Flowchart, Cross-Functional Flowchart, and Six Sigma templates. All of the rules in the Flowchart rule set are defined in filter and test expressions. You can analyze these rules to learn how to create rule sets for other types of diagrams.

Another example of the Flowchart rule set in Visio Premium 2010 is the BPMN Diagram template, as shown in Figure 8. This rule set supports BPMN 1.2, which enables organizations that use this particular methodology to verify that diagrams are structured accordingly.

Figure 8. BPMN rule set

BPMN rule set

You can import rule sets from other open Visio documents by using the Import Rules From option. However, if the required rules are very complex, you can also write rules in code. These types of rules do not require filter and test expressions because they are invoked by the RuleSetValidated event. An example of this type of rule set in Visio Premium 2010 is the SharePoint Designer Workflow template.

Reviewing Existing Rules

To understand how to create your own rules, it is useful to examine a set of existing rules.

To create a list of existing rules

  1. Open a Basic Flowchart template from the Flowchart category, as shown in Figure 9.

    Figure 9. Basic Flowchart template

    Basic Flowchart template

  2. Ensure that the Developer tab is displayed in Visio:

    1. On the File tab, click Options.

    2. In the Visio Options dialog box, click the Advanced tab.

    3. Under General, select Run in developer mode.

  3. Open the VBA Editor by clicking Visual Basic on the Developer tab, and then insert a module into the VBA project.

  4. On the Tools menu, click References, and then select Microsoft Forms 2.0 Object Library to add a reference to that library to your project. The Microsoft Forms object library provides access to the Clipboard object.

    Tip

    If you insert a UserForm into the VBA project, it will automatically add the Microsoft Forms reference, as shown in Figure 10. You can then remove the UserForm.

    Figure 10. Microsoft Forms reference

    Microsoft Forms reference

  5. Copy and paste the following EnumerateRules() subroutine into the module.

    Public Sub EnumerateRules()
    Dim doc As Visio.Document
    Dim ruleSet As Visio.ValidationRuleSet
    Dim rule As Visio.ValidationRule
    Dim datObj As DataObject
    Dim txt As String
        Set doc = Visio.ActiveDocument
        txt = "EnumerateRulesSets Count = " & doc.Validation.RuleSets.Count
    
        For Each ruleSet In doc.Validation.RuleSets
            If ruleSet.Enabled Then
    
                txt = txt & vbCrLf & "EnumerateRules for RuleSet : " & _
                    ruleSet.nameu & " : Count = " & ruleSet.Rules.Count
                txt = txt & vbCrLf & "ID" & vbTab & "Category" & vbTab & "NameU" & vbTab & _
                    "Description" & vbTab & "TargetType" & vbTab & _
                    "FilterExpression" & vbTab & "TestExpression"
    
                For Each rule In ruleSet.Rules
                    With rule
    
                        txt = txt & vbCrLf & .ID & vbTab & .category & vbTab & .nameu & vbTab & _
                            .description & vbTab & .targettype & vbTab & _
                            .filterexpression & vbTab & .testexpression
                    End With
                Next
            End If
        Next
        Set datObj = New DataObject
        datObj.SetText txt
        datObj.PutInClipboard
    End Sub
    

This subroutine copies into the Clipboard all the rules for enabled rule sets in the active document. You can then paste the contents into Microsoft Excel, for example, to create a table, as shown in Table 4.

Table 4. Enabled rule sets

EnumerateRulesSets Count = 1

EnumerateRules for RuleSet : Flowchart : Count = 11

ID

Category

NameU

Description

TargetType

FilterExpression

TestExpression

1

Connectivity

Unglued or Connect

Connector is not glued at both ends.

0

ROLE()=1

AND(AGGCOUNT(GLUEDSHAPES(4))=1, AGGCOUNT(GLUEDSHAPES(5))=1)

2

Start / End

StartWithoutTerminator

Flowchart shape has no incoming connectors and is not a Start/End shape.

0

AND(OR(HASCATEGORY("Flowchart"),ONLAYER("Flowchart")),NOT(OR(HASCATEGORY("Start/End"),STRSAME(LEFT(MASTERNAME(750),9),"Start/End"),STRSAME(LEFT(MASTERNAME(750),10),"Terminator"))))

AGGCOUNT(GLUEDSHAPES(1)) > 0

3

Start / End

EndWithoutTerminator

Flowchart shape has no outgoing connectors and is not a Start/End shape.

0

AND(OR(HASCATEGORY("Flowchart"),ONLAYER("Flowchart")),NOT(OR(HASCATEGORY("Start/End"),STRSAME(LEFT(MASTERNAME(750),9),"Start/End"),STRSAME(LEFT(MASTERNAME(750),10),"Terminator"))))

AGGCOUNT(GLUEDSHAPES(2)) > 0

4

Start / End

NoStartTerminator

Flowchart does not start with a Start/End shape.

1

AGGCOUNT(FILTERSET(SHAPESONPAGE(), "OR(HASCATEGORY(""Flowchart""),ONLAYER(""Flowchart""))")) > 0

AGGCOUNT(FILTERSET(SHAPESONPAGE(), "AND(OR(HASCATEGORY(""Start/End""),STRSAME(LEFT(MASTERNAME(750),9),""Start/End""),STRSAME(LEFT(MASTERNAME(750),10),""Terminator"")),AGGCOUNT(CONNECTEDSHAPES(2))>0)")) > 0

5

Start / End

NoEndTerminator

Flowchart does not end with a Start/End shape.

1

AGGCOUNT(FILTERSET(SHAPESONPAGE(), "OR(HASCATEGORY(""Flowchart""),ONLAYER(""Flowchart""))")) > 0

AGGCOUNT(FILTERSET(SHAPESONPAGE(), "AND(OR(HASCATEGORY(""Start/End""),STRSAME(LEFT(MASTERNAME(750),9),""Start/End""),STRSAME(LEFT(MASTERNAME(750),10),""Terminator"")),AGGCOUNT(CONNECTEDSHAPES(1))>0)")) > 0

6

Connectivity

UnconnectedShape

Flowchart shape is not connected to any other shape.

0

OR(HASCATEGORY("Flowchart"),ONLAYER("Flowchart"))

AGGCOUNT(CONNECTEDSHAPES(0)) > 0

7

Connectivity

TerminatorinMiddle

Start/End shape has both incoming and outgoing connectors.

0

OR(HASCATEGORY("Start/End"),STRSAME(LEFT(MASTERNAME(750),9),"Start/End"),STRSAME(LEFT(MASTERNAME(750),10),"Terminator"))

NOT(AND(AGGCOUNT(CONNECTEDSHAPES(1))>0,AGGCOUNT(CONNECTEDSHAPES(2))>0))

8

Connectivity

TooFewOutConns

Decision shape should have more than one outgoing connector.

0

OR(HASCATEGORY("Decision"),STRSAME(LEFT(MASTERNAME(750),8),"Decision"))

AGGCOUNT(GLUEDSHAPES(2)) > 1

9

Connectivity

NonFlowchartShape

Connected shape is not recognized as a Flowchart shape.

0

NOT(OR(HASCATEGORY("Flowchart"),ONLAYER("Flowchart")))

AGGCOUNT(GLUEDSHAPES(0)) = 0

10

Text

NoShapeText

Flowchart shape has no text label.

0

OR(HASCATEGORY("Flowchart"),ONLAYER("Flowchart"))

NOT(STRSAME(SHAPETEXT(TheText), ""))

11

Cross - Functional

OutsideCFF

Flowchart shapes should belong to a Swimlane.

1

AGGCOUNT(FILTERSET(SHAPESONPAGE(),"HASCATEGORY(""Swimlane"")"))>0

AGGCOUNT(FILTERSET(SHAPESONPAGE(),"AND(OR(HASCATEGORY(""Flowchart""),ONLAYER(""Flowchart"")),AGGCOUNT(FILTERSET(PARENTCONTAINERS(),""HASCATEGORY(""""Swimlane"""")""))=0)"))=0

The FilterExpression and TestExpression formulas are regular ShapeSheet functions, apart from several new special functions added in Visio 2010 especially for validation.

Table 5 lists the special functions that resemble ShapeSheet functions and can be used in the FilterExpression and TestExpression formulas.

Table 5. FilterExpression and TextExpression functions

Function

Description

Role()

Returns an integer that indicates the shape role:

  • Element = 0

  • Connector = 1

  • Container = 2

  • Callout = 4

OnLayer(LayerName)

If called on a shape, returns a Boolean value that indicates whether the shape is a member of the specified layer. If called on a page, returns a Boolean value that indicates whether the layer exists on the page.

ConnectedShapes(Direction)

Returns the set of shapes that match the Direction criteria and are connected to the shape. The ConnectedShapes function skips over the connectors, whereas the GluedShapes function returns the connector shapes themselves.

The value of Direction is one of the VisConnectedShapesFlags constants:

  • visConnectedShapesAllNodes = 0

  • visConnectedShapesIncomingNodes = 1

  • visConnectedShapesOutgoingNodes = 2

GluedShapes(Direction)

Returns the set of shapes that match the Direction criteria and are glued to the shape. The ConnectedShapes function skips over the connectors, whereas the GluedShapes function returns the connector shapes themselves.

The value of Direction is one of the VisGluedShapesFlags constants:

  • visGluedShapesAll1D = 0

  • visGluedShapesIncoming1D = 1

  • visGluedShapesOutgoing1D = 2

  • visGluedShapesAll2D = 3

  • visGluedShapesIncoming2D = 4

  • visGluedShapesOutgoing2D = 5

ContainerMembers()

Returns the set of shapes that are members of the container or list shape.

ListMembers()

Returns the set of shapes that are members of the list shape.

Callouts()

Returns the set of shapes that are callouts on the shape.

ParentContainers()

Returns the set of containers that the shape belongs to.

ShapesOnPage()

Returns the set of top-level shapes on the page. If no page specifier precedes the function, the shape’s containing page is assumed.

AggCount(Set)

Counts the number of shapes in a set.

FilterSet(Set,FilterExpression)

Returns the subset of shapes in a set that match an expression.

OnBoundaryOf()

Returns the set of containers in such a way that the shape is on the boundary of these containers.

Creating a New Rule Set

Now that you understand how rules are written, you can create your own custom rule sets. This section shows how you can write simple structured diagramming rules for the Fault Tree Analysis diagram, which currently has no validation rules attached.

First create a new Fault Tree Analysis Diagram from the Business category, as shown in Figure 11.

Figure 11. Fault Tree Analysis diagram

Fault Tree Analysis Diagram

Later you will add some VBA code into the VBA project of this new document.

Analyzing the Requirements

The first task is to understand the shapes that you can use in the construction of the diagram type.

Drag all of the master shapes from the Fault Tree Analysis Shapes stencil and drop them onto the blank page. Then open the Document Stencil and Drawing Explorer windows (on the Developer tab) to see what layers the shapes are on by default. As you can see in Figure 12, the Dynamic connector is on the Connector layer, and all of the other shapes are on the Flowchart layer.

Figure 12. Shape layers

Shape layers

You can also check the shapes to see whether they contain any shape data rows (these particular master shapes do not).

Next, you can group the masters by usage. In this case, there are six gate symbols, five event symbols, one transfer symbol, and one connector.

Now you can start to think about the basic rules that you want to create. The following list shows an example set of rules:

  • Every connector must be connected to a shape at each end.

  • Every event shape must be labeled.

  • Every Fault Tree Analysis (FTA) shape must be connected to another FTA shape.

  • An undeveloped event should not have any outward connections.

  • Every gate shape must have only one input.

  • Every gate, except the inhibit gate, must have at least two outputs.

  • An inhibit gate should have one outward connection.

  • Every gate, except the inhibit gate, must connect to at least three events.

  • A transfer symbol must have only one connection.

To create some of these rules, you will need to clarify what a valid shape is.

First, determine whether all of the valid shapes are on the Flowchart layer. You can use the OnLayer(LayerName) function to check for this.

Next, determine the names of the master shapes. You can use the MasterName(langid_opt) function for this, but you have to exercise a bit of caution. This is because it is easy for a user to accidentally create duplicate masters in a document, in which case Visio will automatically force the duplicate master name to be unique by appending a dot and a number. Consequently, you should modify the test to be StrSame(Left(MasterName(750),n),Name), where 750 is the universal language code, Name is the name of the master to be checked, and n is the number of characters in the Name.

In the flowchart templates that already have rules supplied, the master shapes have been modified to include an additional user-defined cell, User.msvShapeCategories, which can contain a list of categories that the shape belongs to. You can then use the new HasCategory(CategoryName) function, instead of the MasterName() function, as a test. If you are creating a template that contains your own masters, you have the option of adding the User.msvShapeCategories to your masters.

Adding a Rule Set

First, you must create a rule set for the rules to belong to. The following code procedure, AddRuleSet(), adds the Fault Tree Analysis rule set, or updates it if it already exists. It is followed by a support procedure, getRuleSet(), which is used to test whether a named rule exists. It will return the Ruleset object if it exists; otherwise, it will return Nothing.

Public Sub AddRuleSet()
' Add a validation rule set to the document.
' Edit the nameU to suit.
Dim doc As Visio.Document
Dim ruleSet As Visio.ValidationRuleSet
Dim nameU As String
    nameU = "Fault Tree Analysis"
    Set doc = Visio.ActiveDocument
    ' Check whether the rule set already exists.
    Set ruleSet = getRuleSet(doc, nameU)
    If ruleSet Is Nothing Then
        ' Create the new rule set.
        Set ruleSet = doc.Validation.RuleSets.Add(nameU)
    End If
    ruleSet.description = "Example Fault Tree Analysis rule set."
    ruleSet.Enabled = True
    ruleSet.RuleSetFlags = Visio.VisRuleSetFlags.visRuleSetDefault
End Sub

Private Function getRuleSet(ByVal doc As Visio.Document, _
    ByVal nameU As String) As Visio.ValidationRuleSet
' Return a named rule set or nothing.
Dim retVal As Visio.ValidationRuleSet
Dim ruleSet As Visio.ValidationRuleSet
    Set retVal = Nothing
    For Each ruleSet In doc.Validation.RuleSets
        If UCase(ruleSet.nameU) = UCase(nameU) Then
            Set retVal = ruleSet
            Exit For
        End If
    Next
    Set getRuleSet = retVal
End Function

Deleting a Rule Set

You can use the following DeleteRuleSet() code procedure to delete an unwanted rule in a rule set.

Public Sub DeleteRuleSet()
' Delete a rule set from the active document.
' Edit the ruleSetNameU value to suit.
Dim doc As Visio.Document
Dim nameU As String
    nameU = "Fault Tree Analysis"
    Set doc = Visio.ActiveDocument
    ' Check whether the rule set already exists.
    If Not getRuleSet(doc, nameU) Is Nothing Then
        ' Delete the rule set.
        doc.Validation.RuleSets.Item(nameU).Delete
    End If
End Sub

Adding a Rule

The following example code procedure shows how to add a rule to a rule set.

Public Sub AddRule()
' Add a rule to named rule set.
' Edit nameU and the addARule arguments to suit.
Dim doc As Visio.Document
Dim ruleSet As Visio.ValidationRuleSet
Dim nameU As String
    nameU = "Fault Tree Analysis"
    Set doc = Visio.ActiveDocument
    ' Check whether the rule set already exists.
    Set ruleSet = getRuleSet(doc, nameU)
    If ruleSet Is Nothing Then
        Exit Sub
    End If
    ' Add the rule.
    addARule ruleSet, "Connectivity", "UngluedConnector", _
            "Connector is not glued at both ends.", 0, _
            "ROLE()=1", _
            "AND(AGGCOUNT(GLUEDSHAPES(4)) = 1, AGGCOUNT(GLUEDSHAPES(5)) = 1)"
End Sub

Private Function getRule(ByVal ruleSet As Visio.ValidationRuleSet, _
    ByVal nameU As String) As Visio.ValidationRule
' Return a named rule or nothing.
Dim retVal As Visio.ValidationRule
Dim rule As Visio.ValidationRule
    Set retVal = Nothing
    For Each rule In ruleSet.Rules
        If UCase(rule.nameU) = UCase(nameU) Then
            Set retVal = rule
            Exit For
        End If
    Next
    Set getRule = retVal
End Function

Private Sub addARule(ByVal ruleSet As Visio.ValidationRuleSet, _
    ByVal category As String, ByVal nameU As String, _
    ByVal description As String, ByVal targetType As Integer, _
    ByVal filterExpression As String, ByVal testExpression As String)
    ' Add or update a validation rule in the document.
Dim rule As Visio.ValidationRule
    Set rule = getRule(ruleSet, nameU)
    If rule Is Nothing Then
        Set rule = ruleSet.Rules.Add(nameU)
    End If
    rule.category = category
    rule.description = description
    rule.Ignored = False
    rule.targetType = targetType
    rule.filterExpression = filterExpression
    rule.testExpression = testExpression
    ' Flush existing issues to ensure re-validation.
    ruleSet.Document.Validation.Issues.Clear
End Sub

Deleting a Rule

You can use the following DeleteRule() code procedure to delete an unwanted rule from a rule set.

Public Sub DeleteRule()
' Delete a rule from a rule set.
' Edit ruleSetNameU and ruleNameU to suit.
Dim ruleSetNameU As String
Dim ruleSet As Visio.ValidationRuleSet
    ruleSetNameU = "Fault Tree Analysis"
    Set ruleSet = getRuleSet(Visio.ActiveDocument, ruleSetNameU)
    If ruleSet Is Nothing Then
        Exit Sub
    End If
    
Dim ruleNameU As String
    ruleNameU = "UngluedConnector"
    
    ' Check whether the rule already exists.
    If Not getRule(ruleSet, ruleNameU) Is Nothing Then
        ' Delete the rule.
        ruleSet.Rules.Item(ruleNameU).Delete
    End If
End Sub

Adding a Rule from the Clipboard

To add a rule to a rule set, the AddRule() procedure shown previously works fine. However, you will have to either edit the procedure for more rules, or copy the procedure, slightly rename it, and then edit the arguments for the addARule() procedure. If you use this approach, you will have many variations of the AddRule() procedure in your module.

However, alternatively, you can enter the arguments in a Microsoft Excel table, in a format similar to the output in the EnumerateRulesets() method listed previously. You can then edit your arguments—especially the filter and test expressions—in an Excel cell, as shown in Figure 13.

Figure 13. Editing arguments in Excel

Editing arguments in Excel

Then use the following code to add the rules from Excel to your drawing. Notice that this method will work on multiple rows, but it assumes that a header row exists and skips over that row by starting at row 2. If your spreadsheet does not have a header row, adjust the code accordingly.

' Adds rules to named rule set from Excel.
' To use this in a VBA project, add a reference to the "Microsoft Excel 14.0 Object Library".
Public Sub AddRulesFromExcel()

    Dim xlWorkbook As Excel.Workbook
    Dim doc As Visio.Document
    Dim ruleSet As Visio.ValidationRuleSet
    Dim nameu As String
    nameu = "Fault Tree Analysis"
    
    Dim category As String
    Dim rulenameu As String
    Dim description As String
    Dim targettype As String
    Dim filterexpression As String
    Dim testexpression As String
    
    Const categoryCol As Integer = 2
    Const rulenameCol As Integer = 3
    Const descriptionCol As Integer = 4
    Const targettypeCol As Integer = 5
    Const filterexpressionCol As Integer = 6
    Const testexpressionCol As Integer = 7
    
    Set doc = Visio.ActiveDocument
    
    ' Check whether the rule set exists already.
    Set ruleSet = GetRuleSet(doc, nameu)
    If ruleSet Is Nothing Then
        Exit Sub
    End If
    
    ' Get data from Excel.
    ' Assumes you have created an Excel spreadsheet at the path shown, that contains the rules you want to add,
    ' and with columns that correspond to the constants declared in this subroutine.
    Dim xlApp As New Excel.Application

    Set xlWorkbook = xlApp.Workbooks.Open("C:\Users\username\Documents\RuleList.xlsx")
    
    On Error GoTo AddRulesFromExcel_Err

    Dim xlWorkSheet As Excel.Worksheet
    Set xlWorkSheet = xlWorkbook.Worksheets(1)
    
    Dim numRows As Integer
    numRows = xlWorkSheet.UsedRange.Rows.Count
    
    ' Assumes that a header row exists and skips over it.
    For xlRow = 2 To numRows
    
        category = xlWorkSheet.Cells(xlRow, categoryCol)
        rulenameu = xlWorkSheet.Cells(xlRow, rulenameCol)
        description = xlWorkSheet.Cells(xlRow, descriptionCol)
        targettype = xlWorkSheet.Cells(xlRow, targettypeCol)
        filterexpression = xlWorkSheet.Cells(xlRow, filterexpressionCol)
        testexpression = xlWorkSheet.Cells(xlRow, testexpressionCol)
   
        addARule ruleSet, category, rulenameu, description, targettype, filterexpression, testexpression
        
    Next xlRow
   
  
AddRulesFromExcel_Err:
    If (Err.Number) Then
        Debug.Print Err.description
    End If
    
    xlWorkbook.Close
    xlApp.Quit
 
End Sub

Example: Creating a Fault Tree Analysis Rule Set

This section describes a set of nine example rules, as introduced in the section Creating a New Rule Set, that you could apply to a Fault Tree Analysis (FTA) diagram. You can use either procedure that is described previously—AddRule() or AddRuleFromExcel()—to add each rule that is listed in this section.

The parameters are listed in the correct order for copying and pasting into Excel. You can use the Transpose command in Excel to switch the layout of each rule from vertical to horizontal. Paste the rule into Excel, press CTRL+C to copy the pasted range, right-click the selection and then, under Paste Options, click Transpose.

Rule 1: Every connector must be connected to a shape at each end.

The Flowchart rule set in the Basic Flowchart drawing already has such a rule. Therefore, you can copy Rule 1 from that default rule set.

Category

Connectivity

NameU

UngluedConnector

Description

Connector is not glued at both ends.

TargetType

0

FilterExpression

ROLE()=1

TestExpression

AND(AGGCOUNT(GLUEDSHAPES(4)) = 1, AGGCOUNT(GLUEDSHAPES(5)) = 1)

The FilterExpression value means that only one-dimensional (1-D) connector shapes are to be tested. The TestExpression value checks that a single two-dimensional (2-D) shape is glued at either end of the connector. The TargetType value for this rule (and for all of the other rules in this article) is the default visRuleTargetShape.

Figure 14. Every connector must be glued at both ends

Every connector must be glued at both ends

Rule 2: Every event shape must be labeled.

The Flowchart rule set also contains a rule named NoShapeText. For the purpose of this example rule set, change the Description value to Event shape has no text label.

You will have to modify the FilterExpression value, because the FTA shapes do not contain the user-defined ShapeSheet cell called Categories. Therefore, you have to check for the master names specifically instead of using the HasCategory() function. The TestExpression value determines whether there is any text in the shape.

Category

Text

NameU

NoShapeText

Description

Event shape has no text label.

TargetType

0

FilterExpression

OR(STRSAME(LEFT(MASTERNAME(750),11),"Basic event"),STRSAME(LEFT(MASTERNAME(750),17),"Undeveloped event"),STRSAME(LEFT(MASTERNAME(750),5),"Event"),STRSAME(LEFT(MASTERNAME(750),11),"House event"),STRSAME(LEFT(MASTERNAME(750),17),"Conditional event")))

TestExpression

NOT(STRSAME(SHAPETEXT(TheText), ""))

To check that this rule is working, you can choose to ignore the first rule, UngluedConnector, by right-clicking the first rule in the Issues window, clicking Ignore this Rule, and then clicking Check Diagram.

Figure 15. Event shape has no text label

Event shape has no text label

Rule 3: Every FTA shape must be connected to another FTA shape.

As in the first two rules, you can copy this rule (UnconnectedShape) from the Basic Flowchart rule set. Change the Description value to FTA shape is not connected to any other shape.

As you did with the NoShapeText rule, you will have to amend the FilterExpression value, but this time it has to check just the layer assignment. The TestExpression value verifies that there are connected shapes.

You could possibly expand this rule to specify names for the master shapes that are connected.

Category

Connectivity

NameU

UnconnectedShape

Description

FTA shape is not connected to any other shape.

TargetType

0

FilterExpression

ONLAYER("Flowchart")

TestExpression

AGGCOUNT(CONNECTEDSHAPES(0)) > 0

You can test this rule by randomly connecting various FTA shapes.

Figure 16. FTA shape is not connected to any other shape

FTA shape is not connected to any other shape

Rule 4: An undeveloped event should not have any outward connections.

There is no existing rule set from which you can copy this rule, so you will have to write your own rule.

The FilterExpression value verifies that an undeveloped-event shape is to be tested. The TestExpression value checks that there are no outward glued connectors.

Category

Connectivity

NameU

UndevelopedEventHasConnectionOut

Description

Undeveloped-event shape should not have any outward connector.

TargetType

0

FilterExpression

STRSAME(LEFT(MASTERNAME(750),17),"Undeveloped event")

TestExpression

AGGCOUNT(GLUEDSHAPES(2)) = 0

You should now test your rule by gluing an outward connector to an undeveloped-event shape.

Figure 17. Undeveloped event should not have an outward connector

No outgoing connector for undeveloped events

Rule 5: Every gate shape must have only one input.

The FilterExpression value checks the layer assignment and verifies that all of the gates shapes are to be tested. The TestExpression checks that there is one inward glued connector.

Category

Connectivity

NameU

GateHasNoConnectionIn

Description

Gate shape should have one inward connection.

TargetType

0

FilterExpression

AND(ONLAYER("Flowchart"),OR(STRSAME(LEFT(MASTERNAME(750),7),"OR gate"),STRSAME(LEFT(MASTERNAME(750),8),"AND gate"),STRSAME(LEFT(MASTERNAME(750),17),"Priority AND gate"),STRSAME(LEFT(MASTERNAME(750),17),"Exclusive OR gate"),STRSAME(LEFT(MASTERNAME(750),11),"Voting gate"),STRSAME(LEFT(MASTERNAME(750),12),"Inhibit gate")))

TestExpression

AGGCOUNT(GLUEDSHAPES(1)) = 1

You can test the rule by adding more than one inward connector on a gate shape, or by having no inward connector at all.

Figure 18. Gate shape should have one inward connection

Gate shape should have one inward connection

Rule 6: Every gate, except the inhibit gate, must have at least two outputs.

The FilterExpression value checks the layer assignment and verifies that all of the gate shapes are to be tested. The TestExpression value checks that there are at least two outward glued connectors.

Category

Connectivity

NameU

GateWithoutAtLeastTwoOutputs

Description

Gate shape has fewer than two outward connectors.

TargetType

0

FilterExpression

AND(ONLAYER("Flowchart"),OR(STRSAME(LEFT(MASTERNAME(750),7),"OR gate"),STRSAME(LEFT(MASTERNAME(750),8),"AND gate"),STRSAME(LEFT(MASTERNAME(750),17),"Priority AND gate"),STRSAME(LEFT(MASTERNAME(750),17),"Exclusive OR gate"),STRSAME(LEFT(MASTERNAME(750),11),"Voting gate")))

TestExpression

AGGCOUNT(GLUEDSHAPES(2)) > 1

You can test the rule by adding fewer than two outward connectors to a gate shape.

Figure 19. Gate shape has fewer than two outward connectors

Gate shape has fewer than two outgoing connectors

Rule 7: An inhibit gate should have one outward connection.

The FilterExpression checks that an inhibit gate shape is to be tested. The TestExpression checks that there is only one outward glued connector.

Category

Connectivity

NameU

InhibitGateNeedsOneOutput

Description

Inhibit gate shape should have one outward connector.

TargetType

0

FilterExpression

STRSAME(LEFT(MASTERNAME(750),12),"Inhibit gate")

TestExpression

AGGCOUNT(GLUEDSHAPES(2)) = 1

You can test the rule by adding more than one outward connector to an inhibit gate shape.

Figure 20. Inhibit gate shape should have one outward connector

Only one outgoing connection for inhibit gate

Rule 8: A gate, except the inhibit gate, must be connected to at least three events.

The FilterExpression value checks that a gate shape other than an inhibit gate shape is to be tested. The TestExpression value checks that there are at least three connected events.

Category

Connectivity

NameU

GateMustConnectAtLeastThreeEvents

Description

Gate shape has fewer than three connected events.

TargetType

0

FilterExpression

OR(STRSAME(LEFT(MASTERNAME(750),7),"OR gate"),STRSAME(LEFT(MASTERNAME(750),8),"AND gate"),STRSAME(LEFT(MASTERNAME(750),17),"Priority AND gate"),STRSAME(LEFT(MASTERNAME(750),17),"Exclusive OR gate"),STRSAME(LEFT(MASTERNAME(750),11),"Voting gate"))

TestExpression

AGGCOUNT(FILTERSET(CONNECTEDSHAPES(0), "OR(STRSAME(LEFT(MASTERNAME(750),11),""Basic event""),STRSAME(LEFT(MASTERNAME(750),17),""Undeveloped event""),STRSAME(LEFT(MASTERNAME(750),5),""Event""),STRSAME(LEFT(MASTERNAME(750),11),""House event""),STRSAME(LEFT(MASTERNAME(750),17),""Conditional event""))")) > 2

You can test the rule by adding fewer than three connectors to any of the gate shapes.

Figure 21. Gate shape has fewer than three connected events

Gate shape has fewer than three connected events

Rule 9: A transfer symbol must have only one connection.

The FilterExpression value checks the layer assignment and verifies that a transfer symbol shape is to be tested. The TestExpression value checks that there is only one glued connector.

Category

Connectivity

NameU

Transfer

Description

Transfer symbol shape should have one connector.

TargetType

0

FilterExpression

AND(ONLAYER("Flowchart"),STRSAME(LEFT(MASTERNAME(750),15),"Transfer symbol"))

TestExpression

AGGCOUNT(GLUEDSHAPES(0))= 1

You can test the rule by adding more than one connector to a transfer symbol, or by having no connectors at all.

Figure 22. Transfer symbol shape should have one connector

Transfer symbol shape should have one connector

Publishing Rules

Rule sets are saved in Visio documents or templates. For example, you can save your blank FTA document as Fault Tree Validation Rules.vsd. Regardless of whether you use a document or template, any drawing based on your file will contain your rule set. After you use VBA code to add the rules to the file, you can safely remove that code to make your drawing file smaller and avoid the requirement to enable macros in drawings that are created from your template.

Alternatively, you could open an existing or new drawing, and then import the rule set by clicking the Check Diagram arrow, pointing to Import Rules From, and then selecting the rule set (as shown in Figure 23).

Figure 23. Importing a rule set

Importing a rule set

Conclusion

This article shows how to analyze existing validation rules in Visio Premium 2010 and how to use the Validation API to create your own rules and rule sets to validate diagrams. By using the Validation API, you can modify existing rules, or you can create complex rules and rule sets in code to validate custom diagram logic.

Additional Resources

For more information about diagram validation in Visio 2010, see the following resources.

Visio Insights Blog

bVisual Blog

MSDN Library

About the Author

David J. Parker is a Visio MVP and the owner of bVisual Ltd. He writes data visualization solutions, primarily using Visio and Bing Maps.

David writes a regular blog about Visio at bvisual.spaces.live.com, and he is the author of Visualizing Information with Microsoft Visio 2007. He just finished a new book, Microsoft Visio 2010 Business Process Diagramming and Validation, for Packt Publishing.