挑战 - 设置主项目中的行格式
要格式化表格中的文本,请使用FontEx https://msdn.microsoft.com/VBA/Project-VBA/articles/application-fontex-method-project方法。此方法格式化活动(选定)单元格。要选择一行进行格式化,请使用选择行 https://msdn.microsoft.com/en-us/vba/project-vba/articles/application-selectrow-method-project方法。要使用此方法,您需要了解:
- 它相对于活动选择的位置,或
- 其在内部的绝对位置可见任务, or
- 根据唯一标识符查找任务
对于选项 1 和 2,通过过滤器或折叠摘要隐藏的任务意味着SelectRow
方法必须相应调整。很难知道哪些任务可能被隐藏。使用此方法的最佳方法是首先确保所有任务都是可见的(参见代码)。
此外,在处理子项目时,计算绝对行位置是一个挑战,因为首先您需要获得计划中较高位置的子项目的任务计数以及主项目本身中的任何本机任务(尽管这是非典型的)。
所有这些导致使用Find
方法,选项 3,作为在主项目中选择任务的最佳方式。要准确选择正确的任务,Find 方法必须与唯一字段一起使用。唯一 ID 字段是唯一保证唯一的字段。
主项目中的唯一 ID
将任务添加到项目时,会分配一个增量唯一 ID,从 1 开始。当项目在主项目中组合时,通过添加种子值来更改唯一 ID,以便主项目中不存在重复项。
种子值基于内部子项目“索引”。第一个子项目任务的种子值为 4194304,第二个子项目任务的种子值为 8388608 (4194304 * 2),依此类推。
如果从主项目中删除子项目,则不会重新使用它的“索引”。同样,如果在主项目中重新排列子项目,“索引”值也不会更改。因此,您不能使用Index
子项目对象的属性来获取用于创建种子的内部“索引”值,因为该属性仅指示子项目的顺序。
(注意,有一种方法可以获得这个内部值,但这超出了这个问题的范围。仅供参考,它还需要选择所有任务。)
Solution
要在用户界面中选择任务,您需要知道它在主计划中的唯一 ID。如果您通过以下方式访问任务SourceProject.Tasks
您将访问其本机子项目中的任务的方法,并且唯一 ID 将不包含种子值。例如,唯一 ID 将为 2,这在主项目中不是唯一的,因此不足以使用 Find 方法选择任务。
由于您已经循环遍历计划中的所有任务,因此确定主唯一 ID 的最简单方法是循环遍历主项目中的本机任务。为此,请选择所有任务并循环选择。
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
Notes:
- 选择所有任务是一项要求,除非您可以保证计划已完全展开并且您选择选项 1 或 2。对于 10-15 个子项目,选择所有任务将花费一点时间,但其余代码将在关闭时运行以相同的速度。
- 如果任务已分组或未按任务 ID 排序,则选项 1 或 2 的所有选项均无效。
- 将先前的值存储在按任务 ID 索引的数组中不适用于主项目。相反,应将以前的值存储在集合或字典中,并以主唯一 ID 作为键。请参阅这篇有关在 VBA 中使用字典的 SO 帖子。 https://stackoverflow.com/questions/915317/does-vba-have-dictionary-structure