Re: 11600 ... and Resource UID = 0 (ignore or use?)

Hi,

Many thanks for the updated DLL. I see there is a fix 11600 MPP first resource in Collection is ignored.

I use a saved XML file as a template when I create a new project. This xml file was saved from MS Project. This includes 1 task and 1 resource by default and neither of the two are visible (as far as I can tell).. I understood the resource and task to hold the defaults for new resources or tasks.

Task UID = 0 = project level information

The resource with UID = 0 does not seem to have any information other than the various settings for the resource. I have been ignoring the UID = 0 resource in the same way I ignore the task UID = 0.

given this fix, I am now confused about what to change in my application as I now get a blank resource showing in the resource sheet.

Could you confirm that MS Project (the application) does not have a hidden resource similar to the project level task and that I should remove this from my template ... or there will be a hidden resource in the XML file. (note I'm only using XML files at this point).

I would appreciate a quick reply on this as I have started a beta test with the XML version.

Regards, Bruce

Hi, Bruce,


We understand, that some people who made some adaptation to the functionality before meet some troubles here. The MS Project requires a resource with UID = 0 (if you have any), but allways ignores it. So you had to create some dummy resource to keep your own first resource alive:).

Now, CalcResourceUids() starts numeration from 1 not from 0. But during export to xml the library checks do you have the resource with UID=0, and if not it just add it to xml file (not to you project). The same way the CalcResourceAssignmentUids()starts numeration from 1. Fortunatly, here we don’t need to add a dummy assignment.

So, if you have calculated UIDs for your resources by yourself, you don’t need to add the dummy resource, it will be added automatically. Also, you can add it by yourself, nothing will be changed in this case.

Hi,

My problem is not adaptation of the functionality - its about how MS Project saves an empty project.

I have created the following .MPT file with a blank project by saving an empty project (as I do not want to handle the initialisation of all of the MS Project settings).

MS Project created a resource and task with UID = 0.

I am concerned that you will not be preserving the UID = 0 for resources if MS Project creates one with UID = 0.

My request was that you check the default save functionality of MS Project and be consistent with that. I do not want to be responsible for resources appearing by accident.

Regards, Bruce

Hi,

To clarify... I add resources like this..

Dim presNew As Aspose.Tasks.Resource = New Aspose.Tasks.Resource(MSP_Resource_FixTitle(vstrTitle))

'may need to copy from a generic resource rather than make this fixed.

presNew.Type = ResourceType.Work

presNew.MaxUnits = 1

presNew.AccrueAt = CostAccrualType.Prorated

'----------end setup.

mprjDocument.Resources.Add(presNew)

mprjDocument.CalcResourceUids()

----------------------------------------------------------------------

All of the other resources are passed through or updated as necessary.

With the new version, I get a blank first resource which I assume was UID = 0.

Regards, Bruce

Hi, Bruce,


In your case, the resources UIDs will be started from 1.
When you export the project to xml the dummy resource with UID=0 will be created as a first resource in the xml (but not to you mprjDocument.Resources collection). MS Project will read all your resources and ignore the first (like root task with UID=0).

You can ignore it as well when you will read the xml back. MS Project needs the resource with UID = 0, which it ignores.

It is the same way as MS Office project exports resources into xml. It always creates an empty one with UID = 0. Just create a project with one resource and export into xml, you will see two of them, the first with UID = 0.

In case you prefer to create the dummy resource by yourself, you can add it by hand after mprjDocument.CalcResourceUids() call. Nothing wil be added to xml in the case.
In the previous version, resource UIDs were started from 0 and MS Project just ignored the first user resource as it ignores everithing with UID = 0.

In case if you want everything as it was before :), just call
ArrayUtils.Apply(
mprjDocument.Resources, new ArrayCounter(0, “Uid”), 0);
instead of
mprjDocument.CalcResourceUids().

But, as I have said before, your first resource will not be loaded into project resources list after loading your xml into MS Project.

Bruce,


For your attention, if dummy resource was added to your resources before by you or you loaded it from xml, do not use CalcResourceUids(). As in the case it gets UID=1 now (the numeration is started from 1) and a new dummy resource will be added to your resources collection while exporting to xml.

Hi,

I'm getting worried ... I thought my application was working ok before this release. I must read existing files created by MS Project or other applications and I work with what I'm given. I have not had missing resources in all of my testing.

Currently, I create an XML file using the template I provided (from MS Project). This includes a resource with UID = 0. Add the necessary resources. Now I get a blank resource in the first position of the resource sheet. this must be the one you have generated on Save. I need to recalculate UID after each add operation to ensure that all added Resources are unique across an existing Plan.

I thought the resource UID = 0 also provided the initial settings for resources - this is why I was careful to ensure this resource was in place.

My application has an interface to MS Project through Automation and the same interface to Aspose.tasks. I have been careful to make sure that the output from the real MS Project was the same as the output from Aspose.tasks. The answers should be identical (and have been ... though I'm having some problems with currency and other localised settings).

I'll be glad to provide more info if this would help (also I'm happy to make my app available if this would help).

Please confirm the purpose of the resource at UID = 0. If this is the basis for new resources in MS Project ... I think this must be left in tact rather than added later. I cannot inject extra resources.

(NOTE: if it is my application that is causing the trouble - apologies in advance).

Regards, Bruce

Hi, Bruce,

Sorry for getting you worried.

Yes, in your case, when you are using a ready MS Project template, you don't need an any additional resource, as MS Project has created it...

Just replace in your code mprjDocument.CalcResourceUids() by ArrayUtils.Apply(mprjDocument.Resources, New ArrayCounter(0, "Uid"), 0). It will calculate resources UIDs from 0 and all will work as before... ArrayUtils is in
Aspose.Tasks.Util namespace.

Pay attention, that CalcResourceAssignmentUids() now starts the numeration from 1 too, but not any empty assignments will be added. In case, you want to keep your assignments numeration as it was before, use ArrayUtils.Apply(mprjDocument.ResourceAssignments, New ArrayCounter(0, "Uid"), 0) instead of CalcResourceAssignmentUids().

Sorry for troubles, I have made for you. This is because, in some cases, e.g. when you develop the project from scratch, the root resource has to be added, in some - not.

May be we have to add a parameter, like CalcResourceUids(int start), to cover all cases.
Thank you for your attention and feedback. Hope it will resolve the problem.

Hi,

If the UID = 0 resource is already in the template, and CalcResourceUIDs starts from 1, why does Aspose.Tasks add another resource? It doesn't seem to detect that I already have a resource with UID = 0. I am getting a new resource added.

I have searched the entire help file and do not see any documentation on the ArrayCounter object. Is this a standard .net function? or a new algorithm? I'm not able to try your suggestion as I cannot find the documentation about this function.

I also find the documentation on the Calc functions to be light. For example, I am counting on the Calc functions to leave already assigned UIDs the same after loading and only recalculate new tasks or resources to give them unique ids. I need UIDs to remain the same across multiple read / write operations both from MS Project and my application. In other words, Unique must be unique for the lifetime of a resource or task (this appears to be true on the MS Project side). (NOTE: The ID value changes as the order changes ... so this can change as required.)

How does CalcResourceUIDs or CalcTaskUIDs actually work? I would like to only use these functions to handle UIDs. For example, I would expect it to find the highest UID and assign the next numbers to tasks or resources with unassigned UIDs.

I need to understand this area before I make changes in the app - even if this means stopping the beta test for the application. This is critical. I'll be happy to provide any other info about the extra resource as required.

Regards, Bruce

Hi, Bruce,
Sorry for delay, I just have created a working example for you.
In case, if you don't want to change UIDs of resources you have loaded before you can not use CalcResourceUIDs (and CalcTaskUIDs).
CalcResourceUIDs makes resource UID equal to its order in the project resource collection.

It was before, now the numeration starts with 1, so it's a resource number + 1.
In your case, the code below can work:
Imports System.IO
Imports Aspose.Tasks

Module Module1

Sub Main()
Dim project As Project
Dim projectReader As ProjectReader
Dim newResource As Resource

projectReader = New ProjectReader()

Using fileStream As New FileStream("project.xml", FileMode.Open, FileAccess.Read)
project = projectReader.Read(fileStream)
End Using

Console.WriteLine("Before:")
For Each res As Resource In project.Resources
Console.WriteLine(String.Format("Name = {0}, UID={1}", res.Name, res.Uid))
Next res

newResource = New Resource("New resource")
newResource.Type = ResourceType.Work
newResource.MaxUnits = 1
newResource.AccrueAt = CostAccrualType.Prorated

newResource.Uid = NextResourceUid(project)

project.Resources.Add(newResource)

Console.WriteLine("After:")
For Each res As Resource In project.Resources
Console.WriteLine(String.Format("Name = {0}, UID={1}", res.Name, res.Uid))
Next res


Console.WriteLine("Press any key to exit.")
Console.ReadKey()
End Sub

Function NextResourceUid(ByVal project As Project) As Integer
NextResourceUid = 0
For Each res As Resource In project.Resources
If res.Uid >= NextResourceUid Then
NextResourceUid = res.Uid + 1
End If
Next res
End Function

End Module

As a variant, you can calculate the maximum of uids once after loading data and increment it after each adding.

Hi,

Thanks again for the feedback and sample. Are you sure you are handling UIDs the way MS Project handles them?

For example, if I insert a task in the middle of the plan and calculate the UIDs, I get the feeling that anything after the inserted task will have it's UIDs changed.

I understand the IDs will change - I did not expect the UIDs to change.

Am I the only one worried about this? Do I need to manage UIDs for tasks, resources and assignments separately? it makes retrieving a task or resource by UID a bit uncertain ... The question is - how unique is a Unique ID?

This functionality does not feel quite right to me. It's not been clear in the documentation how it works. Have I missed something? Thanks for the clarification.

Regards, Bruce

Bruce,


Of course, we don’t know exectly how MS Project creates UIDs, it looks that nobody is going to say us:)

I think they keep the next UID value in the mpp metadata (for all types of data) just incrementing it by 1 when you creat the next one. But in xml there are not such fields, so the algorithm have to be close to my sample.

UIDs generated by CalcResorceUIDs are unique as, in fact, they are resources numbers in the collection. In case, you are creating them from scratch this all what you need. The only problem was with UID = 0, but now it is resolved. They will be unique and in your case, but some old values can be updated.

You have, more over, MS Project has, to manage UIDs for tasks, resources and assignments separately. But UID has to be unique only for one type of data. For example, root task has UID equal to 0, by the same way as the empty resource. In my file, generated by MS Project 2003, I have a calendar, a task, a resource and an assignment with UID=1. So it is not a GUID. Of course, all tasks have different UIDs and so on.

Hi,

How do I escalate these problems:

1) I am getting an extra resource when I should not be getting an extra resource. I've given you two files for your testing. Please confirm that you get an extra resource after using the template and then adding some resources. I believe the extra resource should not be generated given your description of the new functions. The resource with UID = 0 should be detected and a new one should not be added.

2) I do not understand the algorithm for CalcResourceUID. Does this only allocate ResourceUIDs to new resources or renumber all resources? If it renumbers all resource UIDs, does it also update any assignment UIDs that might be referencing it. (same for tasks). If it renumbers all existing UIDs, I consider this to be a big risk given the ability for other applications to reference a UniqueID in a project. I cannot take a risk of accidentally renumbering existing UIDs within my application.

The use of UIDs in MS Project is actually very important to understand as these tend to translate to primary keys in databases etc. I would appreciate understanding how these are allocated an maintained in Aspose.Tasks.

Regards, Bruce

Hi Bruce,


1) After CalcResourceUID call you will not have a resource with UID = 0. CalcResourceUID changes all resources UIDs. The new UID will be resource order number in the project resource collection. So if you had 3 resources: Resource0, Resource1, Resource2 (in that order, with any UIDs), after the call Resurce0.UID = 1, Resource1.UID = 2, Resource2.UID = 3. Without matter what the resources UIDs were before.

This why the new resource with UID=0 will be created. You can not use CalcResourceUID in your case now, and you could not use it before if you have wanted to keep old UIDs values.

After CalcResourceUID call and export data into xml you will always get a new resource with UID = 0, as all others resources numbers will be changed in your case.

2) Yes, CalcResourceUID renumbers all resources, but now the numeration is started from 1. In previous version, from 0.

Hi,

Thanks for the answer. I take it it does not automatically check the assignments to ensure they are updated too.

I find this functionality not what I thought it was. I recommend adding a bit more in the help system around this issue for both Tasks and Resources.

Maybe Aspose.Tasks can provide a Max UID (Tasks and Resources) to make it easy to assign the next UID Value to new tasks or resources (or include this in the constructor).

I will now not use the CalcResourceUIDs or CalcTaskUIDs for any operations as I need to preserve the UID information.

I'm glad I found out this now rather than in the middle of beta testing.

Regards, Bruce

Hi,

Answered my own question: I've looked at the assignment object and now remember they are linked to objects not IDs. I was confusing the MS Project Object model.

Regards, Bruce

FYI: This is my understanding ... of UniqueIDs

https://docs.microsoft.com/en-us/office-project/xml-data-interchange/uid-element?view=project-client-2016

I thought the Calc...UID functions used this as a basis for operation.

Regards, Bruce

Hi Bruce,


Yes, you are right. MS Project generates UID at the time you create a task, resource and so on. Calc functions generate UID when you finished the project creation.

We don’t know to which project you are going to add the task in the time you call it’s constuctor:(
You can move tasks from one project to another, or merge them or what ever you want. MS Project knows exactly to what project the task will be added.

I think, we can add a function like NextTaskUID and NextResourceUID to Project class, it will calculate a max of UIDs during file loading and generates next each time you will ask it. For new project all UIDs will start from 0.

Hi,

NextTaskUID and NextResourceUID would be perfect!!!!!!!!!! This is how I was using the calc ...UID functions.

A suggestion to uncouple the calc UID and Resource with UID = 0 ...

Maybe you could add a RootResource object which represents the Resource Object with UID = 0 in a similar way to the RootTask object. This way the handling of the insertion or update to a resource with UID = 0 is not coupled with a Calc function. (it would then be easy to create or ensure a root resource is in the project - in the same way the root task is in the project).

This would also make it easy to use any defaults that might be set in a Root Resource.

Regards, Bruce

Hi Bruce,


A new issue with issue id = 12520 ‘Support NextTaskUID and NextResourceUID methods’ has been created. You will be notified automatically as soon as the issue will be resolved.