web-dev-qa-db-de.com

Kopieren von Outlook-E-Mail-Nachrichten in Excel mithilfe von VBA oder Makros

Ich bin ein Neuling in VBA und Macros. Wenn mir jemand mit VBA-Code und Makros hilft, ist das hilfreich.

Täglich erhalte ich ca. 50-60 Mails mit einem Standardbetreff: "Aufgabe erledigt". Ich habe eine Regel für alle diese E-Mails erstellt, um sie in einen bestimmten Ordner zu verschieben: "Aufgabe erledigt".

Das Lesen aller 50-60 Mails pro Tag und das Aktualisieren aller Mails ist sehr zeitaufwändig. Alle 50-60 Mails in meinem Posteingang haben den gleichen Betreff, aber von verschiedenen Benutzern. Der Postkörper wird variieren.

Ich verwende Outlook 2010 und Excel 2010.

enter image description here

16
Mallur

Da Sie nicht erwähnt haben, was kopiert werden muss, habe ich diesen Abschnitt im folgenden Code leer gelassen.

Außerdem müssen Sie die E-Mail nicht erst in den Ordner verschieben und dann das Makro in diesem Ordner ausführen. Sie können das Makro für die eingehende E-Mail ausführen und dann gleichzeitig in den Ordner verschieben.

Damit können Sie loslegen. Ich habe den Code kommentiert, damit Sie keine Probleme haben, ihn zu verstehen.

Fügen Sie zuerst den folgenden Code in das Outlook-Modul ein.

Dann

  1. Klicken Sie auf Tools ~~> Rules and Alerts
  2. Klicken Sie auf "Neue Regel"
  3. Klicken Sie auf "von einer leeren Regel aus starten"
  4. Wählen Sie "Nachrichten prüfen, wenn sie ankommen"
  5. Klicken Sie unter Bedingungen auf "mit bestimmten Wörtern im Betreff"
  6. Klicken Sie unter Regelbeschreibung auf "Bestimmte Wörter".
  7. Geben Sie das zu überprüfende Wort in das sich öffnende Dialogfeld ein und klicken Sie auf "Hinzufügen".
  8. Klicken Sie auf "OK" und dann auf "Weiter"
  9. Wählen Sie "in den angegebenen Ordner verschieben" nd auch Wählen Sie "Skript ausführen" im selben Feld
  10. Geben Sie im Feld unten den spezifischen Ordner und auch das Skript (das Makro, das Sie im Modul haben) an, das ausgeführt werden soll.
  11. Klicken Sie auf Fertig stellen und Sie sind fertig.

Wenn die neue E-Mail eintrifft, wird die E-Mail nicht nur in den von Ihnen angegebenen Ordner verschoben, sondern auch in Excel exportiert.

UNGETESTET

Const xlUp As Long = -4162

Sub ExportToExcel(MyMail As MailItem)
    Dim strID As String, olNS As Outlook.Namespace
    Dim olMail As Outlook.MailItem
    Dim strFileName As String

    '~~> Excel Variables
    Dim oXLApp As Object, oXLwb As Object, oXLws As Object
    Dim lRow As Long

    strID = MyMail.EntryID
    Set olNS = Application.GetNamespace("MAPI")
    Set olMail = olNS.GetItemFromID(strID)

    '~~> Establish an Excel application object
    On Error Resume Next
    Set oXLApp = GetObject(, "Excel.Application")

    '~~> If not found then create new instance
    If Err.Number <> 0 Then
        Set oXLApp = CreateObject("Excel.Application")
    End If
    Err.Clear
    On Error GoTo 0

    '~~> Show Excel
    oXLApp.Visible = True

    '~~> Open the relevant file
    Set oXLwb = oXLApp.Workbooks.Open("C:\Sample.xls")

    '~~> Set the relevant output sheet. Change as applicable
    Set oXLws = oXLwb.Sheets("Sheet1")

    lRow = oXLws.Range("A" & oXLApp.Rows.Count).End(xlUp).Row + 1

    '~~> Write to Outlook
    With oXLws
        '
        '~~> Code here to output data from email to Excel File
        '~~> For example
        '
        .Range("A" & lRow).Value = olMail.Subject
        .Range("B" & lRow).Value = olMail.SenderName
        '
    End With

    '~~> Close and Clean up Excel
    oXLwb.Close (True)
    oXLApp.Quit
    Set oXLws = Nothing
    Set oXLwb = Nothing
    Set oXLApp = Nothing

    Set olMail = Nothing
    Set olNS = Nothing
End Sub

FOLLOW-UP

Um den Inhalt Ihres E-Mail-Körpers zu extrahieren, können Sie ihn mit SPLIT () teilen und dann die relevanten Informationen daraus analysieren. Siehe dieses Beispiel

Dim MyAr() As String

MyAr = Split(olMail.body, vbCrLf)

For i = LBound(MyAr) To UBound(MyAr)
    '~~> This will give you the contents of your email
    '~~> on separate lines
    Debug.Print MyAr(i)
Next i
24
Siddharth Rout

Neue Einführung 2

In der vorherigen Version des Makros "SaveEmailDetails" habe ich diese Anweisung verwendet, um den Posteingang zu finden:

Set FolderTgt = CreateObject("Outlook.Application"). _
              GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)

Ich habe seitdem eine neuere Version von Outlook installiert und festgestellt, dass der Standardeingang nicht verwendet wird. Für jedes meiner E-Mail-Konten wurde ein separater Shop (benannt nach der E-Mail-Adresse) mit einem eigenen Posteingang erstellt. Keiner dieser Posteingänge ist der Standard.

Dieses Makro gibt den Namen des Geschäfts mit dem Standardeingang im Direktfenster aus:

Sub DsplUsernameOfDefaultStore()

  Dim NS As Outlook.NameSpace
  Dim DefaultInboxFldr As MAPIFolder

  Set NS = CreateObject("Outlook.Application").GetNamespace("MAPI")
  Set DefaultInboxFldr = NS.GetDefaultFolder(olFolderInbox)

  Debug.Print DefaultInboxFldr.Parent.Name

End Sub

Bei meiner Installation wird Folgendes ausgegeben: "Outlook-Datendatei".

Ich habe dem Makro "SaveEmailDetails" eine zusätzliche Anweisung hinzugefügt, die zeigt, wie auf den Posteingang eines Geschäfts zugegriffen werden kann.

Neue Einführung 1

Einige Leute haben das folgende Makro aufgegriffen, es für nützlich befunden und mich direkt kontaktiert, um weitere Ratschläge zu erhalten. Nach diesen Kontakten habe ich einige Verbesserungen am Makro vorgenommen und die überarbeitete Version unten veröffentlicht. Ich habe auch ein Paar Makros hinzugefügt, die zusammen das MAPIFolder-Objekt für jeden Ordner mit der Outlook-Hierarchie zurückgeben. Diese sind nützlich, wenn Sie nicht auf einen Standardordner zugreifen möchten.

Der Originaltext bezog sich nach Datum auf eine Frage, die mit einer früheren Frage verknüpft war. Die erste Frage wurde gelöscht, sodass der Link verloren gegangen ist. Dieser Link war zu Excel-Tabelle basierend auf Outlook-Mail aktualisieren (geschlossen)

Originaltext

Es gibt überraschend viele Variationen der Frage: "Wie extrahiere ich Daten aus Outlook-E-Mails in Excel-Arbeitsmappen?" Beispielsweise wurden zwei Fragen zu [Outlook-vba] am 13. August gestellt. Diese Frage bezieht sich auf eine Variante aus dem Dezember, die ich zu beantworten versuchte.

Bei der Dezember-Frage ging ich mit einer zweiteiligen Antwort über Bord. Der erste Teil bestand aus einer Reihe von Lehrmakros, die die Outlook-Ordnerstruktur untersuchten und Daten in Textdateien oder Excel-Arbeitsmappen schrieben. Im zweiten Teil wurde das Entwerfen des Extraktionsprozesses erläutert. Für diese Frage hat Siddarth eine exzellente, prägnante Antwort und anschließend ein Follow-up bereitgestellt, um bei der nächsten Etappe zu helfen.

Was der Fragesteller bei jeder Variation nicht verstehen kann, ist, dass die Darstellung der Daten auf dem Bildschirm keine Aussage darüber macht, wie der Text oder der HTML-Textkörper aussieht. Diese Antwort ist ein Versuch, dieses Problem zu überwinden.

Das folgende Makro ist komplizierter als das von Siddarth, aber viel einfacher als die, die ich in meiner Dezember-Antwort angegeben habe. Es könnte noch mehr hinzugefügt werden, aber ich denke, das ist genug, um damit zu beginnen.

Das Makro erstellt eine neue Excel-Arbeitsmappe und gibt ausgewählte Eigenschaften jeder E-Mail im Posteingang aus, um das folgende Arbeitsblatt zu erstellen:

Example of worksheet created by macro

Oben im Makro befindet sich ein Kommentar mit acht Hashes (#). Die Anweisung unter diesem Kommentar muss geändert werden, da sie den Ordner angibt, in dem die Excel-Arbeitsmappe erstellt wird.

Alle anderen Kommentare, die Hashes enthalten, schlagen Änderungen vor, um das Makro an Ihre Anforderungen anzupassen.

Wie werden die E-Mails identifiziert, aus denen Daten extrahiert werden sollen? Ist es der Absender, der Betreff, eine Zeichenkette im Körper oder all dies? Die Kommentare helfen dabei, uninteressante E-Mails zu entfernen. Wenn ich die Frage richtig verstehe, hat eine interessante E-Mail Subject = "Task Completed".

Die Kommentare bieten keine Hilfe beim Extrahieren von Daten aus interessanten E-Mails, aber das Arbeitsblatt zeigt sowohl die Text- als auch die HTML-Version des E-Mail-Körpers an, falls vorhanden. Meine Idee ist, dass Sie sehen können, was das Makro sieht, und mit dem Entwerfen des Extraktionsprozesses beginnen können.

Dies ist im obigen Bildschirmbild nicht dargestellt, aber das Makro gibt zwei Versionen auf dem Textkörper aus. Die erste Version ist unverändert, dh Tabulator, Wagenrücklauf und Zeilenvorschub werden beachtet, und alle nicht umbrochenen Leerzeichen sehen wie Leerzeichen aus. In der zweiten Version habe ich diese Codes durch die Zeichenfolgen [TB], [CR], [LF] und [NBSP] ersetzt, damit sie sichtbar sind. Wenn mein Verständnis korrekt ist, würde ich erwarten, dass im zweiten Textkörper Folgendes enthalten ist:

Aktivität [TAB] Count [CR] [LF] Open [TAB] 35 [CR] [LF] HCQA [TAB] 42 [CR] [LF] HCQC [TAB] 60 [CR] [LF] HAbst [TAB] 50 45 5 2 2 1 [CR] [LF] und so weiter

Das Extrahieren der Werte aus dem Original dieser Zeichenfolge sollte nicht schwierig sein.

Ich würde versuchen, mein Makro so zu ändern, dass die extrahierten Werte zusätzlich zu den Eigenschaften der E-Mail ausgegeben werden. Erst wenn ich diese Änderung erfolgreich durchgeführt habe, würde ich versuchen, die extrahierten Daten in eine vorhandene Arbeitsmappe zu schreiben. Ich würde verarbeitete E-Mails auch in einen anderen Ordner verschieben. Ich habe gezeigt, wo diese Änderungen vorgenommen werden müssen, aber keine weitere Hilfe geben. Ich werde auf eine Zusatzfrage antworten, wenn Sie an dem Punkt angelangt sind, an dem Sie diese Informationen benötigen.

Viel Glück.

Neueste Version des Makros im Originaltext

Option Explicit
Public Sub SaveEmailDetails()

  ' This macro creates a new Excel workbook and writes to it details
  ' of every email in the Inbox.

  ' Lines starting with hashes either MUST be changed before running the
  ' macro or suggest changes you might consider appropriate.

  Dim AttachCount As Long
  Dim AttachDtl() As String
  Dim ExcelWkBk As Excel.Workbook
  Dim FileName As String
  Dim FolderTgt As MAPIFolder
  Dim HtmlBody As String
  Dim InterestingItem As Boolean
  Dim InxAttach As Long
  Dim InxItemCrnt As Long
  Dim PathName As String
  Dim ReceivedTime As Date
  Dim RowCrnt As Long
  Dim SenderEmailAddress As String
  Dim SenderName As String
  Dim Subject As String
  Dim TextBody As String
  Dim xlApp As Excel.Application

  ' The Excel workbook will be created in this folder.
  ' ######## Replace "C:\DataArea\SO" with the name of a folder on your disc.
  PathName = "C:\DataArea\SO"

  ' This creates a unique filename.
  ' #### If you use a version of Excel 2003, change the extension to "xls".
  FileName = Format(Now(), "yymmdd hhmmss") & ".xlsx"

  ' Open own copy of Excel
  Set xlApp = Application.CreateObject("Excel.Application")
  With xlApp
    ' .Visible = True         ' This slows your macro but helps during debugging
    .ScreenUpdating = False ' Reduces flash and increases speed
    ' Create a new workbook
    ' #### If updating an existing workbook, replace with an
    ' #### Open workbook statement.
    Set ExcelWkBk = xlApp.Workbooks.Add
    With ExcelWkBk
      ' #### None of this code will be useful if you are adding
      ' #### to an existing workbook.  However, it demonstrates a
      ' #### variety of useful statements.
      .Worksheets("Sheet1").Name = "Inbox"    ' Rename first worksheet
      With .Worksheets("Inbox")
        ' Create header line
        With .Cells(1, "A")
          .Value = "Field"
          .Font.Bold = True
        End With
        With .Cells(1, "B")
          .Value = "Value"
          .Font.Bold = True
        End With
        .Columns("A").ColumnWidth = 18
        .Columns("B").ColumnWidth = 150
      End With
    End With
    RowCrnt = 2
  End With

  ' FolderTgt is the folder I am going to search.  This statement says
  ' I want to seach the Inbox.  The value "olFolderInbox" can be replaced
  ' to allow any of the standard folders to be searched.
  ' See FindSelectedFolder() for a routine that will search for any folder.
  Set FolderTgt = CreateObject("Outlook.Application"). _
              GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
  ' #### Use the following the access a non-default Inbox.
  ' #### Change "Xxxx" to name of one of your store you want to access.
  Set FolderTgt = Session.Folders("Xxxx").Folders("Inbox")

  ' This examines the emails in reverse order. I will explain why later.
  For InxItemCrnt = FolderTgt.Items.Count To 1 Step -1
    With FolderTgt.Items.Item(InxItemCrnt)
      ' A folder can contain several types of item: mail items, meeting items,
      ' contacts, etc.  I am only interested in mail items.
      If .Class = olMail Then
        ' Save selected properties to variables
        ReceivedTime = .ReceivedTime
        Subject = .Subject
        SenderName = .SenderName
        SenderEmailAddress = .SenderEmailAddress
        TextBody = .Body
        HtmlBody = .HtmlBody
        AttachCount = .Attachments.Count
        If AttachCount > 0 Then
          ReDim AttachDtl(1 To 7, 1 To AttachCount)
          For InxAttach = 1 To AttachCount
            ' There are four types of attachment:
            '  *   olByValue       1
            '  *   olByReference   4
            '  *   olEmbeddedItem  5
            '  *   olOLE           6
            Select Case .Attachments(InxAttach).Type
              Case olByValue
            AttachDtl(1, InxAttach) = "Val"
              Case olEmbeddeditem
            AttachDtl(1, InxAttach) = "Ebd"
              Case olByReference
            AttachDtl(1, InxAttach) = "Ref"
              Case olOLE
            AttachDtl(1, InxAttach) = "OLE"
              Case Else
            AttachDtl(1, InxAttach) = "Unk"
            End Select
            ' Not all types have all properties.  This code handles
            ' those missing properties of which I am aware.  However,
            ' I have never found an attachment of type Reference or OLE.
            ' Additional code may be required for them.
            Select Case .Attachments(InxAttach).Type
              Case olEmbeddeditem
                AttachDtl(2, InxAttach) = ""
              Case Else
                AttachDtl(2, InxAttach) = .Attachments(InxAttach).PathName
            End Select
            AttachDtl(3, InxAttach) = .Attachments(InxAttach).FileName
            AttachDtl(4, InxAttach) = .Attachments(InxAttach).DisplayName
            AttachDtl(5, InxAttach) = "--"
            ' I suspect Attachment had a parent property in early versions
            ' of Outlook. It is missing from Outlook 2016.
            On Error Resume Next
            AttachDtl(5, InxAttach) = .Attachments(InxAttach).Parent
            On Error GoTo 0
            AttachDtl(6, InxAttach) = .Attachments(InxAttach).Position
            ' Class 5 is attachment.  I have never seen an attachment with
            ' a different class and do not see the purpose of this property.
            ' The code will stop here if a different class is found.
            Debug.Assert .Attachments(InxAttach).Class = 5
            AttachDtl(7, InxAttach) = .Attachments(InxAttach).Class
          Next
        End If
        InterestingItem = True
      Else
        InterestingItem = False
      End If
    End With
    ' The most used properties of the email have been loaded to variables but
    ' there are many more properies.  Press F2.  Scroll down classes until
    ' you find MailItem.  Look through the members and note the name of
    ' any properties that look useful.  Look them up using VB Help.

    ' #### You need to add code here to eliminate uninteresting items.
    ' #### For example:
    'If SenderEmailAddress <> "[email protected]" Then
    '  InterestingItem = False
    'End If
    'If InStr(Subject, "Accounts payable") = 0 Then
    '  InterestingItem = False
    'End If
    'If AttachCount = 0 Then
    '  InterestingItem = False
    'End If

    ' #### If the item is still thought to be interesting I
    ' #### suggest extracting the required data to variables here.

    ' #### You should consider moving processed emails to another
    ' #### folder.  The emails are being processed in reverse order
    ' #### to allow this removal of an email from the Inbox without
    ' #### effecting the index numbers of unprocessed emails.

    If InterestingItem Then
      With ExcelWkBk
        With .Worksheets("Inbox")
          ' #### This code creates a dividing row and then
          ' #### outputs a property per row.  Again it demonstrates
          ' #### statements that are likely to be useful in the final
          ' #### version
          ' Create dividing row between emails
          .Rows(RowCrnt).RowHeight = 5
          .Range(.Cells(RowCrnt, "A"), .Cells(RowCrnt, "B")) _
                                      .Interior.Color = RGB(0, 255, 0)
          RowCrnt = RowCrnt + 1
          .Cells(RowCrnt, "A").Value = "Sender name"
          .Cells(RowCrnt, "B").Value = SenderName
          RowCrnt = RowCrnt + 1
          .Cells(RowCrnt, "A").Value = "Sender email address"
          .Cells(RowCrnt, "B").Value = SenderEmailAddress
          RowCrnt = RowCrnt + 1
          .Cells(RowCrnt, "A").Value = "Received time"
          With .Cells(RowCrnt, "B")
            .NumberFormat = "@"
            .Value = Format(ReceivedTime, "mmmm d, yyyy h:mm")
          End With
          RowCrnt = RowCrnt + 1
          .Cells(RowCrnt, "A").Value = "Subject"
          .Cells(RowCrnt, "B").Value = Subject
          RowCrnt = RowCrnt + 1
          If AttachCount > 0 Then
            .Cells(RowCrnt, "A").Value = "Attachments"
            .Cells(RowCrnt, "B").Value = "Inx|Type|Path name|File name|Display name|Parent|Position|Class"
            RowCrnt = RowCrnt + 1
            For InxAttach = 1 To AttachCount
              .Cells(RowCrnt, "B").Value = InxAttach & "|" & _
                                           AttachDtl(1, InxAttach) & "|" & _
                                           AttachDtl(2, InxAttach) & "|" & _
                                           AttachDtl(3, InxAttach) & "|" & _
                                           AttachDtl(4, InxAttach) & "|" & _
                                           AttachDtl(5, InxAttach) & "|" & _
                                           AttachDtl(6, InxAttach) & "|" & _
                                           AttachDtl(7, InxAttach)
              RowCrnt = RowCrnt + 1
            Next
          End If
          If TextBody <> "" Then

            ' ##### This code was in the original version of the macro
            ' ##### but I did not find it as useful as the other version of
            ' ##### the text body.  See below
            ' This outputs the text body with CR, LF and TB obeyed
            'With .Cells(RowCrnt, "A")
            '  .Value = "text body"
            '  .VerticalAlignment = xlTop
            'End With
            'With .Cells(RowCrnt, "B")
            '  ' The maximum size of a cell 32,767
            '  .Value = Mid(TextBody, 1, 32700)
            '  .WrapText = True
            'End With
            'RowCrnt = RowCrnt + 1

            ' This outputs the text body with NBSP, CR, LF and TB
            ' replaced by strings.
            With .Cells(RowCrnt, "A")
              .Value = "text body"
              .VerticalAlignment = xlTop
            End With
            TextBody = Replace(TextBody, Chr(160), "[NBSP]")
            TextBody = Replace(TextBody, vbCr, "[CR]")
            TextBody = Replace(TextBody, vbLf, "[LF]")
            TextBody = Replace(TextBody, vbTab, "[TB]")
            With .Cells(RowCrnt, "B")
              ' The maximum size of a cell 32,767
              .Value = Mid(TextBody, 1, 32700)
              .WrapText = True
            End With
            RowCrnt = RowCrnt + 1
          End If

          If HtmlBody <> "" Then

            ' ##### This code was in the original version of the macro
            ' ##### but I did not find it as useful as the other version of
            ' ##### the html body.  See below
            ' This outputs the html body with CR, LF and TB obeyed
            'With .Cells(RowCrnt, "A")
            '  .Value = "Html body"
            '  .VerticalAlignment = xlTop
            'End With
            'With .Cells(RowCrnt, "B")
            '  .Value = Mid(HtmlBody, 1, 32700)
            '  .WrapText = True
            'End With
            'RowCrnt = RowCrnt + 1

            ' This outputs the html body with NBSP, CR, LF and TB
            ' replaced by strings.
            With .Cells(RowCrnt, "A")
              .Value = "Html body"
              .VerticalAlignment = xlTop
            End With
            HtmlBody = Replace(HtmlBody, Chr(160), "[NBSP]")
            HtmlBody = Replace(HtmlBody, vbCr, "[CR]")
            HtmlBody = Replace(HtmlBody, vbLf, "[LF]")
            HtmlBody = Replace(HtmlBody, vbTab, "[TB]")
            With .Cells(RowCrnt, "B")
              .Value = Mid(HtmlBody, 1, 32700)
              .WrapText = True
            End With
            RowCrnt = RowCrnt + 1

          End If
        End With
      End With
    End If
  Next

  With xlApp
    With ExcelWkBk
      ' Write new workbook to disc
      If Right(PathName, 1) <> "\" Then
        PathName = PathName & "\"
      End If
      .SaveAs FileName:=PathName & FileName
      .Close
    End With
    .Quit   ' Close our copy of Excel
  End With

  Set xlApp = Nothing       ' Clear reference to Excel

End Sub

Makros, die nicht im ursprünglichen Beitrag enthalten sind, die aber einige Benutzer des obigen Makros für nützlich befunden haben.

Public Sub FindSelectedFolder(ByRef FolderTgt As MAPIFolder, _
                              ByVal NameTgt As String, ByVal NameSep As String)

  ' This routine (and its sub-routine) locate a folder within the hierarchy and
  ' returns it as an object of type MAPIFolder

  ' NameTgt   The name of the required folder in the format:
  '              FolderName1 NameSep FolderName2 [ NameSep FolderName3 ] ...
  '           If NameSep is "|", an example value is "Personal Folders|Inbox"
  '           FolderName1 must be an outer folder name such as
  '           "Personal Folders". The outer folder names are typically the names
  '           of PST files.  FolderName2 must be the name of a folder within
  '           Folder1; in the example "Inbox".  FolderName2 is compulsory.  This
  '           routine cannot return a PST file; only a folder within a PST file.
  '           FolderName3, FolderName4 and so on are optional and allow a folder
  '           at any depth with the hierarchy to be specified.
  ' NameSep   A character or string used to separate the folder names within
  '           NameTgt.
  ' FolderTgt On exit, the required folder.  Set to Nothing if not found.

  ' This routine initialises the search and finds the top level folder.
  ' FindSelectedSubFolder() is used to find the target folder within the
  ' top level folder.

  Dim InxFolderCrnt As Long
  Dim NameChild As String
  Dim NameCrnt As String
  Dim Pos As Long
  Dim TopLvlFolderList As Folders

  Set FolderTgt = Nothing   ' Target folder not found

  Set TopLvlFolderList = _
          CreateObject("Outlook.Application").GetNamespace("MAPI").Folders

  ' Split NameTgt into the name of folder at current level
  ' and the name of its children
  Pos = InStr(NameTgt, NameSep)
  If Pos = 0 Then
    ' I need at least a level 2 name
    Exit Sub
  End If
  NameCrnt = Mid(NameTgt, 1, Pos - 1)
  NameChild = Mid(NameTgt, Pos + 1)

  ' Look for current name.  Drop through and return nothing if name not found.
  For InxFolderCrnt = 1 To TopLvlFolderList.Count
    If NameCrnt = TopLvlFolderList(InxFolderCrnt).Name Then
      ' Have found current name. Call FindSelectedSubFolder() to
      ' look for its children
      Call FindSelectedSubFolder(TopLvlFolderList.Item(InxFolderCrnt), _
                                            FolderTgt, NameChild, NameSep)
      Exit For
    End If
  Next

End Sub
Public Sub FindSelectedSubFolder(FolderCrnt As MAPIFolder, _
                      ByRef FolderTgt As MAPIFolder, _
                      ByVal NameTgt As String, ByVal NameSep As String)

  ' See FindSelectedFolder() for an introduction to the purpose of this routine.
  ' This routine finds all folders below the top level

  ' FolderCrnt The folder to be seached for the target folder.
  ' NameTgt    The NameTgt passed to FindSelectedFolder will be of the form:
  '               A|B|C|D|E
  '            A is the name of outer folder which represents a PST file.
  '            FindSelectedFolder() removes "A|" from NameTgt and calls this
  '            routine with FolderCrnt set to folder A to search for B.
  '            When this routine finds B, it calls itself with FolderCrnt set to
  '            folder B to search for C.  Calls are nested to whatever depth are
  '            necessary.
  ' NameSep    As for FindSelectedSubFolder
  ' FolderTgt  As for FindSelectedSubFolder

  Dim InxFolderCrnt As Long
  Dim NameChild As String
  Dim NameCrnt As String
  Dim Pos As Long

  ' Split NameTgt into the name of folder at current level
  ' and the name of its children
  Pos = InStr(NameTgt, NameSep)
  If Pos = 0 Then
    NameCrnt = NameTgt
    NameChild = ""
  Else
    NameCrnt = Mid(NameTgt, 1, Pos - 1)
    NameChild = Mid(NameTgt, Pos + 1)
  End If

  ' Look for current name.  Drop through and return nothing if name not found.
  For InxFolderCrnt = 1 To FolderCrnt.Folders.Count
    If NameCrnt = FolderCrnt.Folders(InxFolderCrnt).Name Then
      ' Have found current name.
      If NameChild = "" Then
        ' Have found target folder
        Set FolderTgt = FolderCrnt.Folders(InxFolderCrnt)
      Else
        'Recurse to look for children
        Call FindSelectedSubFolder(FolderCrnt.Folders(InxFolderCrnt), _
                                            FolderTgt, NameChild, NameSep)
      End If
      Exit For
    End If
  Next

  ' If NameCrnt not found, FolderTgt will be returned unchanged.  Since it is
  ' initialised to Nothing at the beginning, that will be the returned value.

End Sub
19
Tony Dallimore