通过VBA将任务基线开始和结束日期从MS Project导入Excel

时间:2014-11-10 00:42:43

标签: excel excel-vba ms-project vba

向所有人致意。

我在两个月前面临这个问题而没有解决方案。

我需要通过VBA将MS Project文件的基线开始和完成日期转换为Excel,这是一个有效的算法:

Set Prj = MSProject.Application
Dim tarea As Task

For Each tarea In Prj.ActiveProject.Tasks


Select Case BL

Case "BL0"
    StartD = CDate(Format(tarea.BaselineStart, "dd/mm/yyyy"))
    EndD   = CDate(Format(tarea.BaselineFinish, "dd/mm/yyyy"))

Case "BL1"
    StartD = CDate(Format(tarea.Baseline1Start, "dd/mm/yyyy"))
    EndD   = CDate(Format(tarea.Baseline1Finish, "dd/mm/yyyy"))

Case "BL2"
    StartD = CDate(Format(tarea.Baseline2Start, "dd/mm/yyyy"))
    EndD   = CDate(Format(tarea.Baseline2Finish, "dd/mm/yyyy"))

Case "BL3"
    StartD = CDate(Format(tarea.Baseline3Start, "dd/mm/yyyy"))
    EndD   = CDate(Format(tarea.Baseline3Finish, "dd/mm/yyyy"))
...

...等到BL10;但是这个代码效率极低,并且当Project文件有超过两千个任务行时,需要花费更多的时间来导入日期。

我尝试了在下一个链接中找到的解决方案,只为不同的基线https://social.msdn.microsoft.com/Forums/en-US/c964e627-079e-4296-9e5c-b7c82900d982/project-2010-standard-vba-export-to-excel-latest-baseline?forum=project2010custprog编写一行代码,但结果略有不同,

StartD = tarea.Baseline3Start --> StartD = 11/06/2014 07:00:00 a.m.

StartD = tarea.GetField(Application.FieldNameToFieldConstant("Baseline" & "3" & "Start", pjTask)) --> StartD = "wdn 11/06/14"

使用第二条指令vba没有得到确切的基线日期,它获得了MS Project中显示的字段值,我无法将有效日期值中的最后结果转换为Excel

我还尝试使用Eval()和Evaluate()函数编写一般代码来获取此日期

BLstring = "tarea.Baseline" & "3" & "Start"
Eval(BLstring) --> Error 2409

这是可以理解的,因为此命令不是本机Excel函数

有没有办法在不使用Select case句子的情况下获得这些日期? 或者,可能是,有没有办法执行字符串作为MS Project外部命令来获取这些日期?

任何想法对我都有很大帮助。

编辑#0:最后,在经历了两个月的缓慢而痛苦的痛苦之后,我找到了解决方案。

Andrew Eversight解决方案对我不起作用,因为它采用相同的方法从MSProject获取值...它查找PjFiel枚举值(http://msdn.microsoft.com/en-us/library/ff867782(v=office.15).aspx),它是188744184,以获取字段任务值:

StartD = tarea.GetField(Application.FieldNameToFieldConstant("Baseline" & "3" & "Start", pjTask)) --> StartD = "wdn 11/06/14"

相当于

StartD = Tsk.GetField(tsk_fld_BaselineStart) --> StartD = "wdn 11/06/14"

对于这两种情况,我都可以通过pjFiel编号获得字段值

FieldNameToFieldConstant("Baseline" & "3" & "Start", pjTask) = 188744184
tsk_fld_BaselineStart = pjTaskBaseline3Start = 188744184

tarea.GetField说明其余部分和结果是相同的( "wdn 11/06/14" )

正如Rachel Hettinger所说,GetField方法总是返回一个字符串,由于某种原因我不明白,CDate不会将此结果转换为有效的日期值。

更改应用程序默认日期格式,正如Rachel Heetinger所说,此时它不可靠,我不想修改任何项目文件(此时此刻)。

我可以使用CallByName获取正确的值:

BLstring = "Baseline" & "3" & "Start"

For Each tarea In Prj.ActiveProject.Tasks

    StartD = CallByName(tarea, BLstring, VbGet)
    StartD_aux = tarea.Baseline3Start

...

两条指令都给出了相同的结果( 11/06/2014 07:00:00 a.m. )

亲爱的Andrew和Rachel,感谢您的快速回答和准时帮助。

1 个答案:

答案 0 :(得分:1)

当你有几千行时,性能永远不会很好,但我可以告诉你我做了什么,这是两者的组合。

首先,在开始循环执行任务之前,使用select case语句获取要使用的字段的名称:

Dim tsk_fld_BaselineStart As PjField
Dim tsk_fld_BaselineFinish As PjField

Select Case str_BaselineDestFieldSet

    Case "Baseline"
        tsk_fld_BaselineStart = pjTaskBaselineStart
        tsk_fld_BaselineFinish = pjTaskBaselineFinish
    Case "Baseline1"
        tsk_fld_BaselineStart = pjTaskBaseline1Start
        tsk_fld_BaselineFinish = pjTaskBaseline1Finish
    Case "Baseline2"
        tsk_fld_BaselineStart = pjTaskBaseline2Start
        tsk_fld_BaselineFinish = pjTaskBaseline2Finish

'... and so on

End Select

在变量中捕获这些字段后,当您循环执行任务时,您不必执行那么大的select case语句,或者将字符串转换为字段值,因为它已经完成了:

Dim Tsk As Task
Dim StartD As Date
Dim EndD As Date

For Each Tsk In ActiveProject.Tasks

    StartD = CDate(Tsk.GetField(tsk_fld_BaselineStart))
    EndD = CDate(Tsk.GetField(tsk_fld_BaselineFinish))

    Debug.Print "Task """ & Tsk.Name & """ starts " & StartD & " and ends " & EndD

Next Tsk

确保将StartD和EndD明确声明为日期变量,因为这可能是您收到错误格式的原因。这不是我以前遇到过的问题。 更新11/11: Rachel在评论中澄清了这一点 - 上面的代码已更新为包含日期的CDate功能。

如果要在大型项目中定期使用它,可能需要实现一个进度条来向用户显示它在执行期间的进展情况,因为即使使用此性能增强,也可能需要一些时间才能运行。 / p>