You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MS-Project文件中存储自定义非任务数据(VSTO插件场景)

嘿,我正好做过类似的VSTO项目加载项开发,给你梳理下实现这个需求的关键步骤和代码示例,应该能帮到你!

核心思路

因为你只需要存储项目每周整体的实际工作量,不需要单个活动的统计数据,最贴合MSP数据结构的方案是:创建一个顶级虚拟汇总任务,然后给这个任务添加时间分段的实际工作量数据。这样既符合MSP的原生逻辑,后续生成挣值图时也能直接调用这些数据,不用额外做统计转换。

实现步骤
  • 第一步:搭建VSTO开发环境
    在Visual Studio里新建「Office/SharePoint」分类下的「Project 2016加载项」项目,选择C#语言,确保引用对应版本的MSP Interop程序集。
  • 第二步:设计数据存储方案
    创建一个名为「项目整体工作量汇总」的顶级汇总任务,专门用来承载每周的整体实际工作量(如果已经存在就复用,不存在则新建)。
  • 第三步:对接外部系统数据
    编写逻辑从你的统计系统拉取按周划分的实际工作量数据,建议封装成包含「周起始日期」和「实际工时」的实体类。
  • 第四步:写入MSP文件
    通过MSP的对象模型,把每周的工作量数据写入到汇总任务的时间分段字段中。
  • 第五步:生成挣值图
    可以直接用MSP自带的「挣值」报告(已经能识别汇总任务的时间分段数据),或者通过VSTO程序化生成自定义样式的图表。
代码示例

1. 引用必要命名空间

using Microsoft.Office.Core;
using Microsoft.Office.Interop.MSProject;
using System;
using System.Collections.Generic;
using System.Windows.Forms;

2. 定义工作量数据实体

// 对应外部系统返回的每周工作量数据结构
public class WeeklyWorkload
{
    public DateTime WeekStartDate { get; set; }
    public double ActualWorkHours { get; set; }
}

3. 获取/创建虚拟汇总任务

private Task GetOrCreateSummaryTask(Project project)
{
    // 先检查是否已存在目标汇总任务
    foreach (Task task in project.Tasks)
    {
        if (task.Name.Equals("项目整体工作量汇总", StringComparison.OrdinalIgnoreCase) && task.OutlineLevel == 1)
        {
            return task;
        }
    }
    // 不存在则创建新的顶级汇总任务
    Task summaryTask = project.Tasks.Add("项目整体工作量汇总");
    summaryTask.Summary = true; // 标记为汇总任务,避免被误操作
    return summaryTask;
}

4. 写入每周实际工作量到MSP

private void WriteWeeklyActualWork(Project activeProject, List<WeeklyWorkload> weeklyData)
{
    Task summaryTask = GetOrCreateSummaryTask(activeProject);
    
    foreach (var workload in weeklyData)
    {
        // 计算周结束日期(假设周一为周起始,周日结束)
        DateTime weekEndDate = workload.WeekStartDate.AddDays(6);
        
        // 操作时间分段的实际工作量字段
        TimeScaleValues timeScaleValues = summaryTask.TimeScaleData(
            StartDate: workload.WeekStartDate,
            EndDate: weekEndDate,
            Type: PjAssignmentTimescaledData.pjAssignmentTimescaledActualWork,
            TimeScaleUnit: PjTimescaleUnit.pjTimescaleWeeks,
            Count: 1);
        
        if (timeScaleValues.Count > 0)
        {
            timeScaleValues[1].Value = workload.ActualWorkHours;
        }
    }
    
    // 保存修改后的项目文件
    activeProject.Save();
    MessageBox.Show("每周实际工作量已成功写入MSP文件!");
}

5. 在加载项启动时调用(示例)

private void ThisAddIn_Startup(object sender, EventArgs e)
{
    // 模拟从外部系统获取的样本数据
    List<WeeklyWorkload> sampleWorkloads = new List<WeeklyWorkload>
    {
        new WeeklyWorkload { WeekStartDate = new DateTime(2024, 5, 6), ActualWorkHours = 135 },
        new WeeklyWorkload { WeekStartDate = new DateTime(2024, 5, 13), ActualWorkHours = 150 },
        new WeeklyWorkload { WeekStartDate = new DateTime(2024, 5, 20), ActualWorkHours = 142 }
    };
    
    // 获取当前打开的MSP项目
    Project currentProject = Application.ActiveProject;
    if (currentProject != null)
    {
        WriteWeeklyActualWork(currentProject, sampleWorkloads);
    }
}
注意事项
  • 单位转换:MSP的工作量默认单位是小时,如果你的外部系统用的是天/分钟等单位,记得提前转换。
  • 权限问题:部署加载项时,要确保用户有修改.mpp文件的权限,尤其是在受保护的系统文件夹下。
  • 计划工作量写入:如果需要把外部系统的计划工作量也导入,可以用同样的逻辑,把数据写入到汇总任务的「基准工时(Baseline Work)」字段中,这样MSP就能自动计算挣值指标。
  • 版本兼容:确保引用的MSP Interop程序集版本和用户的MSP 2016匹配,避免兼容性问题。

内容的提问来源于stack exchange,提问作者Grumpy Curmudgeon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:33:02