2015-06-20 5 views
5

Mam kolekcję, której używam, aby mieć mapę String -> MailItem. Wypełniam mapę, a kiedy znajdę zduplikowany klucz, chcę przeczytać przedmiot w Kolekcji.Dlaczego nie mogę uzyskać elementu z kolekcji i zapisać go w zmiennej?

Wydaje się to łatwe, ale spędziłem ponad godzinę próbując dowiedzieć się, dlaczego nie mogę przypisać elementu kolekcji do zmiennej lokalnej. (Patrz PROBLEM w kodzie poniżej)

oMailOther = cMails.Item(cMailKey) "obiekt Zmienna lub zmienna bloku nie ustaw"

Set oMailOther = cMails.Item(cMailKey) "Object required"

Drugi cMails(cMailKey) forma daje ten sam błąd. Przenoszenie Dim wokół nie robi żadnej różnicy. cMails musi być dostępny, ponieważ jest używany wcześniej w metodzie. Zwróć uwagę na linię Debug.Print tuż przed tym stwierdzeniem, , która działa pod numerem. czego mi brakuje?

Option Explicit 
Option Compare Text 

Public cMails As Collection 

Public Sub GetOutlookAttachments() 
    Set cMails = New Collection 

    Dim oStore As Store 
    For Each oStore In Session.Stores 
     If oStore.DisplayName = "Outlook Data File" Then 
      ProcessFolder oStore.GetRootFolder() 
     End If 
    Next 
End Sub 

Private Sub ProcessFolder(oFolder As Folder) 
    Debug.Print oFolder.FolderPath 
    ProcessItems oFolder.Items 

    Dim oSubFolder As Folder 
    For Each oSubFolder In oFolder.Folders 
     ProcessFolder oSubFolder ' recurse 
    Next 
End Sub 

Private Sub ProcessItems(oItems As Items) 
    Dim oItem As Object 
    For Each oItem In oItems 
     DoEvents 
     If TypeOf oItem Is MailItem Then 
      Dim oMail As MailItem 
      Set oMail = oItem 
      Dim cMailKey As String 
      cMailKey = oMail.ConversationID & "-" & oMail.ConversationIndex 
      If Not Contains(cMails, cMailKey) Then 
       cMails.Add oMail.Subject, cMailKey 
      Else 
       Debug.Print cMails.Item(cMailKey) 
       Dim oMailOther As MailItem 
PROBLEM  oMailOther = cMails.Item(cMailKey) 
       Debug.Print cMailKey & ": " & oMailOther.Subject 
      End If 
     ElseIf TypeOf oItem Is MeetingItem Then 
      ' ignore 
     Else 
      Debug.Print "oItem Is a " & TypeName(oItem) 
     End If 
    Next oItem 
End Sub 

Public Function Contains(col As Collection, key As Variant) As Boolean 
    Dim obj As Variant 
    On Error GoTo err 
    Contains = True 
    obj = col(key) 
    Exit Function 
err: 
    Contains = False 
End Function 

Próbowałem też powtórzyć podobny Add i Item połączenia gdzie indziej i działa.

Public Sub Test() 
    Set cMails = New Collection 

    Dim cMailKey As String 
    cMailKey = "hello" 
    cMails.Add Session.Stores.Item(1), cMailKey 

    Debug.Print cMails(cMailKey) 
    Dim oStore As Store 
    Set oStore = cMails(cMailKey) 
    Debug.Print oStore.DisplayName 
End Sub 
+1

Spróbuj użyć 'CreateObject (" Scripting.Dictionary ")' zamiast 'Collection'. Słownik ma natywną metodę '.Exists()', więc nie będziesz potrzebować 'funkcji zawiera()'. – omegastripes

+0

@ Homegastripes Wiem, ale ta część działa dobrze, w przeciwnym razie nie dotarłaby do linii 'PROBLEM'. Nie chcę dodatkowych zależności. – TWiStErRob

+0

Nie jestem pewien, czy uznałbym 'Scripting.Dictionary' za problematyczną zależność - wymagałoby to pracy * nie * by była dostępna na maszynie docelowej. – Comintern

Odpowiedz

6

skopiowane kod i prowadził ją. Utworzona kolekcja cMails to zbiór Strings, a nie obiektów poczty; jednak oMailOther jest zadeklarowany jako Object typu MailItem.

W zadaniu bez słowa kluczowego Set, VB skarży się, że chce coś przypisać do obiektu (po lewej stronie) i powinien użyć słowa kluczowego Set. Teraz, wraz z kluczowych Set, VB skarży się, że po prawej stronie nie jest obiektem ...

Aby cMails do colection przesyłek pocztowych, zmień oświadczenie Add następująco:

cMails.Add oMail, cMailKey 

(czyli nie dodać oMail.Subject ale cały oMail Object).

teraz użyj słowa kluczowego Set w Set oMailOther = cMails.Item(cMailKey) i wszystko działa poprawnie.

+0

Jak to widzisz: "to zbiór ciągów"? (poza zauważeniem '.Subject' w' .Add'). – TWiStErRob

+0

Ustawiłem Watch na 'oMail' i sprawdziłem przedmiot (y) i zobaczyłem, że były one strunami, jak inni zauważyli poprzez analizę. –

+0

To jest tak dziwne, że nie może powiedzieć "Wymagany MailItem", jak większość normalnych języków (InvalidCastException, ClassCastException). – TWiStErRob

2

oMailOther jest MailItem, więc bez pytania należy użyć Set co przypisanie go do zmiennej:

Set oMailOther = cMails(cMailKey) 

Jednak kolekcji cMails nie zawiera MailItem obiekt. Zawiera tylko tematy (które są ciągami w przeciwieństwie do obiektów), które wcześniej dodałeś z .

Podobno miałeś na myśli cMails.Add oMail, cMailKey.

1

Problemem nie jest to, jak jesteś pobierania elementy, to jak masz dodanie im:

If Not Contains(cMails, cMailKey) Then 
    cMails.Add oMail.Subject, cMailKey 
Else 

Collection.Add jest pierwszym parametrem jest to, czego są przechowywane w zbiorach - w w tym przypadku Temat. Gdy próbujesz pobrać elementy z kolekcji tutaj ...

Debug.Print cMails.Item(cMailKey) 
Dim oMailOther As MailItem 
MailOther = cMails.Item(cMailKey) 
Debug.Print cMailKey & ": " & oMailOther.Subject 

... próbujesz pobrać sam obiekt. Debug.Print działa, ponieważ masz kolekcję wypełnioną napisami.

Jeśli potrzebujesz kolekcję MailItem, trzeba wypełnić go tak:

cMails.Add oMail, cMailKey 
Powiązane problemy