在执行你的代码时,最小化Microsoft Project的主要缺陷是几乎不能给用户提供宏进程的目视反馈。至少在任务视图可见时,屏幕闪烁可表明宏仍在运行。对于宏的时间消耗,用户通常愿意多占用一些时间来换取更好的目视反馈。一种折衷的好方法是创造性地使用伪工程。
创建一个你可用来填充应用程序窗口的伪工程,这样做的好处有两点:一是消除了大量的屏幕重绘;二是提供了显示状态消息的良好中介。为了有效地利用这种方法,你必须先创建一个用来提供状态消息的工程。参考一下提供的STATUS.MPP文件,这个工程中包含一个单任务,并在自定义的名为“Macor Status(宏状态)”的PERT视图处于活动时得以保存。当我们的宏运行时,我们打开这个文件,并利用显示的单任务框来为用户提供状态消息。
为说明这个过程,下面的宏在活动的工程的每个任务中运行两次,先将Flag1字段的值赋为True,再将Flag2字段的值也赋为True。
Sub SetFlagTest3()
Dim tskIndex As Task ' Tasks集合的指数
Dim tskStatus As Task ' 用来显示进程的任务
Dim prjStatus As Project ' 用来显示进程的工程
Dim prjCurrent As Project ' 当前的工程
Set prjCurrent = ActiveProject
FileOpen "status.mpp"
Set prjStatus = ActiveProject
Set tskStatus = prjStatus.Tasks(1)
ActiveWindow.Caption = "Macro Status"
tskStatus.Name = "Now setting task Flag1 fields..."
DoEvents ' 允许刷新视图
For Each tskIndex In prjCurrent.Tasks
tskIndex.Flag1 = True
tskStatus.Name = "Now processing task " & tskIndex.ID
Next tskIndex
tskStatus.Name = "Now setting task Flag2 fields..."
DoEvents ' 允许刷新视图
For Each tskIndex In prjCurrent.Tasks
tskIndex.Flag2 = True
tskStatus.Name = "Now processing task " & tskIndex.ID
Next tskIndex
FileClose pjDoNotSave
End Sub
注意,通过利用Microsoft Project延迟刷新显示的任务框的方法 ,宏可以实现在任务框中显示一条消息,同时在进入栏(entry bar)中显示另一消息。
为确定这些状态消息对宏的性能的实际影响,我们可使用下面的代码:
Sub SetFlagtest4()
Dim tskIndex As Task ' Tasks集合的指数
Dim lBegin As Long ' 计时的开始时间
Dim lEnd As Long '计时的结束时间
Dim lMsgFlag1 As Long ' 在状态消息下,赋值Flag1所用时间
Dim lMinFlag1 As Long ' 在应用程序窗口最小化下,赋值Flag1所用时间
Dim lMsgFlag2 As Long ' 在状态消息下,赋值Flag2所用时间
Dim lMinFlag2 As Long ' 在应用程序窗口最小化下,赋值Flag2所用时间
Dim tskStatus As Task ' 用于显示进程的任务
Dim prjStatus As Project ' 用于显示进程的工程
Dim prjCurrent As Project ' 当前的工程
Set prjCurrent = ActiveProject
FileOpen "status.mpp"
Set prjStatus = ActiveProject
Set tskStatus = prjStatus.Tasks(1)
ActiveWindow.Caption = "Macro Status"
lBegin = GetTickCount()
tskStatus.Name = "Now setting task Flag1 fields..."
DoEvents ' Allows view to refresh
For Each tskIndex In prjCurrent.Tasks
tskIndex.Flag1 = True
tskStatus.Name = "Now processing task " & tskIndex.ID
Next tskIndex
lEnd = GetTickCount()
lMsgFlag1 = lEnd - lBegin
lBegin = GetTickCount()
tskStatus.Name = "Now setting task Flag2 fields..."
DoEvents ' Allows view to refresh
For Each tskIndex In prjCurrent.Tasks
tskIndex.Flag2 = True
tskStatus.Name = "Now processing task " & tskIndex.ID
Next tskIndex
lEnd = GetTickCount()
lMsgFlag2 = lEnd - lBegin
FileClose pjDoNotSave
Application.WindowState = pjMinimized
lBegin = GetTickCount()
For Each tskIndex In prjCurrent.Tasks
tskIndex.Flag1 = True
Next tskIndex
lEnd = GetTickCount()
lMinFlag1 = lEnd - lBegin
lBegin = GetTickCount()
For Each tskIndex In prjCurrent.Tasks
tskIndex.Flag2 = True
Next tskIndex
lEnd = GetTickCount()
lMinFlag2 = lEnd - lBegin
Application.WindowState = pjNormal
MsgBox "Elapsed times with messages:" & Chr(10) & _
"Flag1 - " & lMsgFlag1 / 1000 & " s." & Chr(10) & _
"Flag2 - " & lMsgFlag2 / 1000 & " s." & Chr(10) & _
Chr(10) & "While minimized:" & Chr(10) & _
"Flag1 - " & lMinFlag1 / 1000 & " s." & Chr(10) & _
"Flag2 - " & lMinFlag2 / 1000 & " s."
End Sub
在一个有200个任务的工程中运行这个宏,你可得到下列类似结果:
{bmc ZCK4A.WPG}
注意,在这种情况下提供状态消息大约要增加30%的执行时间。虽然它会大大增加某些工程的执行时间,但用户通常还是愿意接受性能下降来换取持续的目视反馈。
最小直接对象处理
改善Microsoft Project 宏的性能的另一种方法是在可能的地方,使对代码中的对象的直接处理最小化。虽然在执行一些动作时,通常采用整个对象集合中进行迭代的简便方法,但如果使用Microsoft Project 的一些固有特征,将必须检测的对象数量最小化,则比迭代法快得多。下面是这项技巧的示例。
在本示例中(取自Project Metrics 应用程序),为确定是否有资源分配给任务,必须检测工程中的每个任务。下列代码段是通过检查分配给当前工程的任务集合中每个任务的资源数量来实现的:
' 给每个尚未分配任何资源的任务分配伪资源
tassign = 0
For Each t In ActiveProject.Tasks
If Not (t Is Nothing) Then
If t.Resources.Count < 1 Then
If tassign > 1000 Then Error err_assign_limit
t.Assignments.Add ResourceID:=oNewRes.ID
tassign = tassign + 1 'keeps track of the 'number of assignments made
End If
End If
Next t
前面的代码是有效的,但下面的示例会运行得更快。这两个示例的区别在于,后一个示例设置了一个任务过滤器,它可筛选出分配了资源的任务。这个筛选操作非常快,并可改善程序的性能达300%以上。
将常量cpts_nores_filter定义为任务过滤器,方法如下:
Field Name Test Value(s) And/Or
Resource Names Equals And
Milestone Equals No And
Summary Equals No
tassign = 0
FilterApply cpts_nores_filter
SelectAll
If Not ActiveSelection.Tasks Is Nothing Then
For Each t In ActiveSelection.Tasks
With t
If tassign > 1000 Then Error err_assign_limit
.Assignments.Add ResourceID:=oNewRes.ID
tassign = tassign + 1 'keeps track of the number of 'assignments made
End With
Next t
End If
1995 Microsoft 公司。
这些材料是仅为信息用途而提供的“原样”,微软公司和微软的供应商都不对这些材料的内容或此处包含的任何信息的正确性作出明确的或隐含的保证,包括不对某些特殊目的的商业性和适用性作出不加限制的隐含保证。上述限制不适用于某些不允许排除隐含保证的州/管辖区。
无论是微软公司还是微软的供应商都不对任何后续的、偶然的、直接的、间接的、特殊的损害或利益损失负任何责任。上述限制不适用某些不允许排除后续或偶然损害的州/管辖区。在任何情况下,微软及其供应商对由于这些材料引起的全部责任(不管是以侵权的、合同性的还是以任何其他方式引起)不得超过这些材料的建议零售价。
[此贴子已经被作者于2005-1-21 21:41:45编辑过] |