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

如何通过VSTO插件将员工工时导入Microsoft Project的TimeScaleData

工时导入Microsoft Project的报错修复方案

核心报错原因

Assignments.Add抛出System.Runtime.InteropServices.COMException的直接原因是新创建的任务未设置有效时间范围——Microsoft Project要求任务必须有明确的开始/结束日期才能创建资源分配,否则会判定参数无效。此外代码中还存在变量初始化不规范的潜在问题。

分步修复

1. 为任务设置有效时间范围

创建任务后,立即将Phase的BaselineStart和BaselineFinish赋值给任务的Start和Finish属性,确保任务有合法的时间区间:

Task newPhaseTask = project.Tasks.Add(phase.Name);
// 绑定任务时间范围,解决分配创建的核心限制
newPhaseTask.Start = DateTime.Parse(phase.BaselineStart);
newPhaseTask.Finish = DateTime.Parse(phase.BaselineFinish);

2. 修复assignmentExists变量初始化问题

遍历员工的每个工时日期前,必须重置assignmentExists为false,否则第一次检测到分配存在后,后续循环会持续跳过创建逻辑:

foreach (var date in emp.EntryDates)
{
    bool assignmentExists = false; // 每次循环重新初始化
    foreach (Assignment assignment in newPhaseTask.Assignments)
    {
        if (assignment.Resource.Name.Equals(resource.Name, StringComparison.OrdinalIgnoreCase))
        {
            assignmentExists = true;
            break;
        }
    }
    // 后续创建分配或更新工时的逻辑
}

3. 优化资源查找逻辑(可选)

用LINQ简化资源查找代码,提升可读性:

Resource resource = project.Resources.Cast<Resource>()
    .FirstOrDefault(r => r.Name.Equals(emp.Name, StringComparison.OrdinalIgnoreCase));
if (resource == null)
{
    resource = project.Resources.Add(emp.Name);
}

4. 修正TimeScaleData的工时赋值逻辑

Project的工时单位默认是分钟,且TimescaleValues集合的Add方法并非直接传入日期和小时,正确方式是修改对应日期的Value值:

TimescaleValues tsValues = targetAssignment.TimeScaleData(
    date.DateEntered, 
    date.DateEntered, 
    PjAssignmentTimescaledData.pjAssignmentTimescaledWork, 
    PjTimescaleUnit.pjTimescaleDays, 
    1);
if (tsValues.Count > 0)
{
    // 将小时转换为分钟,匹配Project的工时单位
    tsValues[1].Value = date.Hours * 60;
}

完整修复代码

Project project = Globals.ThisAddIn.Application.ActiveProject;
Task newPhaseTask = project.Tasks.Add(phase.Name);
// 设置任务有效时间范围
newPhaseTask.Start = DateTime.Parse(phase.BaselineStart);
newPhaseTask.Finish = DateTime.Parse(phase.BaselineFinish);

foreach (Employee emp in Employees)
{ 
    // 查找或创建对应资源
    Resource resource = project.Resources.Cast<Resource>()
        .FirstOrDefault(r => r.Name.Equals(emp.Name, StringComparison.OrdinalIgnoreCase));
    if (resource == null)
    {
        resource = project.Resources.Add(emp.Name);
    }

    // 检查是否已存在该资源的任务分配
    bool assignmentExists = false;
    Assignment targetAssignment = null;
    foreach (Assignment assignment in newPhaseTask.Assignments)
    {
        if (assignment.Resource.Name.Equals(resource.Name, StringComparison.OrdinalIgnoreCase))
        {
            assignmentExists = true;
            targetAssignment = assignment;
            break;
        }
    }

    // 不存在则创建新分配
    if (!assignmentExists)
    {
        targetAssignment = newPhaseTask.Assignments.Add(resource);
    }

    // 为每个日期写入工时数据
    foreach (var date in emp.EntryDates)
    {
        TimescaleValues tsValues = targetAssignment.TimeScaleData(
            date.DateEntered, 
            date.DateEntered, 
            PjAssignmentTimescaledData.pjAssignmentTimescaledWork, 
            PjTimescaleUnit.pjTimescaleDays, 
            1);
        if (tsValues.Count > 0)
        {
            tsValues[1].Value = date.Hours * 60;
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 17:27:46