Code to Walk Through Predecessors

B

Bill Bordiuk

I have code that walks through the predecessors of a task using the
TaskDependencies collection to find all paths back to start tasks. This code
works fine unless a task is linked to an external task. Even though the
master and subproject tasks are all displayed, I'm unable to access
predecessors of the 'Ghost' task that project creates to represent the
external link.

Private Sub t1(t As Task, ByVal s As String)
' Recursive walk through a task's predecessors
Dim d As TaskDependency

For Each d In t.TaskDependencies
If t.ID = d.To.ID Then
Debug.Print s & " Pred: " & d.From.ID & "[" & d.From.UniqueID &
"] <" & d.From.Name & "> ext=" & d.From.ExternalTask
t1 d.From, s & " "
End If
Next
End Sub

Public Sub test(p As Project)
Dim t As Task, d As TaskDependency
For Each t In p.Tasks
Debug.Print t.ID & "[" & t.UniqueID & "] : " & t.Name
t1 t, ""
Next
End Sub

Called with Test Activeproject

This code will not walk past an external task. What's strange is that the
Unique IDs of the external tasks are different when you look at them as
predecessors from when you look at them directly. In fact, Project seems to
keep 2 tasks for each external task, the real task and the ghost. If I could
access the real task from the ghost, I could get that task's predecessors
and move through the project. The problem is that I can't find any way to
get to the real task from the ghost except by using the task name to access
the task in the subproject (as in:
Projects(d.from.project).tasks(d.from.name)). This is a problem because
there's no way to be sure that tasks have unique names.

Does anyone have a suggestion/solution here?

Thanks,

Bill B
 
J

JackD

I don't have any handy examples, but the chain of dependencies from one
project to another is actually like this:

Proj1RealTask1 ->
Proj1PointerToTaskinProj2--|-->Proj2PointerToExternalTaskinProj1->Proj2RealT
ask1

That is to say that a dummy "external task" exists in Proj1 which points to
Proj2.

The following code seems to work for me across project boundries.

Sub crossProj()
For Each Task In ActiveProject.Tasks
Set sucs = Task.SuccessorTasks
For Each t In sucs
MsgBox t.Name
Next t
Next Task
End Sub

If you want to use unique ID's you should note that they ARE the same except
that they have a multiple of a very large number added to them at random
(actually depending on the order the projects were inserted)
You can find out the true Unique ID with code like this:

Sub getRealUniqueID()
For Each Task In ActiveProject.Tasks
MsgBox Task.UniqueID Mod 4194304
Next Task
End Sub

I think I'd go beyond using active project and determine the project for the
external tasks and use that as the project you are operating on. Then you
won't have the UID problem. For a hint on how and why look at this article:

http://zo-d.com/blog/archives/project_management/microsoft_project/programming/index.html

Have you taken a look at my "Trace" macro here?
http://masamiki.com/project/macros.htm

--
-Jack ... For project information and macro examples visit
http://masamiki.com/project
or http://zo-d.com/blog/index.html
..
Bill Bordiuk said:
I have code that walks through the predecessors of a task using the
TaskDependencies collection to find all paths back to start tasks. This code
works fine unless a task is linked to an external task. Even though the
master and subproject tasks are all displayed, I'm unable to access
predecessors of the 'Ghost' task that project creates to represent the
external link.

Private Sub t1(t As Task, ByVal s As String)
' Recursive walk through a task's predecessors
Dim d As TaskDependency

For Each d In t.TaskDependencies
If t.ID = d.To.ID Then
Debug.Print s & " Pred: " & d.From.ID & "[" & d.From.UniqueID &
"] <" & d.From.Name & "> ext=" & d.From.ExternalTask
t1 d.From, s & " "
End If
Next
End Sub

Public Sub test(p As Project)
Dim t As Task, d As TaskDependency
For Each t In p.Tasks
Debug.Print t.ID & "[" & t.UniqueID & "] : " & t.Name
t1 t, ""
Next
End Sub

Called with Test Activeproject

This code will not walk past an external task. What's strange is that the
Unique IDs of the external tasks are different when you look at them as
predecessors from when you look at them directly. In fact, Project seems to
keep 2 tasks for each external task, the real task and the ghost. If I could
access the real task from the ghost, I could get that task's predecessors
and move through the project. The problem is that I can't find any way to
get to the real task from the ghost except by using the task name to access
the task in the subproject (as in:
Projects(d.from.project).tasks(d.from.name)). This is a problem because
there's no way to be sure that tasks have unique names.

Does anyone have a suggestion/solution here?

Thanks,

Bill B
 
B

Bill Bordiuk

Jack,

Thanks for the quick response. I tried your code using PredecessorTasks
instead of SuccessorTasks and none of the external tasks showed up in the
predecessor collections (I need to work back from the end tasks for my
analysis). This is the reason I switched to using the TaskDependencies
collection to begin with! The challenge is to find some way to cross the
link between the ghost task in the predecessors collection and the real task
in another project. Here's the set of tasks I'm using to test (all lags are
FS 0):

Top Level
Task Preds
1
2 1
3 2
4 3
5(Sub1)1
6(Sub2)1
7 3,5, 3 from Sub1, 4 from Sub 2
8 7

Sub1
Task Preds
1
2 1
3 2

Sub2
Task Preds
1
2 1
3 2
4 3

Run your code on the top level, replacing SuccessorTasks with
PredecessorTasks. You should see that it doesn't show the second two
predecessors of task 7.

Bill B.
I have code that walks through the predecessors of a task using the
TaskDependencies collection to find all paths back to start tasks. This code
works fine unless a task is linked to an external task. Even though the
master and subproject tasks are all displayed, I'm unable to access
predecessors of the 'Ghost' task that project creates to represent the
external link.

Private Sub t1(t As Task, ByVal s As String)
' Recursive walk through a task's predecessors
Dim d As TaskDependency

For Each d In t.TaskDependencies
If t.ID = d.To.ID Then
Debug.Print s & " Pred: " & d.From.ID & "[" &
d.From.UniqueID
&
"] <" & d.From.Name & "> ext=" & d.From.ExternalTask
t1 d.From, s & " "
End If
Next
End Sub

Public Sub test(p As Project)
Dim t As Task, d As TaskDependency
For Each t In p.Tasks
Debug.Print t.ID & "[" & t.UniqueID & "] : " & t.Name
t1 t, ""
Next
End Sub

Called with Test Activeproject

This code will not walk past an external task. What's strange is that the
Unique IDs of the external tasks are different when you look at them as
predecessors from when you look at them directly. In fact, Project seems to
keep 2 tasks for each external task, the real task and the ghost. If I could
access the real task from the ghost, I could get that task's predecessors
and move through the project. The problem is that I can't find any way to
get to the real task from the ghost except by using the task name to access
the task in the subproject (as in:
Projects(d.from.project).tasks(d.from.name)). This is a problem because
there's no way to be sure that tasks have unique names.

Does anyone have a suggestion/solution here?

Thanks,

Bill B
 
J

JackD

Bill,

I haven't had time to work through this.
As much as I'd like to I'm not sure I will in the near future either.
When I do get a chance to work it out I'll post the solution as an article
on my blog.
http://zo-d.com/blog/index.html
Just don't want to leave you hanging here waiting for an answer.

--
-Jack ... For project information and macro examples visit
http://masamiki.com/project
or http://zo-d.com/blog/index.html

Bill Bordiuk said:
Jack,

Thanks for the quick response. I tried your code using PredecessorTasks
instead of SuccessorTasks and none of the external tasks showed up in the
predecessor collections (I need to work back from the end tasks for my
analysis). This is the reason I switched to using the TaskDependencies
collection to begin with! The challenge is to find some way to cross the
link between the ghost task in the predecessors collection and the real task
in another project. Here's the set of tasks I'm using to test (all lags are
FS 0):

Top Level
Task Preds
1
2 1
3 2
4 3
5(Sub1)1
6(Sub2)1
7 3,5, 3 from Sub1, 4 from Sub 2
8 7

Sub1
Task Preds
1
2 1
3 2

Sub2
Task Preds
1
2 1
3 2
4 3

Run your code on the top level, replacing SuccessorTasks with
PredecessorTasks. You should see that it doesn't show the second two
predecessors of task 7.

Bill B.
I have code that walks through the predecessors of a task using the
TaskDependencies collection to find all paths back to start tasks.
This
code
works fine unless a task is linked to an external task. Even though the
master and subproject tasks are all displayed, I'm unable to access
predecessors of the 'Ghost' task that project creates to represent the
external link.

Private Sub t1(t As Task, ByVal s As String)
' Recursive walk through a task's predecessors
Dim d As TaskDependency

For Each d In t.TaskDependencies
If t.ID = d.To.ID Then
Debug.Print s & " Pred: " & d.From.ID & "[" &
d.From.UniqueID
&
"] <" & d.From.Name & "> ext=" & d.From.ExternalTask
t1 d.From, s & " "
End If
Next
End Sub

Public Sub test(p As Project)
Dim t As Task, d As TaskDependency
For Each t In p.Tasks
Debug.Print t.ID & "[" & t.UniqueID & "] : " & t.Name
t1 t, ""
Next
End Sub

Called with Test Activeproject

This code will not walk past an external task. What's strange is that the
Unique IDs of the external tasks are different when you look at them as
predecessors from when you look at them directly. In fact, Project
seems
to
keep 2 tasks for each external task, the real task and the ghost. If I could
access the real task from the ghost, I could get that task's predecessors
and move through the project. The problem is that I can't find any way to
get to the real task from the ghost except by using the task name to access
the task in the subproject (as in:
Projects(d.from.project).tasks(d.from.name)). This is a problem because
there's no way to be sure that tasks have unique names.

Does anyone have a suggestion/solution here?

Thanks,

Bill B
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top