使用 VSTO 将数据加载到 Microsoft Project 时如何提高性能

How to Improve Performance when Loading Data into Microsoft Project with VSTO

背景

我们有一个现有的应用程序,可以将数据加载到 Microsoft Project 中,以便可以由 MS Project 进行操作。

原应用是针对MS Project 2003 / 2007的VB6编写的老式COM Project插件,现计划迁移到针对MS Project 2013 / 2016的VSTO插件。

问题

对于他们的 COM 加载项解决方案,我们遇到了性能问题:

Testing project has 4414 activities (av_activity table) and 8330 relationships (av_reln table).

Performance issues were reported during Load operation:

Load time on MSP 2003 template for above project is apprx: 30-35 mins.

Load time on MSP 2007 & 2010 template is > 3hrs

对于 VSTO 解决方案,它变得更好,但我们仍然希望可以通过某种方式提高加载性能。

到目前为止我们已经尝试了什么

我们试了好几个招都收效不大...

寻求帮助

我正在寻求有关在使用 VSTO 加载项和 C# 将数据加载到 MS Project 时提高性能的任何解决方案的帮助。

提前致谢!

是的,使用 TaskDependencies.Add 方法创建关系非常慢。

这很不幸,因为这是合乎逻辑的使用方法。 唯一的解决方法是提前构建 Predecessor 列表。获得该列表后,您可以通过两种方式创建关系:

  • 添加到现有计划
  • 通过导入包含前置任务列表的任务数据创建新计划

由于您的数据已经是表格形式,因此使用项目导入向导从 csv 或 Excel 文件导入它效果很好。 要使用项目导入向导,select csv 或 Excel 文件从 MS Project 中打开(文件 -> 打开)。该向导将引导您完成创建导入映射的步骤,您可以将其保存以供以后自动化使用。 在您的导入数据中包含 Predecessors 列,向导将在几秒钟内为您创建关系。

任务 Predecessors field 包含逗号分隔的前置任务列表。每个前辈的格式如下:

  • 任务 ID
  • 关系类型(FS、FF、SS、SF)
  • 滞后 (+/- #d)

具有 FS 类型且没有滞后的前任任务仅显示任务 ID。以下是前置字段值的一些示例:

  • 14,126,127
  • 73,92SS
  • 144FS+3d,145

如何从 table 关系中创建前置字段值

假设 table 关系包含前任和继任者的任务 ID:

  1. 创建一个包含整数键(后续任务 ID)和字符串值(前置任务)的字典。
  2. 遍历关系的table,将后续的任务ID和它的前置任务添加到字典中;如果它已经存在,更新值以附加逗号和前导。
  3. 遍历字典并 A) 更新 csv 文件中的前任列 B) 在后继者上设置前任字段日程中的任务。

如果您正在使用您的数据创建一个新项目,您可以使用 MPXJ 生成一个 Microsoft 项目 XML 文件(MSPDI 文件),然后您可以直接在 Project 中打开该文件。

如果我理解这个问题,你说将 4000 多个任务放入 MS Project 大约需要 30 分钟。我不确定您所说的 8000 种关系是什么意思;你是说 predecessors/successors 吗?也许你可以澄清一下?因此,您拥有的是一个由 3 个组件组成的系统:数据源、传输机制和 MS Project 本身;正确吗?

这个表现让我很吃惊。我编写了一些 VBA 代码(见 post 的底部)来测试添加 4000 个具有不同大纲级别的任务的性能 + 前辈和我的系统(Proj 2016,Intel i7,Win 10)它花了添加任务最多 100 秒。这告诉我 Project 中没有瓶颈。我怀疑瓶颈在您的数据源或传输机制中。

为了证实这一点,也许您可​​以尝试将所有任务(您称它们为 activity)数据添加到一个任务的注释中 属性,然后看看您的表现如何。 A 如果速度很快,那么也许可以尝试添加 4000 个任务但不带任何属性(名称除外),然后逐步添加更多属性,直到找到哪些属性添加速度慢-吃下。从我下面的测试来看,使用 task.predecessors 属性 增加了 6 倍的性能降低,其余的影响可以忽略不计;您可能会遇到另一个降低性能的属性。 B 但是,如果将您的任务数据添加到一个任务的笔记中仍然很慢,那么您可能是数据源或传输机制有问题。也许您一次发送一个任务(即 activity),而不是构建一个批次?无论如何,隔离问题并消除它。

祝你好运!

Sub add4000tasks()

On Error Resume Next

Dim myTask As task
Dim myProject As Project
resPool = Split("Allice,Bob,Claire,Dave", ",")

For testRun = 0 To &HF '00001111

    testPreds = testRun And &H1 '00000001
    testOutlines = testRun And &H2 '00000010
    testDurations = testRun And &H4 '00000100
    testAssignments = testRun And &H8 '00001000

    If testPreds Then Debug.Print "Testing Predcessors"
    If testOutlines Then Debug.Print "Testing Outlines"
    If testDurations Then Debug.Print "Testing Durations"
    If testAssignments Then Debug.Print "Testing Resource Assignments"


    Application.Projects.Add
    Set myProject = ActiveProject
    Application.Calculation = pjManual

    starttime = Now

    Set myTask = myProject.Tasks.Add("Task 0")
    For a = 1 To 4000

        Set myTask = myProject.Tasks.Add("Task " & a)

        If testPreds Then
            myTask.Predecessors = Rnd * 10000000 Mod a + 1 'may fail if predecessor is also a parent
        End If

        If testOutlines Then
            If Rnd * 10000000 Mod 10 = 0 And myTask.OutlineLevel < 10 Then
                myTask.OutlineIndent
            ElseIf Rnd * 10000000 Mod 10 = 1 And myTask.OutlineLevel > 1 Then
                myTask.OutlineOutdent
            End If
        End If

        If testDurations Then
            myTask.Duration = Rnd * 10000000 Mod 50 & "d"
        End If

        If testAssignments Then
            myTask.ResourceNames = resPool(Rnd * 10000000 Mod UBound(resPool) + 1)
        End If


    Next

    Application.Calculation = pjAutomatic

    Debug.Print (Now - starttime) * 86400 & vbCrLf

    Application.FileCloseEx (pjDoNotSave)

Next

结束子