在 MS Project 中,使用 VBA,我想根据 excel 文件的内容在自定义字段之间移动数据

In MS Project, using VBA, I want to move data between custom fields based on the contents of an excel file

提问人:Miles 提问时间:11/8/2023 更新时间:11/9/2023 访问量:84

问:

我想移动各种自定义字段的内容,例如 Text1 -> Text2,然后是 Text3 -> Text1。

我可以使用VBA中的一系列条目来做到这一点: 子transfer_test_1()

Dim t As Task

For Each t In ActiveProject.Tasks
    t.Text2 = t.Text1
    t.Text1 = ""
Next t

CustomFieldRename FieldID:=pjCustomTaskText1, NewName:="test Field"

End Sub

但是,使用 Excel 工作表作为翻译的来源会更优雅。我使用前面的答案作为打开Excel工作表并将其读取到数组中的基础,以便我可以遍历数组。

Sub GetValuesFromExcel()
'from https://stackoverflow.com/questions/66766996/how-to-pull-project-info-from-excel-into-ms-project-using-a-ms-project-macro

'code uses early binding to the Excel object library so you'll need to set a reference to
'that file (Tools Menu: References, check the box for the Microsoft Excel Object Library).


    Dim xl As Excel.Application
    Set xl = CreateObject("Excel.Application")
    xl.Visible = True
    
    Dim wbk As Excel.Workbook
    Set wbk = xl.Workbooks.Open("C:\Users\miles\OneDrive\Field Translations.xlsx", UpdateLinks:=False, ReadOnly:=True)
    
    Dim Dept As String
    Dim Customer As String
    Dept = wbk.Worksheets("Sheet1").Range("A2")
    Customer = wbk.Worksheets("Sheet1").Range("B2")
    
    'count how many rows
    lastrow = ActiveSheet.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
    'lastrow = Worksheets("Sheet1").Range("A1000").End(xlUp).Row
    
    Dim DataArray As Variant
    DataArray = Worksheets("Sheet1").Range("A2:d" & lastrow)
    
    wbk.Close False
    xl.Quit
    For r = 1 To lastrow - 1
        For c = 1 To 4
            Debug.Print DataArray(r, c)
        Next c
    Next r
Dim t As Task

For Each t In ActiveProject.Tasks
Debug.Print "test of progress: " & t.ID & " - " & t.Name
    For r = 1 To lastrow - 1
        t.DataArray(r, 2) = t.DataArray(r, 1)
        t.DataArray(r, 1) = ""
    Next r
Next t
'For r = 1 To lastrow - 1
'    CustomFieldRename FieldID:=pjCustomTask & DataArray(r, 2), NewName:=DataArray(r, 4)
'Next r

    'ActiveProject.ProjectSummaryTask.SetField FieldNameToFieldConstant("Project Departments"), Dept
    'ActiveProject.ProjectSummaryTask.SetField FieldNameToFieldConstant("Customer"), Customer
    
End Sub

代码失败,我怀疑它正在“读取”为 t。text2“ = t.”text1“不起作用,但这只是一个猜测!t.DataArray(r, 2) = t.DataArray(r, 1)

谁能建议我如何做到这一点?这种“优雅”的解决方案比将所有翻译直接输入VBA花费更多时间!但是,尝试自动化时经常会出现这种情况,所以我宁愿不放弃!:)

非常感谢。

Excel VBA 集成 MS-Project

评论

0赞 CDP1802 11/8/2023
什么是工作表上的列,其中之一是任务 ID 吗?A:D
0赞 Miles 11/8/2023
A 列是源字段 (Text1),C 列是目标字段 (text2),C 是源字段的新名称,D 是目标字段的新名称。通过这种方式,我可以定义需要发生的各种转移。
0赞 CDP1802 11/8/2023
我不是 MSProject 专家,但猜您需要确定字段 id 并用于该值。like 和.GetField(id)fldno1 = FieldNameToFieldConstant("Text1") : myValue =myTask.GetField(fldno1)myTask.SetField(fldno2,myValue)
0赞 Rachel Hettinger 11/8/2023
@Miles “但是,使用 Excel 工作表作为翻译的来源会更优雅。”Excel 是为每个任务的这些字段提供新值,还是提供映射(例如,对于每个任务,将 Text1 移动到 Text4,将 Text3 移动到 Text1)?
0赞 Miles 11/8/2023
@RachelHettinger后者,代码是在自定义字段之间移动值。理想情况下,它会重命名自定义字段以匹配已移动的数据(如第一个代码片段所示),但是我在 excel 版本上还没有走得那么远。

答:

1赞 Rachel Hettinger 11/8/2023 #1

我想移动各种自定义字段的内容,以便 实例 Text1 -> Text2,然后 Text3 -> Text1。

使用 Excel 工作表作为 翻译。

此代码将打开一个 Excel 文件,以获取将数据从一个字段移动到另一个字段(列 A 和 C)的映射。然后,它根据 Excel 文件中 B 和 D 列中的信息重命名字段。

Sub GetMappingsFromExcel()
    
    Dim xl As Excel.Application
    Set xl = CreateObject("Excel.Application")
    xl.Visible = True
    
    Dim wbk As Excel.Workbook
    Set wbk = xl.Workbooks.Open("C:\Users\miles\OneDrive\Field Translations.xlsx", UpdateLinks:=False, ReadOnly:=True)

    Dim wst As Excel.Worksheet
    Set wst = wbk.Worksheets("Sheet1")
    
    Dim Dept As String
    Dim Customer As String
    Dept = wst.Range("A2")
    Customer = wst.Range("B2")

    Dim lastrow As Long
    lastrow = wst.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
    
    Dim Remapping As Variant
    Remapping = wst.Range("A2:D" & lastrow)
    
    ' Column A is the source field (eg Text1)
    ' Column B is the new name for the source field
    ' Column C is the destination field (eg Text2)
    ' Column D is the new name for the destination
    
    
    wbk.Close False
    xl.Quit
    
    Dim fldIDs() As PjField
    ReDim fldIDs(lastrow - 1, 2)
    Dim idxMap As Integer
    For idxMap = 0 To lastrow - 2
        fldIDs(idxMap, 0) = FieldNameToFieldConstant(Remapping(idxMap + 1, 1))
        fldIDs(idxMap, 1) = FieldNameToFieldConstant(Remapping(idxMap + 1, 3))
    Next idxMap
    
    Dim t As Task
    For Each t In ActiveProject.Tasks
        For idxMap = 0 To lastrow - 2
            t.SetField fldIDs(idxMap, 1), t.GetField(fldIDs(idxMap, 0))
        Next idxMap
    Next t


    For idxMap = 0 To lastrow - 2
        CustomFieldRename FieldID:=fldIDs(idxMap, 0), NewName:=CStr(Remapping(idxMap + 1, 2))
        CustomFieldRename FieldID:=fldIDs(idxMap, 1), NewName:=CStr(Remapping(idxMap + 1, 4))
    Next idxMap

    'ActiveProject.ProjectSummaryTask.SetField FieldNameToFieldConstant("Project Departments"), Dept
    'ActiveProject.ProjectSummaryTask.SetField FieldNameToFieldConstant("Customer"), Customer
    
End Sub

sample Excel file with field mappings

评论

0赞 Miles 11/9/2023
这太棒了;我开始理解你做了什么:)我将包括一个检查任务是否为空。现在我需要在此基础上运行组织者来传输字段公式、过滤器等,我将开始运行!谢谢。