Taha Ahmad
Taha Ahmad

Reputation: 559

VSTO: MS Project - Calculating the ID for child tasks performance issues/workaround

I have a database that contains a list of Tasks. I am using VSTO to read from this database and create a new Microsoft Project out of it. The upper limit for the Tasks is 3000.

The problem is that the records in the database are in random order. Sure, they have a parent child relationship defined in the form of a primary-foreign key in the same table. However, there are 2 restrictions:

  1. I must read all the records in one go.
  2. The order in which the record is read can be completely random.

The 2nd issue is where the real problem happens. Since it is likely that I might get all the OutlineLevel = 1 records first, followed by some OutlineLevel = 5 records, then some Outline Level = 2 and so on and so forth (completely random).

Since the VSTO API is odd in the sense that doing ParentTask.OutlineChildren.Add(<Task>), will create a Child Task of that parent, but will add the TASK to the LAST row of the grid!

This forces me to recompute the IDs for each record that I encounter. With ID, I mean the row number in MS Project on which the record must go.

The problem with this is that if I recompute this for 3000 tasks it gets slower and slower. Towards the start, it is able to insert 30-40 tasks per seconds, but it takes 11 hours to process all 3000 tasks! (This is of course unacceptable).

Is there some API method that will do this quickly? Or is there another way of recomputing the ID for a child task.

Upvotes: 1

Views: 1044

Answers (2)

user2166949
user2166949

Reputation: 26

The COM interface is slow, so the most important thing is to do as much of your processing as possible in your own code, and only after you have a list of tasks in row-order should you insert them into Project.

As for the actual algorithm, I would create a tree structure and as you go through your database I would create a new node not just for the task read but for its implied parent if this has not yet been encountered. So:

Read each record and: Look to see if parent already exists (use a Dictionary for this). If not, create it (and add to the Dictionary). Look to see if task already exists (use same Dictionary for this). If not, create it (and add to the Dictionary). Add task to the parent's list of children.

(Probably more elegant to create a top level task first, and make any task without a parent a child of this top level.)

When finished, traverse the tree in a depth-first way and you have the tasks in row order.

Upvotes: 1

melan
melan

Reputation: 1718

The easiest way to solve the problem is to insert a child task before the 1st task listed in Task.OutlineChildren. But it works only if there are some children tasks already.

The next fast enough solution is to read structure of your project into some data structure in your add-on and scan it instead of calling COM every time. I will just have to update the structure by yourself when you change your project.

And of course if you want to insert just few tasks at the end of a list of their siblings you may scan for the next task with the same OutlineLevel as their parent have and insert before that task.

But anyway caching project structure on mass insert/update is the most reasonable solution.

Upvotes: 0

Related Questions