2016-08-29 12 views
2

我有一個WBS(工作分解結構),具有多行(組大綱的頂級),每個頂級行是一個活動。直接參與活動是涉及的角色。使用VBA中的默認數組來填充Excel中的WBS大綱

根據頂層活動的值(例如,「計劃」),根據其在另一工作表上的相關表格中的值(「默認值」選項卡)填充以下級別的單元格, 。

當前,活動(對應於角色)下的行正在進行醜陋的索引/匹配查找,該數值乘以25個角色,可能會導致電子表格停頓。

什麼我認爲將解決這個問題是採取角色默認值表,把它放在一個持久數組,並重復使用數組中的值,因爲用戶放入頂級活動。我只是無法弄清楚如何讓數組持久化(因此VBA不會在用戶更改單元格時重新填充它)。如果「角色默認值」表中的值發生更改,我可以使用工作表OnChange處理該值,所以這不是問題。

WBS Expanded Activity Rows, to show Roles

第3行「活動1」是活動行的樣子同組的輪廓崩潰。

第4-9行是活動行的樣子,擴展了組大綱,顯示了基本角色。

Role Defaults

對於每個角色,這是所使用來查找應該在WBS選項卡上的相應的活性/角色單元中的值的另一標籤中的表格。

+0

'我只是不知道如何使數組持久化 - - 通過在模塊級別聲明它而不是過程級別。再次,你可能應該修復醜陋的查找,因爲我不知道它絕對是醜陋的。 – GSerg

+0

謝謝@GSerg。醜陋的查找的一個大問題是,我必須執行角色默認查找,加上基於其他標準的其他計算,這需要活動#。我的最終目標是將Worksheet_Change函數更改爲僅折回頂部活動行,並重用角色默認數組來填充角色,而不是活動周下的每個單元格的當前INDEX/MATCH。 –

回答

0

每當需要查找時,我都會使用Dictionary對象。在我的解決方案中,我使用嵌套字典返回頂層和活動的組合。 (注:我試着儘可能地瞭解你的業務需求,但我確信我沒有認識到它,我還假設了一些關於初學者水平的VBA知識,如果你有問題,請問我們會盡力幫助)。

首先,創建一個新的模塊來容納全球可用的Dictionary。這不能是Worksheet模塊。 (在VBE中,轉到插入 - >模塊)。在模塊的最頂端,創造一個子程序之前就宣佈一個公開的Dictionary

Public oDictWbs As Object 

我們只希望這本字典的一個實例,所以我喜歡用Singleton狀的圖案,如果已經創建了返回Dictionary如果沒有,則創建並返回一個新的。 (注意:我將計算出的例程返回到RefreshWBS,以便它可以用於根據您的業務規則創建新字典。例如,在默認工作表OnChange事件中,您可以調用RefreshWBS [code重用總是很有趣])。

Private Function GetWBS() As Object 
    If Not oDictWbs Is Nothing Then 
     Set GetWBS = oDictWbs 
     Exit Function 
    End If 

    Set GetWBS = RefreshWBS() 
End Function 

Private Function RefreshWBS() 
    Dim sDefault As Worksheet 
    Dim rTopLevels As Range 
    Dim rActivities As Range 
    Dim rIterator As Range 
    Dim rInnerIter As Range 

    Set oDictWbs = Nothing 
    'Both variables below establish the range that stores the fixed info (the default worksheet) 
    'Instead of hard coding in the range, create your own logic based on your needs and rules 
    Set sDefault = Sheets("Default") 
    Set rTopLevels = sDefault.Range("B1:C1") 
    Set rActivities = sDefault.Range("A3:A4") 

    Set oDictWbs = CreateObject("Scripting.Dictionary") 

    For Each rIterator In rTopLevels 
     If Not oDictWbs.exists(rIterator.Value) Then 
      Set oDictWbs(rIterator.Value) = CreateObject("Scripting.Dictionary") 
     End If 

     For Each rInnerIter In rActivities 
      If Not oDictWbs(rIterator.Value).exists(rInnerIter.Value) Then 
       oDictWbs(rIterator.Value)(rInnerIter.Value) = sDefault.Cells(rInnerIter.Row, rIterator.Column) 
      End If 
     Next rInnerIter 
    Next rIterator 

    Set RefreshWBS = oDictWbs 

End Function 

最後,我們創建一個可以從工作表本身進行訪問,使用戶能夠在WBS字典訪問信息的功能。您可以輸入Excel單元格中的一個函數,如=GetWbsActivityTime(B1, A4),假定單元格B1包含頂級描述符,A4描述該活動。只要該值在字典中,它就會返回與其相關的值。

Function GetWbsActivityTime(sTopLevel As String, sActivity As String) As Variant 
    Dim oDict As Object 

    Set oDict = GetWBS() 

    If Not oDict.exists(sTopLevel) Then 
     GetWbsActivityTime = CVErr(xlErrRef) 
     Exit Function 
    End If 

    If Not oDict(sTopLevel).exists(sActivity) Then 
     GetWbsActivityTime = CVErr(xlErrRef) 
     Exit Function 
    End If 

    GetWbsActivityTime = oDict(sTopLevel)(sActivity) 
End Function 

我知道這是一個很大的吸收,所以審查,並讓我知道的任何問題或與怪癖,我可以提供幫助。另外,如果我完全錯過了練習的要點,請告訴我,我會看看我們是否可以挽救部分解決方案。

+0

謝謝@ user3561813。我沒有使用字典,所以我很欣賞這個機會。我覺得一些澄清可能有所幫助:「角色默認值」表包含角色(列A),活動(第3行)和它們的值(A3:O37)的三維表。這用作用戶輸入的描述符(例如「Plan」,「Wkshp」等)的查找,並輸入到WBS選項卡上的相應角色。我會查看是否可以修改您的代碼以使用我的特定方案。 –

+0

我還在抓我的頭,你是怎麼做到的,但是當我用默認角色替換你的Set rTopLevels = sDefault.Range(「B1:C1」)和Set rActivities = sDefault.Range(「A3:A4」)時行頭範圍,第一列範圍,它的作品!我可以假設嵌套字典的功能就像創建3D數組一樣,函數GetWbsActivityTime使用頂級(標題)和活動(角色)來獲取交集值? –

+0

@RobS這正是它所做的。 rTopLevels是第一個關鍵的查找。 (計劃,Wkshp等)。其中每一個都有自己的基礎字典和自己的密鑰(Proj Manag。,Proj Manag - Offshore等)。當用戶從主字典中選擇「計劃」時,函數指向包含在「計劃」中的子字典。如果用戶指向「Proj Mana」作爲第二個參數,它將跳轉到關鍵字段並返回值。如果您有任何問題,請隨時詢問。 – user3561813