如何在子项目中选择任务的行(在主项目中)

How to SelectRow of a Task in Sub-Project (inside a Master-Project)

我有一个主项目,里面有几个子项目。

我想根据字段的值设置行颜色的格式 Text5

当前问题:如何使用VBA代码引用第二个子项目中的行。 当我 运行 代码并修改任务 ID 5(在子项目 2 中)中的 Text5 值时,它修改了任务 ID 5 的颜色,但修改了子项目 1 的颜色。

如何使用 SelectRow 并添加对所需子项目的引用?

我的代码(相关部分)

Sub FormatChangedTasks()

Dim SubPrj      As Subproject
Dim Tsk         As Task
Dim i           As Long

For Each SubPrj In ActiveProject.Subprojects
    ' compare the name of Sub-Project with the one saved in the "Stack" srray
    If SubPrj.SourceProject.Name = ModifiedPrjName Then
        For Each Tsk In SubPrj.SourceProject.Tasks
            If Not Tsk Is Nothing Then
                i = Tsk.ID

                ' check if Tsk.Text5 value has changed from value in "StatusStackArr" array
                If StatusStackArr(i - 1).StatusOldVal <> Tsk.Text5 Then
                    ' **** at the line below it selects the Row from the top
                    ' (not the desired Sub-Project) ******
                    SelectRow Row:=i, RowRelative:=False

                    ' --format entire row --
                    Select Case Tsk.Text5 ' Get the Field's used field, not name
                        Case "R", "Y", "G"
                            FontEx CellColor:=7, Color:=0
                            FontEx Italic:=False '  Font regular

                        Case "Complete"
                            FontEx Italic:=True '  Font Italic
                            FontEx CellColor:=15, Color:=14 ' Background Silver ; font Gray

                    End Select

               ' rest of code (un-relevant)

挑战——格式化主项目中的一行

要在 table 中设置文本格式,请使用 FontEx method. This method formats the active (selected) cells. To select a row for formatting, use the SelectRow 方法。要使用此方法,您需要了解:

  1. 其相对于活性select离子的位置,或
  2. 其在可见任务
  3. 中的绝对位置
  4. 根据唯一标识符查找任务

对于被过滤器或折叠摘要隐藏的选项 1 和 2 任务意味着必须相应地调整 SelectRow 方法的行参数。很难知道哪些任务可能被隐藏。使用此方法的最佳方法是首先确保所有任务都可见(见代码)。

此外,在处理子项目时,计算绝对行位置是一项挑战,因为首先您需要获得时间表中较高位置的子项目的任务数以及主项目本身中的任何本机任务(尽管这是非典型的)。

所有这些导致使用 Find 方法, 选项 3,作为在主项目 中完成 select 任务的最佳方式。要 select 完全正确的任务,则 Find 方法必须与唯一字段一起使用。唯一 ID 字段是唯一保证唯一的字段。

主项目中的唯一 ID

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

种子值基于内部子项目"index"。第一个子项目的任务的种子值为 4194304,第二个子项目的任务的种子值为 8388608 (4194304 * 2),依此类推。

如果从主项目中删除子项目,则不会重新使用它 "index"。同样,如果子项目在主项目中重新排列,"index" 值不会改变。因此,您不能使用子项目对象的 Index 属性 来获取用于创建种子的内部 "index" 值,因为 属性 只是表示子项目的顺序. (请注意,有一种方法可以获得这个内部值,但这超出了这个问题的范围。仅供参考,它还需要 select 执行所有任务。)

解决方案

要 select 用户界面中的任务,您需要知道它在主计划中的唯一 ID。如果您通过 SourceProject.Tasks 方法访问任务,您将访问其本机子项目中的任务,并且唯一 ID 将不包括种子值。例如,唯一 ID 将为 2,这在主项目中不是唯一的,因此不足以 select 使用查找方法的任务。

由于您已经循环遍历了日程中的所有任务,因此确定主唯一 ID 的最简单方法是循环遍历主项目中的本机任务。为此 select 所有任务并循环 selection。

Sub FormatChangedTasks()

' show all tasks
FilterClear
SelectAll
SummaryTasksShow (0)
OutlineShowAllTasks

Dim AllTasks As Tasks
Set AllTasks = ActiveSelection.Tasks

Dim Tsk As Task

For Each Tsk In AllTasks
    If Not Tsk Is Nothing Then
        ' compare the name of Sub-Project with the one saved in the "Stack" srray
        If Tsk.Project = ModifiedPrjName Then

            ' check if Tsk.Text5 value has changed from prior value
            ' NOTE: use a dictionary here instead of an array
            If StatusStackArr(i - 1).StatusOldVal <> Tsk.Text5 Then

                Find "Unique ID", "equals", Tsk.UniqueID
                SelectRow

                ' --format entire row --
                Select Case Tsk.Text5 ' Get the Field's used field, not name
                    Case "R", "Y", "G"
                        FontEx CellColor:=7, Color:=0
                        FontEx Italic:=False '  Font regular

                    Case "Complete"
                        FontEx Italic:=True '  Font Italic
                        FontEx CellColor:=15, Color:=14 ' Background Silver ; font Gray

                End Select

            ' rest of code (un-relevant)
        End If
    End If
Next Tsk
End Sub

备注:

  • 选择所有任务是一项要求,除非您可以保证日程已经完全展开并且您选择选项 1 或 2。选择所有任务将花费 10-15 个子项目的时间,但其余的代码将 运行 以接近相同的速度。
  • 如果任务已分组或未按任务 ID 排序,则所有选项 1 或 2 均无效。
  • 将以前的值存储在由任务 ID 索引的数组中不适用于主项目。相反,将以前的值存储在以主唯一 ID 作为键的集合或字典中。 See this SO post about using dictionaries in VBA.