求助:如何在Microsoft Project的Timescale中读写任务工时数据?
问题解决:Microsoft Project工时刻度(Timescale)数据的Python读写方案
问题背景
无法在Microsoft Project任务使用视图的工时刻度中提取或写入数据,现有1000+任务需批量导入员工工时表数据,避免手动操作。尝试编写的Python代码逻辑看似正确,但始终无法运行。
原代码的潜在问题
- 枚举常量值错误:原代码中
pjAssignmentTimescaledWork和pjTimescaleDays的数值与MS Project COM对象的实际枚举值不匹配,导致无法正确调用TimescaleData方法。 - COM初始化不严谨:未处理初始化失败的情况,且未确保Project实例正确激活,易引发调用异常。
- 缺少写入逻辑:原代码仅实现读取,未覆盖批量写入工时数据的核心需求。
- 边界检查不足:未处理任务无资源分配、日期为空等特殊场景,易触发报错。
修正后的代码(支持读写)
import pythoncom import win32com.client from win32com.client import constants as ms_const import datetime def init_ms_project(): # 初始化COM环境 pythoncom.CoInitialize() # 创建Project实例 ms_project = win32com.client.Dispatch('MSProject.Application') ms_project.Visible = True return ms_project def open_project(ms_project, file_path): # 关闭已有项目,避免冲突 if ms_project.Projects.Count > 0: ms_project.FileCloseEx(0) # 0 = pjDoNotSave ms_project.FileOpen(file_path) return ms_project.ActiveProject def read_timescale_data(task): """读取任务分配的工时刻度数据""" print(f"任务: {task.Name}") if task.Assignments.Count == 0: print(" 无资源分配") return for assignment in task.Assignments: print(f" 资源: {assignment.ResourceName}") try: # 使用官方枚举常量,避免数值错误 timephased_data = assignment.TimescaleData( StartDate=task.Start, EndDate=task.Finish, TimeScaleUnit=ms_const.pjTimescaleDays, Type=ms_const.pjAssignmentTimescaledWork ) for idx, data in enumerate(timephased_data): print(f" 时间段{idx+1}: {data.StartDate} - {data.EndDate}, 工时: {data.Value}小时") except Exception as e: print(f" 读取失败: {str(e)}") def write_timescale_data(assignment, date_work_dict): """批量写入工时刻度数据:date_work_dict为{日期: 工时(小时)}""" try: # 获取任务全周期的工时刻度集合 timephased_data = assignment.TimescaleData( StartDate=assignment.Task.Start, EndDate=assignment.Task.Finish, TimeScaleUnit=ms_const.pjTimescaleDays, Type=ms_const.pjAssignmentTimescaledWork ) # 遍历时间段,匹配日期并设置工时(MS Project工时单位为分钟,需转换) for data in timephased_data: target_date = data.StartDate.date() if target_date in date_work_dict: data.Value = date_work_dict[target_date] * 60 print(f" 资源{assignment.ResourceName}工时写入完成") except Exception as e: print(f" 写入失败: {str(e)}") if __name__ == "__main__": file_path = r"D:\Manufacturing Resourcing\Test Folder\Test.mpp" # 示例工时数据:替换为实际员工提交的工时表数据 sample_work_data = { datetime.date(2024, 5, 1): 8, datetime.date(2024, 5, 2): 7.5, datetime.date(2024, 5, 3): 8 } ms_project = init_ms_project() project = open_project(ms_project, file_path) # 遍历任务,读取并写入数据 for task in project.Tasks: if task is None or not task.Start or not task.Finish: continue read_timescale_data(task) # 针对有资源分配的任务写入数据(示例:给第一个分配写入数据) if task.Assignments.Count > 0: write_timescale_data(task.Assignments(1), sample_work_data) # 保存项目 ms_project.FileSave() # 清理COM环境 pythoncom.CoUninitialize()
关键注意事项
- 依赖安装:确保已安装
pywin32库,执行pip install pywin32完成安装 - 版本兼容:代码适用于Microsoft Project 2016及以上版本,不同版本需确认枚举值一致性
- 单位转换:MS Project中工时存储单位为分钟,写入时需将小时转换为分钟
- 权限问题:运行代码时需以管理员权限启动Python,避免COM调用权限不足
- 实例冲突:运行前关闭所有Microsoft Project窗口,避免实例冲突导致文件打开失败
内容的提问来源于stack exchange,提问作者user25048319
相关产品推荐
相关产品推荐

