提问人:2mas 提问时间:10/6/2023 最后编辑:2mas 更新时间:10/10/2023 访问量:135
Excel VBA:将数据从 MS Project 复制到 Excel 并返回
Excel VBA: Copy data from MS Project to Excel and back
问:
我知道您可以使用 MSP 将数据导出到 Excel。 经理仍然希望我编写一个 vba 脚本。
MSP 中有一个计划,Excel 中的一些数据属于一起。来自 MSP 的数据被粘贴到 Excel 中,xlookup 会检查某些值是否更改。只有这样,才允许从计划中启动某些活动。这个过程有法律原因。
过程:
- 用户打开 Excel 并通过单击按钮启动脚本
- 用户选择了正确的 MSP 文件
- MSP 中 A:B 列中的数据通过按钮复制到 A:B 列中(如何使 vba 查找正确的标题名称?MSP中的视图不是固定的,如何正确引用位置?我可以强制 MSP 使用某个自定义视图吗?
- 仅供参考:Xlookup(已经工作)检查是否满足条件,并授予德语“Freigabe erteilt”的权限。权限(用引号引起来)以字符串形式写入单元格中。
- 将 C 列复制到 MSP 中的 C 列(再次:如何使 VBA 找到正确的标题,因为列可以在 MSP 中移动/隐藏,而不是像 excel 中那样具有绝对位置)
奖励 1:对性能改进有什么建议吗? 奖励 2:帮助我改进整个过程,使用 Power BI 还是其他?
截至目前,一切正常,直到我必须将信息从 MSP 复制到 Excel 并返回。 我尝试使用标准的 excel 逻辑,但似乎必须以另一种方式处理 MSP。我困惑何时使用哪种语法
我看到另一个线程有类似的问题,但它侧重于性能,这对我来说是次要的。我也是 Vba 的新手,我仍然很难查看其他解决方案以及如何将它们实现到我的代码中,因为我总是需要更改一些东西,我什至不知道如何搜索它,因为我不知道名称。
Option Explicit
Private Sub DatenAktualisieren()
Dim ProjApp As MSProject.Application ' Microsoft Project Application
Dim ProjFile As Variant ' Path to the Microsoft Project file
Dim ProjSheet As MSProject.Project ' Microsoft Project Worksheet
Dim ExcelBook As Workbook
Set ProjApp = CreateObject("Msproject.Application") **'Bonus1: CreateObject -> GetObject? I read somewhere it can speed up the script, since nothing is visible, which.. I don't know needs more processing power?**
' Paths to MS Project and Excel files
' standard drive is C, this function has to be pointed to the destination: drive X, where all project files are located
ChDrive "X"
ChDir "X:<filepath>"
ProjFile = Application.GetOpenFilename(FileFilter:="Project Files (*.mpp), *.mpp", _
Title:="MS Project Datei auswählen", _
MultiSelect:=False)
If ProjFile = "False" Then 'GetOpenFilename returns boolean, not an object/string/integer, as one might think!
Exit Sub
End If
' Open the MS Project file
If ProjFile <> False Then
ProjApp.FileOpen Name:=ProjFile
Set ProjSheet = ProjApp.ActiveProject
ProjApp.Visible = True
'until now everything works as expected
'copy column a:b from MSP to Excel
' wtf am I doing here?
''''''''
'this is the critical part imho
ProjApp.Range("A1:B5000").Copy
ExcelBook = ThisWorkbook
ExcelBook.Sheet(1).Range("A1:B5000").PasteSpecial
'Copy new Data back from Excel to MSP
ExcelBook.Range("C1:C5000").Copy
ProjApp.Range("C1:C5000").PasteSpecial
'''''''''
End If
' Clean up
Set ProjSheet = Nothing
Set ProjApp = Nothing
End Sub
答:
截至目前,一切正常,直到我必须从 MSP 复制信息 到 Excel 并返回。我试图使用标准的 excel 逻辑,但似乎 MSP必须以另一种方式处理。
是的,由于 MS Project 的用途与 Excel 不同,因此它具有不同的对象模型,并且 Excel 逻辑不适用。要记住的一件关键事情是,Project 中的视图与 Excel 中的不同工作表完全不同。
Project 的基础是任务,它们可以在不同的视图中显示,以不同的顺序显示,经过筛选等。将数据从 Project 复制到 Excel 时,尽量不要将其视为将范围从一个 Excel 文件复制到另一个 Excel 文件。相反,逐个复制任务,或者如果性能有问题,则创建任务数组并将数组复制到 Excel。
下面的代码从项目中复制任务数据,并将其放入 Excel 文件的 A 列和 B 列中。然后,将 C 列中的数据复制回任务。
Private Sub DatenAktualisieren()
Dim ProjApp As MSProject.Application ' Microsoft Project Application
Dim ProjFile As Variant ' Path to the Microsoft Project file
Dim ProjSheet As MSProject.Project ' Microsoft Project Worksheet
Dim ExcelBook As Workbook
' Paths to MS Project and Excel files
' standard drive is C, this function has to be pointed to the destination: drive X, where all project files are located
ChDrive "X"
ChDir "X:<filepath>"
ProjFile = Application.GetOpenFilename(FileFilter:="Project Files (*.mpp), *.mpp", _
Title:="MS Project Datei auswählen", _
MultiSelect:=False)
If ProjFile = "False" Then 'GetOpenFilename returns boolean, not an object/string/integer, as one might think!
Exit Sub
End If
' Open the MS Project file
If ProjFile <> False Then
' if Project is already open, get a reference to it, otherwise open it
On Error Resume Next
Set ProjApp = GetObject(, "MSProject.Application")
If ProjApp Is Nothing Then
Set ProjApp = CreateObject("Msproject.Application")
End If
ProjApp.Visible = True
ProjApp.DisplayAlerts = False
ProjApp.FileOpen Name:=ProjFile
Set ProjSheet = ProjApp.ActiveProject
Set ExcelBook = ThisWorkbook
Dim ExcelSheet As Worksheet
Set ExcelSheet = ExcelBook.Sheets(1)
ExcelSheet.Range("A1:B5000").Clear
' copy data from Project to Excel
Dim fldProcessCode As Long
fldProcessCode= ProjApp.FieldNameToFieldConstant("Process Code")
Dim r As Long
r = 1
Dim tsk As Task
For Each tsk In ProjSheet.Tasks
r = r + 1
ExcelSheet.Cells(r, 1) = tsk.UniqueID ' pick the field you want to put in Column A
ExcelSheet.Cells(r, 2) = tsk.GetField(fldProcessCode) ' pull value from custom field
Next tsk
'Copy new Data back from Excel to MSP
ExcelSheet.Calculate
r = 1
For Each tsk In ProjSheet.Tasks
r = r + 1
tsk.Text1 = ExcelSheet.Cells(r, 3) ' pick the Task field where Column C data should go
Next tsk
End If
End Sub
提示 1:在自动执行其他应用程序(在本例中为 MS Project)时,请始终立即将 Visible 属性设置为 True,以便用户可以响应意外的弹出消息。
提示 2:考虑为项目文件使用不同的变量名称,因为“工作表”在 MS Project 中没有意义。通常,“proj”或“project”可以单独使用,也可以用作前缀或后缀。
提示 3:若要从自定义任务字段(企业字段或具有自定义名称且基础字段名称未知的本地字段)获取值,请使用应用程序对象的 FieldNameToFieldConstant 方法首先获取 FieldID,然后使用 Task 对象的 GetField 方法获取值。
评论
tsk.Text1
评论