如果选择了多于 1 行,但在活动项目上仅运行一个选定的行,则在活动选择上运行宏

问题描述 投票:0回答:1

我有一个宏,旨在确保 MS Project 计划中的行没有重复的名称。目前,这被设计为贯穿整个计划,因此使用:

for each t in ActiveProject.tasks
code
Next t

我发现,如果用户选择了超过 1 个任务的范围,或者通过选择对话框提供此选项,则仅在一组特定任务上运行此选项可能会很好。

如何在不需要复制并粘贴 ActiveSelection 的整个代码集的情况下执行此操作?

完整的代码,以防有人发现它有用或有更好的方法:

Sub task_names_fully_auto_de_dup()
Dim t As Task
Dim t_test As Task
Dim Dups As New Collection

For Each t In ActiveProject.Tasks
    If task_test(t) Then 'check the row is valid (not external or blank)
        For Each t_test In ActiveProject.Tasks
            If task_test(t_test) Then 'check the row is valid (not external or blank)
                'Compare t_test name to t to find dups and add to dups collection
                If t_test.Name = t.Name And t_test.ID <> t.ID Then
                    Dups.Add t.Name  'need to work out how to avoid trying to add the same name more than once
                End If
            End If
        Next t_test
    End If
Next t
 
If Dups.Count = 0 Then
    MsgBox ("No duplicates found")
    Exit Sub
Else 'offer choices for where the summary names will be added
    choice = InputBox("chose where to add the summary names." & vbCrLf & "1 = Before (prefix)" & vbCrLf & "2 = After (Sufix)", "Auto de-duplication of names 1/2", 2)
    If choice = 1 Then 'choose prefix
        Pre = InputBox("Choose which seperator you would like." & vbCrLf & "1 = Space" & vbCrLf & "2 = Dash" & vbCrLf & "3 = Colon", "Adding text to many tasks 2/2", 2)
        Select Case Pre
            Case 1
            Pre = " "
            Case 2
            Pre = " - "
            Case 3
            Pre = ": "
        End Select
    Else
        'chose suffix
        Pre = InputBox("Choose which seporator you would like." & vbCrLf & "1 = Space" & vbCrLf & "2 = Dash" & vbCrLf & "3 = Brackets", "Adding text to many tasks 2/2", 3)
        Select Case Pre
            Case 1
            Pre = " "
            Case 2
            Pre = " - "
            Case 3
            Pre = " ("
        End Select
    End If
End If
 
Dim SummaryName As String
Dim WBS_String() As String
Dim Target_WBS As String
Dim t_wbs As Task

For Each t In ActiveProject.Tasks
    If task_test(t) Then 'checks the row is valid
        Dim item As Variant
        For Each item In Dups
            If t.Name = item Then ' the item is a dup; get the next level up's name
                If InStr(1, t.WBS, ".") <> 0 Then 'if this is the top level we can't get a name
                    WBS_String = Split(t.WBS, ".")
                    ReDim Preserve WBS_String(LBound(WBS_String) To UBound(WBS_String) - 1) 'removes the last element of the WBS
                    Target_WBS = Join(WBS_String, ".") 're-join the WBS into the target WBS to find
                    For Each t_wbs In ActiveProject.Tasks ' find the target WBS and grab the name
                        If task_test(t_wbs) Then
                            If t_wbs.WBS = Target_WBS Then SummaryName = t_wbs.Name
                        End If
                    Next t_wbs
                    't.Name = t.Name & " (" & SummaryName & ")" 'add the Summary name to the task
                    If choice = 1 Then t.Name = SummaryName & Pre & t.Name
                        If choice = 2 Then
                            If Pre = " (" Then
                            t.Name = t.Name & Pre & SummaryName & ")"
                        Else
                            t.Name = t.Name & Pre & SummaryName
                        End If
                    End If
                End If
            End If
        Next item
    End If
Next t
End Sub

Function task_test(t As Task) 'use to replace all the indents
task_test = True
If t Is Nothing Then
    task_test = False
Else
    If t.ExternalTask = True Then task_test = False
End If
End Function
vba ms-project
1个回答
0
投票

为了允许用户在所有任务和选定任务之间进行选择,需要构建一个集合来保存相应的集合。然后重复数据删除代码在该集合上运行。

此代码仅循环执行一次任务,利用集合不能包含重复键的事实来查找重复项。一旦找到重复项,该任务名称的第一个实例将被删除重复,然后是当前的实例。

Sub task_names_fully_auto_de_dup()


    Dim position As String
    Dim separator As String
    
    position = InputBox("chose where to add the summary names." & vbCrLf & "1 = Before (prefix)" _
                    & vbCrLf & "2 = After (suffix)", "Auto de-duplication of names 1/2", 2)
    If Len(position) = 0 Then GoTo ExitSub
    If position = "1" Then
        Dim prefix As String
        prefix = InputBox("Choose which separator you would like." & vbCrLf & "1 = Space" _
                    & vbCrLf & "2 = Dash" & vbCrLf & "3 = Colon", "Adding text to many tasks 2/2", 2)
        If Len(prefix) = 0 Then GoTo ExitSub
        separator = Choose(CSng(prefix), " ", " - ", ": ")
    Else
        Dim suffix As String
        suffix = InputBox("Choose which separator you would like." & vbCrLf & "1 = Space" _
            & vbCrLf & "2 = Dash" & vbCrLf & "3 = Brackets", "Adding text to many tasks 2/2", 3)
        If Len(suffix) = 0 Then GoTo ExitSub
        separator = Choose(CSng(suffix), " ", " - ", " (")
    End If


    Dim answer As VbMsgBoxResult
    answer = MsgBox("Run de-duplication on entire project (Yes) or only selected tasks (No)?" _
        , vbQuestion + vbYesNoCancel, "All tasks or Selected tasks?")
    Dim tsks As Variant
    Select Case answer
        Case Is = vbYes
            Set tsks = ActiveProject.Tasks
        Case Is = vbNo
            Set tsks = ActiveSelection.Tasks
        Case Else
            GoTo ExitSub
    End Select
    
    Dim t As Task
    Dim uniqueTaskNames As New Collection
    Dim tskFirstInstance As Task
    Dim uid As Variant
    
    On Error Resume Next
    For Each uid In tsks
        Set t = ActiveProject.Tasks.UniqueID(uid)
        If Not t.ExternalTask Then
            Err.Clear
            uniqueTaskNames.Add t.UniqueID, t.Name
            If Err.Number <> 0 Then
                Set tskFirstInstance = ActiveProject.Tasks.UniqueID(uniqueTaskNames(t.Name))
                AddPrefixSuffix position, separator, tskFirstInstance
                AddPrefixSuffix position, separator, t
            End If
        End If
    Next uid
    
ExitSub:

End Sub

Sub AddPrefixSuffix(position As String, separator As String, tsk As Task)

    If InStr(tsk.Name, tsk.OutlineParent.Name) = 0 Then
        If position = "1" Then
            tsk.Name = tsk.OutlineParent.Name & separator & tsk.Name
        ElseIf separator = " (" Then
            tsk.Name = tsk.Name & separator & tsk.OutlineParent.Name & ")"
        Else
            tsk.Name = tsk.Name & separator & tsk.OutlineParent.Name
        End If
    End If
    
End Sub
© www.soinside.com 2019 - 2024. All rights reserved.