Application.SelectRow selecting the wrong row

S

Stephan Steiner

Hi

I've written a software to automatically publish certain tasks. I have the
TaskUID of the tasks I need to publish so I iterate through the tasks in a
project once opened, and compare Task.UniqueID with the UIDs I have. If I
have found the proper UID, I call Application.SelectRow(Task.ID, false,
Missing.Value, Missing.Value, true)

When I tested the software, that seemed to work fine. However, now one week
after going into service, I was informed about a case (I can't say for sure
if it's the only one.. I think I've seen some other stuff that was off.. but
by one line which is not that much of a problem because I don't think the
summary task needs to be published explicitly anyway) where I select 4 lines
for publishing, but the resource got to see just two (the summary task and
one of the actual tasks).

In stepping through the code, I have confirmed that I definitely give the
proper parameters to Application.SelectRow (the Task.ID corresponds to the
line number in project client) - however, what then happens is that the line
Task.ID + 3 is selected. Needless to say that's not the line I want to
select.

Is there anything that could explain this behavior and how can I prevent it
from happening?

Regards
Stephan
 
S

Stephan Steiner

As if this wasn't enough, it gets even better.. the delta is project
dependant. If I open another project that I'm automatically publishing (one
of the productive ones.. I never saw the issue in the development projects
anyway), there's no delta.

I moved the app back to the dev machine and put a breakpoint before the line
selection so I can follow what is going on with each project.

Regards
Stephan
 
J

John

Stephan Steiner said:
Hi

I've written a software to automatically publish certain tasks. I have the
TaskUID of the tasks I need to publish so I iterate through the tasks in a
project once opened, and compare Task.UniqueID with the UIDs I have. If I
have found the proper UID, I call Application.SelectRow(Task.ID, false,
Missing.Value, Missing.Value, true)

When I tested the software, that seemed to work fine. However, now one week
after going into service, I was informed about a case (I can't say for sure
if it's the only one.. I think I've seen some other stuff that was off.. but
by one line which is not that much of a problem because I don't think the
summary task needs to be published explicitly anyway) where I select 4 lines
for publishing, but the resource got to see just two (the summary task and
one of the actual tasks).

In stepping through the code, I have confirmed that I definitely give the
proper parameters to Application.SelectRow (the Task.ID corresponds to the
line number in project client) - however, what then happens is that the line
Task.ID + 3 is selected. Needless to say that's not the line I want to
select.

Is there anything that could explain this behavior and how can I prevent it
from happening?

Regards
Stephan

Stephan,
Ah the old selectrow gotcha. First of all, when using Project's
SelectRow statement, the row argument is NOT the row ID, rather it is
the number of the visible rows in the active view. For example, let's
say you have a filtered view that shows task IDs 28, 29 & 30. If you
then use the statement, SelectRow row:=1, rowrelative:=false, the result
will select the first visible row or in this case, task ID 28.

But wait, it gets even better. Let's say you have selected the option to
show the Project Summary Task. Now the row numbering starts at row "0".
So if you use the same statement as above, the result will now be
selection of the second visible row, or task ID 29. In this case the
rowrelative argument is essentially null and void.

It just doesn't get any more fun than this.

John
Project MVP
 
S

Stephan Steiner

John

Stephan,
Ah the old selectrow gotcha. First of all, when using Project's
SelectRow statement, the row argument is NOT the row ID, rather it is
the number of the visible rows in the active view. For example, let's
say you have a filtered view that shows task IDs 28, 29 & 30. If you
then use the statement, SelectRow row:=1, rowrelative:=false, the result
will select the first visible row or in this case, task ID 28.

But wait, it gets even better. Let's say you have selected the option to
show the Project Summary Task. Now the row numbering starts at row "0".
So if you use the same statement as above, the result will now be
selection of the second visible row, or task ID 29. In this case the
rowrelative argument is essentially null and void.

It just doesn't get any more fun than this.

Is there a way to avoid this? When I have the two plans side by side, they
appear the same (both show the project summary task), and there is no filter
set.

Is there a way to programmatically determine which offset would be needed to
make sure the right line is marked? E.g. something like calling
SelectRow(1) - then get the active row (is there a command to do that?), and
from that information figure out the relative line number difference between
the absolute line number that you want to have selected, and what line
number that translates to in the current view?

Regards
Stephan
 
J

Jan De Messemaeker

Hi Stephan,

There's probably a lot of better ways but this one works:
Selectall
for ctr=1 to activeselection.tasks.count
if activeselection.tasks(ctr).id=TheIDyoulookfor Then
set MyDearestTask=activeselection.tasks(ctr)
end if
next ctr

Greetings,
 
J

John

Stephan Steiner said:
John



Is there a way to avoid this? When I have the two plans side by side, they
appear the same (both show the project summary task), and there is no filter
set.

Is there a way to programmatically determine which offset would be needed to
make sure the right line is marked? E.g. something like calling
SelectRow(1) - then get the active row (is there a command to do that?), and
from that information figure out the relative line number difference between
the absolute line number that you want to have selected, and what line
number that translates to in the current view?

Regards
Stephan

Stephan,
I forgot to ask why you want to use a direct select method to select
certain tasks. It is much easier and more efficient to work with Project
data in background mode. That is, operate directly on Project's objects,
independent of what is displayed in the current view.

Some things must be done using foreground processing (direct selection)
but that should be the exception, not the rule. Jan provided a code
snippet of the most common way foreground processing might be used but
unless you are working with a filtered or grouped view, it is not a very
efficient approach. Don't get me wrong, I'm not knocking Jan's
suggestion. In fact I use it often in my macros, but again, only when
I'm working with a filtered or grouped set of tasks. When working with
an unfiltered or ungrouped project file the most efficient construct is:

Dim t as Task
For Each t in ActiveProject.Tasks
If Not t is Nothing Then
[your code here]
End If
Next t

John
Project MVP
 
S

Stephan Steiner

Well, what I really want to do is publish a number of tasks..

looking at the VBA documentation, I figured this would serve me best:

Application.PublishNewAndChangedAssignments(false, pjPublishScopeSelected,
false, Missing.Value)

So, I need to select the tasks I want to publish, then call the above
statement. I have the UIDs of all the tasks I want to publish.. so that's my
starting point (I could also get the absolute line number if absolutely
necessary though I prefer to use UIDs since line numbers may not always be
static). So, do you see a better way for me to publish only a handful of
tasks?

Regards
Stephan

P.S. I'm currently interating over tasks using the C# equivalent code from
what John indicated.. I loop over all tasks, compare the UID with the UID I
have "on file", and if it's a line I'm interested in, I'm trying to select
it so that I can later publish just the selected lines.
 
J

John

Stephan Steiner said:
Well, what I really want to do is publish a number of tasks..

looking at the VBA documentation, I figured this would serve me best:

Application.PublishNewAndChangedAssignments(false, pjPublishScopeSelected,
false, Missing.Value)

So, I need to select the tasks I want to publish, then call the above
statement. I have the UIDs of all the tasks I want to publish.. so that's my
starting point (I could also get the absolute line number if absolutely
necessary though I prefer to use UIDs since line numbers may not always be
static). So, do you see a better way for me to publish only a handful of
tasks?

Regards
Stephan

P.S. I'm currently interating over tasks using the C# equivalent code from
what John indicated.. I loop over all tasks, compare the UID with the UID I
have "on file", and if it's a line I'm interested in, I'm trying to select
it so that I can later publish just the selected lines.

I forgot to ask why you want to use a direct select method to select
certain tasks. It is much easier and more efficient to work with Project
data in background mode. That is, operate directly on Project's objects,
independent of what is displayed in the current view.

Some things must be done using foreground processing (direct selection)
but that should be the exception, not the rule. Jan provided a code
snippet of the most common way foreground processing might be used but
unless you are working with a filtered or grouped view, it is not a very
efficient approach. Don't get me wrong, I'm not knocking Jan's
suggestion. In fact I use it often in my macros, but again, only when
I'm working with a filtered or grouped set of tasks. When working with
an unfiltered or ungrouped project file the most efficient construct is:

Dim t as Task
For Each t in ActiveProject.Tasks
If Not t is Nothing Then
[your code here]
End If
Next t

John
Project MVP

Stephan,
If I were doing it, it would probably use a combination of foreground
and background processing. I would first use the loop I suggested along
with some type of lookup table to set a flag field for all tasks with
the desired UID. Then I would apply a filter for that flag field and use
a loop construct similar to what Jan proposed to select the tasks for
publishing.

If the file is very large and I only need to identify a few UIDs for
publishing, I might use the Find Method for setting the flag instead of
looping through all tasks looking for the desired UID. It's a tradeoff.

John
Project MVP
 

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