Macro for Filtering based on “Task Path” in Microsoft Project

Here in the TaskPathFilters module, I provide five simple macros for applying a filter (or table highlighting) that corresponds to Task Path bar highlighting output.

For users of Microsoft Project 2013+, including the desktop versions of Project for Office 365, the Task Path bar styles provide a useful method for highlighting logical connections between tasks.  Four different sets of bar styles can be created, corresponding to the Predecessors, Driving Predecessors, Successors, and Driven Successors of the selected task.  Unfortunately, the “show for…” criteria used to apply the bar styles are not available for creating a filtered display of tasks – say the driving path to a key milestone – while hiding the non-driving tasks.

[The “driving” and “driven” Task Paths are defined (by MSP) using the task StartDriver object, the same as in the Task Inspector.  As shown here, StartDriver has proven unreliable in identifying driving logic in the presence of non-FS relationships, actual progress, splits, and resource leveling.

In another blog entry here, you can find a set of macros for duplicating the results of the Task Path bars, with the added benefit of being able to re-sort tasks according to logic flow, so concurrent logic paths are easily separated.  Those macros use the same underlying data as Task Paths, so their results should be identical to these.  Unlike these, they can be used in versions of MSP prior to 2013.]

Here’s the code (requires MSP 2013+).

Note, for real logic analysis, have a look at BPC Logic Filter.

1'TaskPathFilters Module
2'This module includes five procedures to mark tasks according to their TaskPath
3'characteristics.  A sixth procedure applies a filter to display only the marked tasks.
4'The module is intended only for users of Microsoft Project 2013+, which incorporates TaskPath
5'formatting of task bars.  If the applicable TaskPath formatting has not been applied,
6'then no filter will be created.  VBA code developed by TMBoyle, 14Sep'18
7'   1. Install all code into a new module, with "TaskPathFilters Module" above as the top line.
8'   2. Assign buttons or hotkeys to the first five procedures only (the other one is called by these):
9        'a. AllTaskPathFilter() - Filters all the marked task paths.
10        'b. TaskPathPredecessorFilter() - Filters the marked "predecessors" of the selected task.
11        'c. TaskPathDrivingPredecessorFilter() - Filters the marked "driving predecessors" of the selected task.
12        'd. TaskPathSuccessorFilter() - Filters the marked "successors" of the selected task.
13        'e. TaskPathDrivenSuccessorFilter() - Filters the marked "driven successors" of the selected task.
14'
15Public MsgBase As String, Tsel As Task
16Sub AllTaskPathFilter()
17    Dim t As Task
18    Dim Apply As Boolean
19     
20    Set Tsel = ActiveCell.Task
21    For Each t In ActiveProject.Tasks
22        If Not t Is Nothing Then
23            If (t.PathPredecessor = True) Or (t.PathDrivingPredecessor = True) Or _
24                (t.PathSuccessor = True) Or (t.PathDrivenSuccessor = True) Then
25                t.Marked = True
26                Apply = True
27            Else
28                t.Marked = False
29            End If
30        End If
31    Next t
32    Tsel.Marked = "Yes"
33    If Apply Then
34        MarkedFilter
35        MsgBox (MsgBase & "All Selected for task " & vbCrLf & _
36            Tsel.ID & " - " & Tsel.Name)
37    Else
38        MsgBox "No Filter Applied."
39    End If
40End Sub
41Sub TaskPathPredecessorFilter()
42    Dim t As Task
43    Dim Apply As Boolean
44     
45    Set Tsel = ActiveCell.Task
46    For Each t In ActiveProject.Tasks
47        If Not t Is Nothing Then
48            If t.PathPredecessor = True Then
49                t.Marked = True
50                Apply = True
51            Else
52                t.Marked = False
53            End If
54        End If
55    Next t
56    Tsel.Marked = "Yes"
57    If Apply Then
58        MarkedFilter
59        MsgBox (MsgBase & "Predecessors of task " & vbCrLf & _
60            Tsel.ID & " - " & Tsel.Name)
61    Else
62        MsgBox "No Filter Applied."
63    End If
64End Sub
65 
66Sub TaskPathDrivingPredecessorFilter()
67    Dim t As Task
68    Dim Apply As Boolean
69     
70    Set Tsel = ActiveCell.Task
71    For Each t In ActiveProject.Tasks
72        If Not t Is Nothing Then
73            If t.PathDrivingPredecessor = True Then
74                t.Marked = True
75                Apply = True
76            Else
77                t.Marked = False
78            End If
79        End If
80    Next t
81    Tsel.Marked = "Yes"
82    If Apply Then
83        MarkedFilter
84        MsgBox (MsgBase & "Driving Predecessors of task " & vbCrLf & _
85            Tsel.ID & " - " & Tsel.Name)
86    Else
87        MsgBox "No Filter Applied."
88    End If
89End Sub
90 
91Sub TaskPathSuccessorFilter()
92    Dim t As Task
93    Dim Apply As Boolean
94     
95    Set Tsel = ActiveCell.Task
96    For Each t In ActiveProject.Tasks
97        If Not t Is Nothing Then
98            If t.PathSuccessor = True Then
99                t.Marked = True
100                Apply = True
101            Else
102                t.Marked = False
103            End If
104        End If
105    Next t
106    Tsel.Marked = "Yes"
107    If Apply Then
108        MarkedFilter
109        MsgBox (MsgBase & "Successors of task " & vbCrLf & _
110            Tsel.ID & " - " & Tsel.Name)
111    Else
112        MsgBox "No Filter Applied."
113    End If
114End Sub
115 
116Sub TaskPathDrivenSuccessorFilter()
117    Dim t As Task
118    Dim Apply As Boolean
119     
120    Set Tsel = ActiveCell.Task
121    For Each t In ActiveProject.Tasks
122        If Not t Is Nothing Then
123            If t.PathDrivenSuccessor = True Then
124                t.Marked = True
125                Apply = True
126            Else
127                t.Marked = False
128            End If
129        End If
130    Next t
131    Tsel.Marked = "Yes"
132    If Apply Then
133        MarkedFilter
134        MsgBox (MsgBase & "Driven Successors of task " & vbCrLf & _
135            Tsel.ID & " - " & Tsel.Name)
136    Else
137        MsgBox "No Filter Applied."
138    End If
139End Sub
140 
141Sub MarkedFilter()
142Dim HL As Boolean
143 
144    If MsgBox("Apply Highlighting Only?", vbYesNo) = vbYes Then
145        HL = True
146        MsgBase = "Highlighting TaskPath "
147    Else
148        MsgBase = "Filtered for TaskPath "
149    End If
150    On Error Resume Next
151    FilterApply Name:="Marked Tasks", Highlight:=HL
152    If Err.Number <> 0 Then
153        FilterEdit Name:="Marked Tasks", TaskFilter:=True, Create:=True, OverwriteExisting:=True, _
154           FieldName:="Marked", Test:="equals", Value:="Yes", ShowInMenu:=True, ShowSummaryTasks:=True
155        FilterApply Name:="Marked Tasks", Highlight:=HL
156    End If
157    EditGoTo ID:=Tsel.ID
158End Sub

Why I Left LinkedIn Groups

LinkedIn Groups are dead to me.  Today I removed my membership in all 22 Groups that I had joined since creating my LinkedIn account nearly 13 years ago.  For a long while during those 13 years, Groups seemed to provide the main forums for interesting discussions on project management topics, and a few web boards that had previously hosted those discussions became comparatively barren as a result.  Over the last several years, however, Groups have transformed from discussion forums into bazaars crowded with hawkers.  They’ve now become too noisy to stay and listen.

Here is a list of Groups’ problems that I’ve been mulling over the last 12 months or so:

  1. Barrage Marketing. I.e. >90% of thread initiators in some groups are links to external content, and there are few good discussions.  (One notable exception is the FIDIC Contracts group, which has a lot of active participants and seems to be extraordinarily well curated.  I’ll miss that one.)
  2. No retention of information. (Short memory and no search).  If you stumble upon or participate in a particularly edifying Group discussion – one that you may want to refer to later – don’t expect LinkedIn to archive it for you.  If it’s worth saving, copy and save it yourself.
  3. Classic Silos / Fragmentation of Discussion on common topics.  Whether asking a new and interesting question, sharing a Pulse article, or looking to drive traffic to an external website, thread-starters routinely cross-post the same entry to multiple groups.  (One day I encountered the same entry in eight or nine different groups.)  The scattered and disjointed comments that result can hardly be called discussions.
  4. Sloppy/repetitive discourse.  This is on the users.  E.g. ignoring all previous comments while simply repeating them.  Failure to “listen” before speaking. (There is no rational motivation for this.)
  5. Comments hierarchy.  The organization (i.e. grouping and sorting) of LinkedIn comments seems to vary depending on the client platform (e.g. mobile or desktop) and LinkedIn source (e.g. Group discussion, Pulse article, or Share).  Most of my interactions have been in Group discussions on a computer, where comments have been arranged (until recently) in flat chronological order.
  6. It’s difficult or impossible to filter views to see only “new” comments (i.e. since my last visit) or even “recent” comments (i.e. within the last day).  The “New conversations” control is not valid.
  7. Outright deletion of valid content by LI – e.g. truncation of discussions (while still leaving them open for further comments).  Deja vu!
  8. The last straw: it seems the September 2018 update to Groups has simply amplified all the negatives above.  Clicking a “Group” today reveals a simple stream of graphics-heavy linked content and ads for my consumption, hardly distinguishable from a Facebook or Twitter feed.  LinkedIn Groups is no longer a place to converse.  I’m done.