【问题标题】:Is there a way to get a subproject's seed value programmatically?有没有办法以编程方式获取子项目的种子值?
【发布时间】:2021-04-24 04:27:29
【问题描述】:

我目前正在为 MS Project 编写 VBA 宏。我想遍历集成主文件(包含链接子项目的文件)中的所有任务并写入任务的原始唯一 ID 值。我知道插入的子项目会获得一个“种子”值(4194304 的倍数),并且集成文件中所有任务的 UID 都成为种子值 + 原始 UID 值

如果我想得到一个任务的原始UID,我怎么知道子项目的种子值是多少?我尝试使用任务所属项目对象的 Index 属性,然后将其乘以 4194304,但 Index 属性似乎并不总是返回正确的子项目索引值。

Sub test()

Dim t As Task
Dim subProjIndex As Integer
Dim originalUID As Long
Dim baseSeedVal As Long

baseSeedVal = 4194304

For Each t In Application.ActiveProject.Tasks
    subProjIndex = Application.Projects(t.Project).Index 'does not always give me the correct subproject index value
    originalUID = t.UniqueID - (baseSeedVal * subProjectIndex)
Next t

End Sub

【问题讨论】:

    标签: vba ms-project


    【解决方案1】:

    这里有两个独立的问题,1) 帖子正文中的问题和 2) 帖子标题。

    如果我想获取任务的原始 UID...

    这个答案很简单:

    originalUID = t.UniqueID Mod 4194304
    

    有没有办法以编程方式获取子项目的种子值?

    有时需要找到子项目任务的唯一 ID,因为它在主项目中。这主要出现在处理外部链接时(例如,任务的前任或继任者在不同的项目中)。

    此代码填充一个字典,其中包含每个子项目的名称和基本主 uid。给定本机任务 uid,这允许您通过其主任务 uid 在主项目中找到该任务。

    Dim SubProjects As New Scripting.Dictionary
    
    Const MasterUidSeed = 4194304
    
    Function GetSubProjectInfo(ByVal prj As MSProject.Project) As Scripting.Dictionary
    
        ShowAllTasks
    
        Dim Subs As New Scripting.Dictionary
        Dim SubProj As Subproject
        
        For Each SubProj In ActiveProject.SubProjects
    
            Application.Find "Unique ID", "equals", SubProj.InsertedProjectSummary.UniqueID
            Application.SelectCellDown
    
            Dim UIDBase As Long
            UIDBase = (Application.ActiveCell.Task.UniqueID \ MasterUidSeed) * MasterUidSeed
    
            Subs.Add SubProj.SourceProject.Name, UIDBase
    
        Next
    
        Set GetSubProjectInfo = Subs
    
    End Function
    
     Sub ShowAllTasks()
    
        ' expands all tasks to make sure all collapsed subprojects are loaded; presumes a task view is active
        With Application
            .SummaryTasksShow (True)
            .FilterClear
            .SelectAll
            .OutlineShowAllTasks
            .SelectBeginning
        End With
    
    End Sub
    

    请参阅SO post,了解如何在 VBA 中使用字典。

    有关主项目任务 uid 如何工作以及为什么使用子项目索引会导致意外结果的更多信息:

    主项目中的唯一 ID

    将任务添加到项目时,会分配一个递增的唯一 ID,从 1 开始。当项目在主项目中合并时,唯一 ID 会通过添加种子值来更改,这样主项目中就不会出现重复项项目。

    种子值基于内部子项目“索引”。第一个子项目的任务的种子值为 4194304,第二个子项目的任务的种子值为 8388608 (4194304 * 2),以此类推。这个“索引”不同于子项目的Index property,它指的是子项目在主项目中的当前位置。

    如果子项目从主项目中删除,它的“索引”不会被重新使用。同样,如果子项目在主项目中重新排列,“索引”值不会改变。因此,您不能使用子项目对象的 Index 属性来获取用于创建种子的内部“索引”值,因为该属性仅指示子项目的顺序。

    【讨论】:

    • 瑞秋,谢谢你的回答。因此,从您的代码 sn-p 用主 UID 种子填充字典,我收集到插入项目摘要任务正下方的任务 UID 始终对应于子项目插入主项目的数字顺序,对吗?即使源项目中该摘要行的 UID 可能不同?如果不是,那么要获得 Master UID 种子,我认为您需要向下舍入到最接近的整数。
    • 项目摘要任务将在主计划中具有本机 UID(例如,较低的数字),但其自身的任务将根据添加子项目时分配的种子在主计划中具有新的 UID。通过确保所有任务都可见并展开,项目摘要任务下方的任务将成为子项目的一部分,除非子项目为无任务。一旦我们找到该任务,我们就可以使用整数除法来推断种子。
    • 对,所以我从您的回答中查看这一行: UIDBase = (Application.ActiveCell.Task.UniqueID \ MasterUidSeed) * MasterUidSeed 所以如果 Application.ActiveCell.Task.UniqueID 返回的值不是 MasterUidSeed 值的偶数倍,在除以 MasterUidSeed 之后,我们需要向下舍入到最接近的整数,然后再乘以 MasterUidSeed,对吗?
    • 这就是整数除法的作用——它会丢弃小数部分。见https://mathworld.wolfram.com/IntegerDivision.html
    猜你喜欢
    • 2022-12-20
    • 2012-10-21
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    • 2017-04-05
    • 2011-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多