About Those Pesky Unique IDs - AronGahagan/cpt-dev Wiki

The below is obsolete. Subproject UID must be derived from Subproject Task Masked UID at run-time.

Table of Contents

  1. Assignment Unique IDs
  2. Assignment Unique IDs in a Master Project
  3. Master Project Unique IDs

Assignment Unique IDs

  • The displayed Assignment Unique ID in the Task Usage view is off by 2^20 (or 1,048,576)1: [displayed assignment UID] = [assignment UID returned via VBA] - 1048576 or [displayed assignment UID] = [assignment UID returned via VBA] - (2 ^ 20). Note that in 64 bit versions of Office VBA, exponents must be written as 2 ^ 20 (note spacing) and not 2^202.
  • Oddly, in a standalone project file, you can reference a particular Assignment in VBA using either the displayed UID or the UID returned via VBA.
  • Further, and incredibly, you can pass any Assignment UID to the Assignments object of any other task in the file and manipulate the values. (This confirms earlier suspicions that Assignments are stored as a separate object/table/collection in a normalized RDBMS, but that object/table/collection is not directly exposed via VBA.)

1: https://stackoverflow.com/a/42334614/3481213

2: https://stackoverflow.com/questions/51264287/vba-power-operator-not-working-as-expected-in-64-bit-vba

Assignment Unique IDs in a Master Project

  • The displayed assignment UID in a master project is the result of the formula: [master assignment UID] = (([inserted project summary UID] + 1) * 4194304) + [source assignment UID]
  • The [inserted project summary UID] can be derived: lngInsertedUID = ActiveProject.Subprojects(oTask.Project).InsertedProjectSummary.UniqueID where oTask is the parent of the oAssignment under scrutiny.
  • The [source assignment UID] can be derived by: lngAssignmentSourceUID = [displayed assignment UID] Mod 4194304 or, if you're extracting the Assignment UID by VBA, lngAssignmentSourceUID = oTask.Assignments(1).UniqueID - (2 ^ 20).
  • The Assignment UID returned by VBA is high by 1,048,576 (or 2^20) but is the same whether in the standalone project or the master project. However, in a master project, you cannot reference a particular Assignment in VBA using the UID returned by VBA. It must be referenced by the displayed [master assignment UID].
  • The [master assignment UID] can then be calculated: [master assignment UID] = ((lngInsertedUID + 1) * 4194304) + lngAssignmentSourceUID - and it is this value that must be passed to oTask.Assignments.UniqueID(lngAssignmentMasterUID) in order to operate on a particular assignment with certainty that you're targeting the exact Assignment in view.

Master Project Unique IDs

  • The displayed Unique ID in a master project is the result of the formula: [master task UID] = (([inserted project summary UID] + 1) * 4194304) + [source task UID]
  • To get the [inserted project summary UID], where oLink is a TaskDependency object, oTask is a Task object and the task whose predecessor you're trying to find, use oLink.From.Project. If oLink.From.ExternalTask = True then you'll need to clean up the result.
...
If oLink.To.Guid = oTask.Guid Then 'limit to predecessor(s)
    strProject = oLink.From.Project 'returns server project with "<>\" or a file path
    If oLink.From.ExternalTask = True Then
        strProject = Replace(strProject,".mpp","") 'strips the file extension, if it exists
        strProject = Mid(strProject,InstRev(strProject,"\")-1) 'strips off the path for local or server paths
    End if
    lngInsertedUID = ActiveProject.Subprojects(strProject).InsertedSummaryTask.UniqueID
...
  • Note that you need to get lngInsertedUID--whether oLink.From.ExternalTask = True or not--in order to derive the [master task UID].
  • To get the [source task UID]: If oLink.From.ExternalTask = True then oLink.From.UniqueID refers not to the "giver" task UID in the external project, but to the UID of the ghost task in the "receiver" project. Use oLink.From.GetField(185073906) Mod 4194304. If oLink.From.ExternalTask = False then you can use oLink.From.UniqueID.
    If oLink.From.ExternalTask Then
        lngLinkSourceUID = oLink.From.GetField(185073906) Mod 4194304
    Else
        lngLinkSourceUID = oLink.From.UniqueID
    End If
  • Finally, to get the [master task UID] of the Predecessor, use:
    lngLinkMasterUID = ((lngInsertedUID + 1) * 4194304) + lngLinkSourceUID 
  • Now you can execute a Find or refer to the Predecessor by its Unique ID as it exists in the Master Project in your code (ActiveProject.Tasks.UniqueID(lngLinkMasterUID)). (EditGoTo will not work, though, because it relies on a Task's ID...which is useless in a Master/Sub situation.)
⚠️ **GitHub.com Fallback** ⚠️