' BEWARE: you must add a reference to Outlook library
' go to your project properties page
' click to References there
' click to Add button->Reference->COM->Type libraries
' find Microsoft Outlook 15.0 Object Library on that long list (or whatever number is available on your machine)
' be careful to click it TWICE: first time you just select that element from the list, and the second time click to a checkbox that appears after selecting it
' click OK at the bottom right
' this will automatically also add the reference to Microsoft Office 15.0 Object Library
' add the following imports statement
Imports Outlook = Microsoft.Office.Interop.Outlook

Module Module1

    Sub Main()

        'this program reads Outlook contact data from Outlook contacts list

        'you need to have Outlook installed on your machine
        'you also need to add a reference to Microsoft.Office.Interop.Outlook in your project
        '
        ' made by Gjuro Kladaric, 2016-07
        '
        ' you can use this code for absoutely any (legal) purpose you want
        ' however, I do not accept any responsibilty related to such use

        ' yes, backup your .PST files first, no excuses, no crying later :-)

        Dim oApp As New Outlook.Application
        Dim oNS As Outlook.NameSpace = oApp.GetNamespace("MAPI")
        Dim folders = oNS.Folders

        ' the following is the-name-of-your-PST-file.pst  (so, no file path, no file extension, it's just a "PST data file name" you see in Outlook
        ' normaly, it is called "Outlook"
        Dim fff = folders("the-name-of-your-PST-file")
        Console.WriteLine(fff.Name & " : " & fff.FolderPath)

        ' the following is the name of the local contacts list 
        ' change it if your Outlook installation folder names are different (because of non-English language version)
        fff = fff.Folders("Contacts")
        Console.WriteLine(fff.Name & " : " & fff.FolderPath)

        Dim oContacts = fff.Items ' here we finally got a list of contact items
        Dim contactsCount As Integer = oContacts.Count

        Const numberOfAttributesOfContactItemClass As Integer = 168

        ' this -1 is because VB allocates one element more than you specified: dim a(10) gives you 11 elements, from 0 to 10
        Dim contacts(contactsCount - 1, numberOfAttributesOfContactItemClass - 1) As String

        Dim totalContactNumber As Integer = 0
        For Each cc As Object In oContacts
            ' sometimes, Outlook returns something that is not convertible to ContactItem; I chose to ignore it
            Dim c As Outlook.ContactItem
            c = TryCast(cc, Outlook.ContactItem)
            If c Is Nothing Then
                Console.Write("{0:d} nothing :: ", (totalContactNumber + 1))
            Else ' if it is a real ContactItem, then pick all string attribute values and save it to a string array (so that we can filter out those that are empty)
                Console.Write("{0:d} :: ", (totalContactNumber + 1))
                contacts(totalContactNumber, 0) = c.Account
                'contacts(contactNumber, 1) = "c.Actions"""
                contacts(totalContactNumber, 2) = c.Anniversary
                'contacts(contactNumber, 3) = "c.Application"""
                contacts(totalContactNumber, 4) = c.AssistantName
                contacts(totalContactNumber, 5) = c.AssistantTelephoneNumber
                'contacts(contactNumber, 6) = "c.Attachments"
                contacts(totalContactNumber, 7) = c.AutoResolvedWinner
                contacts(totalContactNumber, 8) = c.BillingInformation
                contacts(totalContactNumber, 9) = c.Birthday
                contacts(totalContactNumber, 10) = c.Body
                contacts(totalContactNumber, 11) = c.Business2TelephoneNumber
                contacts(totalContactNumber, 12) = c.BusinessAddress
                contacts(totalContactNumber, 13) = c.BusinessAddressCity
                contacts(totalContactNumber, 14) = c.BusinessAddressCountry
                contacts(totalContactNumber, 15) = c.BusinessAddressPostalCode
                contacts(totalContactNumber, 16) = c.BusinessAddressPostOfficeBox
                contacts(totalContactNumber, 17) = c.BusinessAddressState
                contacts(totalContactNumber, 18) = c.BusinessAddressStreet
                contacts(totalContactNumber, 19) = c.BusinessCardLayoutXml
                contacts(totalContactNumber, 20) = c.BusinessCardType
                contacts(totalContactNumber, 21) = c.BusinessFaxNumber
                contacts(totalContactNumber, 22) = c.BusinessHomePage
                contacts(totalContactNumber, 23) = c.BusinessTelephoneNumber
                contacts(totalContactNumber, 24) = c.CallbackTelephoneNumber
                contacts(totalContactNumber, 25) = c.CarTelephoneNumber
                contacts(totalContactNumber, 26) = c.Categories
                contacts(totalContactNumber, 27) = c.Children
                contacts(totalContactNumber, 28) = c.Class
                contacts(totalContactNumber, 29) = c.Companies
                contacts(totalContactNumber, 30) = c.CompanyAndFullName
                contacts(totalContactNumber, 31) = c.CompanyLastFirstNoSpace
                contacts(totalContactNumber, 32) = c.CompanyLastFirstSpaceOnly
                contacts(totalContactNumber, 33) = c.CompanyMainTelephoneNumber
                contacts(totalContactNumber, 34) = c.CompanyName
                contacts(totalContactNumber, 35) = c.ComputerNetworkName
                'contacts(contactNumber, 36) = "c.Conflicts"
                contacts(totalContactNumber, 37) = c.ConversationID
                contacts(totalContactNumber, 38) = c.ConversationIndex
                contacts(totalContactNumber, 39) = c.ConversationTopic
                contacts(totalContactNumber, 40) = c.CreationTime
                contacts(totalContactNumber, 41) = c.CustomerID
                contacts(totalContactNumber, 42) = c.Department
                contacts(totalContactNumber, 43) = c.DownloadState
                contacts(totalContactNumber, 44) = c.Email1Address
                contacts(totalContactNumber, 45) = c.Email1AddressType
                contacts(totalContactNumber, 46) = c.Email1DisplayName
                contacts(totalContactNumber, 47) = c.Email1EntryID
                contacts(totalContactNumber, 48) = c.Email2Address
                contacts(totalContactNumber, 49) = c.Email2AddressType
                contacts(totalContactNumber, 50) = c.Email2DisplayName
                contacts(totalContactNumber, 51) = c.Email2EntryID
                contacts(totalContactNumber, 52) = c.Email3Address
                contacts(totalContactNumber, 53) = c.Email3AddressType
                contacts(totalContactNumber, 54) = c.Email3DisplayName
                contacts(totalContactNumber, 55) = c.Email3EntryID
                contacts(totalContactNumber, 56) = c.EntryID
                contacts(totalContactNumber, 57) = c.FileAs
                contacts(totalContactNumber, 58) = c.FirstName
                'contacts(contactNumber, 59) = "c.FormDescription"
                contacts(totalContactNumber, 60) = c.FTPSite
                contacts(totalContactNumber, 61) = c.FullName
                contacts(totalContactNumber, 62) = c.FullNameAndCompany
                contacts(totalContactNumber, 63) = c.Gender
                'contacts(contactNumber, 64) = "c.GetInspector"
                contacts(totalContactNumber, 65) = c.GovernmentIDNumber
                contacts(totalContactNumber, 66) = c.HasPicture
                contacts(totalContactNumber, 67) = c.Hobby
                contacts(totalContactNumber, 68) = c.Home2TelephoneNumber
                contacts(totalContactNumber, 69) = c.HomeAddress
                contacts(totalContactNumber, 70) = c.HomeAddressCity
                contacts(totalContactNumber, 71) = c.HomeAddressCountry
                contacts(totalContactNumber, 72) = c.HomeAddressPostalCode
                contacts(totalContactNumber, 73) = c.HomeAddressPostOfficeBox
                contacts(totalContactNumber, 74) = c.HomeAddressState
                contacts(totalContactNumber, 75) = c.HomeAddressStreet
                contacts(totalContactNumber, 76) = c.HomeFaxNumber
                contacts(totalContactNumber, 77) = c.HomeTelephoneNumber
                contacts(totalContactNumber, 78) = c.IMAddress
                contacts(totalContactNumber, 79) = c.Importance
                contacts(totalContactNumber, 80) = c.Initials
                contacts(totalContactNumber, 81) = c.InternetFreeBusyAddress
                contacts(totalContactNumber, 82) = c.IsConflict
                contacts(totalContactNumber, 83) = c.ISDNNumber
                contacts(totalContactNumber, 84) = c.IsMarkedAsTask
                'contacts(contactNumber, 85) = "c.ItemProperties"
                contacts(totalContactNumber, 86) = c.JobTitle
                contacts(totalContactNumber, 87) = c.Journal
                contacts(totalContactNumber, 88) = c.Language
                contacts(totalContactNumber, 89) = c.LastFirstAndSuffix
                contacts(totalContactNumber, 90) = c.LastFirstNoSpace
                contacts(totalContactNumber, 91) = c.LastFirstNoSpaceAndSuffix
                contacts(totalContactNumber, 92) = c.LastFirstNoSpaceCompany
                contacts(totalContactNumber, 93) = c.LastFirstSpaceOnly
                contacts(totalContactNumber, 94) = c.LastFirstSpaceOnlyCompany
                contacts(totalContactNumber, 95) = c.LastModificationTime
                contacts(totalContactNumber, 96) = c.LastName
                contacts(totalContactNumber, 97) = c.LastNameAndFirstName
                contacts(totalContactNumber, 98) = c.MailingAddress
                contacts(totalContactNumber, 99) = c.MailingAddressCity
                contacts(totalContactNumber, 100) = c.MailingAddressCountry
                contacts(totalContactNumber, 101) = c.MailingAddressPostalCode
                contacts(totalContactNumber, 102) = c.MailingAddressPostOfficeBox
                contacts(totalContactNumber, 103) = c.MailingAddressState
                contacts(totalContactNumber, 104) = c.MailingAddressStreet
                contacts(totalContactNumber, 105) = c.ManagerName
                contacts(totalContactNumber, 106) = c.MarkForDownload
                contacts(totalContactNumber, 107) = c.MessageClass
                contacts(totalContactNumber, 108) = c.MiddleName
                contacts(totalContactNumber, 109) = c.Mileage
                contacts(totalContactNumber, 110) = c.MobileTelephoneNumber
                contacts(totalContactNumber, 111) = c.NetMeetingAlias
                contacts(totalContactNumber, 112) = c.NetMeetingServer
                contacts(totalContactNumber, 113) = c.NickName
                contacts(totalContactNumber, 114) = c.NoAging
                contacts(totalContactNumber, 115) = c.OfficeLocation
                contacts(totalContactNumber, 116) = c.OrganizationalIDNumber
                contacts(totalContactNumber, 117) = c.OtherAddress
                contacts(totalContactNumber, 118) = c.OtherAddressCity
                contacts(totalContactNumber, 119) = c.OtherAddressCountry
                contacts(totalContactNumber, 120) = c.OtherAddressPostalCode
                contacts(totalContactNumber, 121) = c.OtherAddressPostOfficeBox
                contacts(totalContactNumber, 122) = c.OtherAddressState
                contacts(totalContactNumber, 123) = c.OtherAddressStreet
                contacts(totalContactNumber, 124) = c.OtherFaxNumber
                contacts(totalContactNumber, 125) = c.OtherTelephoneNumber
                contacts(totalContactNumber, 126) = c.OutlookInternalVersion
                contacts(totalContactNumber, 127) = c.OutlookVersion
                contacts(totalContactNumber, 128) = c.PagerNumber
                'contacts(contactNumber, 129) = "c.Parent"
                contacts(totalContactNumber, 130) = c.PersonalHomePage
                contacts(totalContactNumber, 131) = c.PrimaryTelephoneNumber
                contacts(totalContactNumber, 132) = c.Profession
                'contacts(contactNumber, 133) = "c.PropertyAccessor"
                contacts(totalContactNumber, 134) = c.RadioTelephoneNumber
                contacts(totalContactNumber, 135) = c.ReferredBy
                contacts(totalContactNumber, 136) = c.ReminderOverrideDefault
                contacts(totalContactNumber, 137) = c.ReminderPlaySound
                contacts(totalContactNumber, 138) = c.ReminderSet
                contacts(totalContactNumber, 139) = c.ReminderSoundFile
                contacts(totalContactNumber, 140) = c.ReminderTime
                'contacts(contactNumber, 141) = "c.RTFBody"
                contacts(totalContactNumber, 142) = c.Saved
                contacts(totalContactNumber, 143) = c.SelectedMailingAddress
                contacts(totalContactNumber, 144) = c.Sensitivity
                'contacts(contactNumber, 145) = "c.Session"
                contacts(totalContactNumber, 146) = c.Size
                contacts(totalContactNumber, 147) = c.Spouse
                contacts(totalContactNumber, 148) = c.Subject
                contacts(totalContactNumber, 149) = c.Suffix
                contacts(totalContactNumber, 150) = c.TaskCompletedDate
                contacts(totalContactNumber, 151) = c.TaskDueDate
                contacts(totalContactNumber, 152) = c.TaskStartDate
                contacts(totalContactNumber, 153) = c.TaskSubject
                contacts(totalContactNumber, 154) = c.TelexNumber
                contacts(totalContactNumber, 155) = c.Title
                contacts(totalContactNumber, 156) = c.ToDoTaskOrdinal
                contacts(totalContactNumber, 157) = c.TTYTDDTelephoneNumber
                contacts(totalContactNumber, 158) = c.UnRead
                contacts(totalContactNumber, 159) = c.User1
                contacts(totalContactNumber, 160) = c.User2
                contacts(totalContactNumber, 161) = c.User3
                contacts(totalContactNumber, 162) = c.User4
                'contacts(contactNumber, 163) = "c.UserProperties"
                contacts(totalContactNumber, 164) = c.WebPage
                contacts(totalContactNumber, 165) = c.YomiCompanyName
                contacts(totalContactNumber, 166) = c.YomiFirstName
                contacts(totalContactNumber, 167) = c.YomiLastName
            End If
            totalContactNumber = totalContactNumber + 1
        Next
        Console.WriteLine()
        Console.WriteLine()

        ' here we have all data from all contacts

        ' next, we will find which fields are all empty so we can ignore that
        ' first, clear the list of useful ones
        Dim useful(numberOfAttributesOfContactItemClass - 1) As Boolean
        For j = 0 To numberOfAttributesOfContactItemClass - 1
            useful(j) = False
        Next

        ' now, record all fields that have any values for any contact
        For n = 0 To totalContactNumber - 1
            For j = 0 To numberOfAttributesOfContactItemClass - 1
                If contacts(n, j) IsNot Nothing AndAlso contacts(n, j).Trim <> "" Then
                    useful(j) = True
                End If
            Next
        Next

        ' in the end, this writes down number of all fields that contain useful data
        Dim nn = 0
        For j = 0 To numberOfAttributesOfContactItemClass - 1
            If useful(j) Then
                Console.Write(j & " : ")
                nn = nn + 1
            End If
        Next
        Console.WriteLine()
        Console.WriteLine()
        Console.WriteLine("koristenih polja: " & nn)

        ' this code would write all the non-empty contents of all usefull fields into separate files, for notepad-like inspection
        'For j = 0 To numberOfAttributesOfContactItem - 1
        '    If ima(j) Then
        '        FileOpen(1, "file" & j.ToString.PadLeft(4, "0"c) & ".txt", OpenMode.Output)
        '        For n = 0 To totalContactNumber - 1
        '            If contacts(n, j) IsNot Nothing AndAlso contacts(n, j).Trim <> "" Then
        '                PrintLine(1, fields(j) & ": " & contacts(n, j))
        '            End If
        '        Next
        '        FileClose(1)
        '    End If
        'Next

        ' now, what follows is MY CHOICE of useful fields, based on notepad-like inspection 
        ' of files previously generated with the above commented-out code

        Dim usefulFields() As Integer = {26, 30, 32, 34, 39, 44, 46, 48, 57, 58, 61, 62, 89, 93, 96, 97, 110, 113, 148}

        Dim countOfUseful = 0
        Dim countOfNonUseful = 0

        ' the code below writes collected data in "ANSI mode" (8 bit chars, according to the locale of your computer)
        ' if you have contact data that contains letters from other languages, this would not work well
        ' recode to use TextWriter class, or build an output array of strings and then write it to a file using 
        ' System.IO.File.WriteAllText()

        ' this file will be written, of course, to the application folder
        FileOpen(1, "output.txt", OpenMode.Output)

        ' we will produce # separated list of data items
        ' field names go into the first line
        Print(1, "itemNumber#")
        For j = 0 To usefulFields.Length - 1
            Print(1, fieldNames(usefulFields(j)) & "#")
        Next
        PrintLine(1)

        ' and then come the data
        For contactNumber = 0 To totalContactNumber - 1
            Dim found = False
            ' but first we should see whether the contact has any data
            For j = 0 To usefulFields.Length - 1
                If contacts(contactNumber, usefulFields(j)) IsNot Nothing AndAlso contacts(contactNumber, usefulFields(j)).Trim <> "" Then
                    found = True
                    Exit For
                End If
            Next

            ' contact number
            Print(1, (contactNumber + 1).ToString & "#")

            ' if any data for a contact, write that data to a file
            If found Then
                countOfUseful += 1
                For j = 0 To usefulFields.Length - 1
                    Dim s = contacts(contactNumber, usefulFields(j))
                    If s IsNot Nothing Then s = s.Replace(vbCrLf, "$$") ' replace any newlines with double dollars, for convenience of later data processing in excel
                    Print(1, s & "#")
                Next
            Else
                countOfNonUseful += 1
            End If
            PrintLine(1)
        Next

        ' finished, close the file
        FileClose(1)

        oApp = Nothing
        folders = Nothing

        Console.WriteLine("Finished. Usefull addresses count " & countOfUseful & ", non-useful " & countOfNonUseful)
        Console.ReadLine()

    End Sub

    Dim fieldNames() As String = {
        "Account",
        "Actions",
        "Anniversary",
        "Application",
        "AssistantName",
        "AssistantTelephoneNumber",
        "Attachments",
        "AutoResolvedWinner",
        "BillingInformation",
        "Birthday",
        "Body",
        "Business2TelephoneNumber",
        "BusinessAddress",
        "BusinessAddressCity",
        "BusinessAddressCountry",
        "BusinessAddressPostalCode",
        "BusinessAddressPostOfficeBox",
        "BusinessAddressState",
        "BusinessAddressStreet",
        "BusinessCardLayoutXml",
        "BusinessCardType",
        "BusinessFaxNumber",
        "BusinessHomePage",
        "BusinessTelephoneNumber",
        "CallbackTelephoneNumber",
        "CarTelephoneNumber",
        "Categories",
        "Children",
        "Class",
        "Companies",
        "CompanyAndFullName",
        "CompanyLastFirstNoSpace",
        "CompanyLastFirstSpaceOnly",
        "CompanyMainTelephoneNumber",
        "CompanyName",
        "ComputerNetworkName",
        "Conflicts",
        "ConversationID",
        "ConversationIndex",
        "ConversationTopic",
        "CreationTime",
        "CustomerID",
        "Department",
        "DownloadState",
        "Email1Address",
        "Email1AddressType",
        "Email1DisplayName",
        "Email1EntryID",
        "Email2Address",
        "Email2AddressType",
        "Email2DisplayName",
        "Email2EntryID",
        "Email3Address",
        "Email3AddressType",
        "Email3DisplayName",
        "Email3EntryID",
        "EntryID",
        "FileAs",
        "FirstName",
        "FormDescription",
        "FTPSite",
        "FullName",
        "FullNameAndCompany",
        "Gender",
        "GetInspector",
        "GovernmentIDNumber",
        "HasPicture",
        "Hobby",
        "Home2TelephoneNumber",
        "HomeAddress",
        "HomeAddressCity",
        "HomeAddressCountry",
        "HomeAddressPostalCode",
        "HomeAddressPostOfficeBox",
        "HomeAddressState",
        "HomeAddressStreet",
        "HomeFaxNumber",
        "HomeTelephoneNumber",
        "IMAddress",
        "Importance",
        "Initials",
        "InternetFreeBusyAddress",
        "IsConflict",
        "ISDNNumber",
        "IsMarkedAsTask",
        "ItemProperties",
        "JobTitle",
        "Journal",
        "Language",
        "LastFirstAndSuffix",
        "LastFirstNoSpace",
        "LastFirstNoSpaceAndSuffix",
        "LastFirstNoSpaceCompany",
        "LastFirstSpaceOnly",
        "LastFirstSpaceOnlyCompany",
        "LastModificationTime",
        "LastName",
        "LastNameAndFirstName",
        "MailingAddress",
        "MailingAddressCity",
        "MailingAddressCountry",
        "MailingAddressPostalCode",
        "MailingAddressPostOfficeBox",
        "MailingAddressState",
        "MailingAddressStreet",
        "ManagerName",
        "MarkForDownload",
        "MessageClass",
        "MiddleName",
        "Mileage",
        "MobileTelephoneNumber",
        "NetMeetingAlias",
        "NetMeetingServer",
        "NickName",
        "NoAging",
        "OfficeLocation",
        "OrganizationalIDNumber",
        "OtherAddress",
        "OtherAddressCity",
        "OtherAddressCountry",
        "OtherAddressPostalCode",
        "OtherAddressPostOfficeBox",
        "OtherAddressState",
        "OtherAddressStreet",
        "OtherFaxNumber",
        "OtherTelephoneNumber",
        "OutlookInternalVersion",
        "OutlookVersion",
        "PagerNumber",
        "Parent",
        "PersonalHomePage",
        "PrimaryTelephoneNumber",
        "Profession",
        "PropertyAccessor",
        "RadioTelephoneNumber",
        "ReferredBy",
        "ReminderOverrideDefault",
        "ReminderPlaySound",
        "ReminderSet",
        "ReminderSoundFile",
        "ReminderTime",
        "RTFBody",
        "Saved",
        "SelectedMailingAddress",
        "Sensitivity",
        "Session",
        "Size",
        "Spouse",
        "Subject",
        "Suffix",
        "TaskCompletedDate",
        "TaskDueDate",
        "TaskStartDate",
        "TaskSubject",
        "TelexNumber",
        "Title",
        "ToDoTaskOrdinal",
        "TTYTDDTelephoneNumber",
        "UnRead",
        "User1",
        "User2",
        "User3",
        "User4",
        "UserProperties",
        "WebPage",
        "YomiCompanyName",
        "YomiFirstName",
        "YomiLastName"
    }

End Module