아웃룩에서 메일 하나를 클릭해 둔 상태로 매크로를 실행하면, 그 메일의 제목과 본문을 바로 꺼내 쓸 수 있습니다. 거래처 주문 메일을 열어 둔 채 버튼 하나로 엑셀 양식에 옮긴다거나, 선택한 메일 내용을 사내 시스템에 등록하는 자동화를 만들 때 출발점이 되는 코드예요. "지금 사용자가 보고 있는 것"을 가져오는 게 핵심이라, 폴더를 뒤져 메일을 찾는 코드보다 훨씬 간단합니다.
Sub progrgram1472()
Dim myOlExp As Outlook.Explorer
Dim myOlSel As Outlook.Selection
Set myOlExp = Application.ActiveExplorer
Set myOlSel = myOlExp.Selection
Dim selectedFolder As Outlook.MAPIFolder
Set selectedFolder = myOlExp.CurrentFolder
Dim itemMessage As String
itemMessage = "Item is unknown."
Dim expMessage As String
expMessage = "Your current folder is " & selectedFolder.Parent.Name & " - " & selectedFolder.Name & "." & vbCrLf
If myOlSel.Count > 0 Then
Dim selObject As Object
Set selObject = myOlSel.Item(1)
If (TypeOf selObject Is Outlook.mailItem) Then
Dim mailItem As Outlook.mailItem
Set mailItem = selObject
itemMessage = "The item is an e-mail message." & " The subject is " & mailItem.Subject & "."
itemMessage = itemMessage & vbCrLf
itemMessage = itemMessage & mailItem.Body
'mailItem.Display (False)
ElseIf (TypeOf selObject Is Outlook.contactItem) Then
Dim contactItem As Outlook.contactItem
Set contactItem = selObject
itemMessage = "The item is a contact." & " The full name is " & contactItem.Subject & "."
'contactItem.Display (False)
ElseIf (TypeOf selObject Is Outlook.AppointmentItem) Then
Dim apptItem As Outlook.AppointmentItem
Set apptItem = selObject
itemMessage = "The item is an appointment." & apptItem.Subject & "."
ElseIf (TypeOf selObject Is Outlook.taskItem) Then
Dim taskItem As Outlook.taskItem
Set taskItem = selObject
itemMessage = "The item is a task." & " The body is " & taskItem.Body & "."
ElseIf (TypeOf selObject Is Outlook.meetingItem) Then
Dim meetingItem As Outlook.meetingItem
Set meetingItem = selObject
itemMessage = "The item is a meeting item. " & "The subject is " & meetingItem.Subject & "."
End If
End If
expMessage = expMessage & itemMessage
MsgBox (expMessage)
End Sub
Explorer와 Selection의 관계
아웃룩 화면은 크게 두 종류의 창으로 나뉩니다. 폴더 목록과 메일 목록이 보이는 메인 창이 Explorer, 메일을 더블클릭해서 따로 띄운 창이 Inspector입니다. Application.ActiveExplorer는 지금 앞에 있는 메인 창을 돌려주고, 그 창의 Selection에는 목록에서 선택된 항목들이 들어 있습니다. 여러 개를 Ctrl로 잡았다면 Count가 그만큼 늘어나고, 이 코드는 그중 첫 번째(Item(1))만 처리합니다.
CurrentFolder는 현재 보고 있는 폴더이고, Parent.Name을 함께 찍으면 어느 계정(사서함) 아래의 어느 폴더인지 알 수 있습니다. 계정이 여러 개 붙어 있는 PC에서 엉뚱한 받은편지함을 보고 있는 건 아닌지 확인할 때 쓸모가 있습니다.
항목 종류를 먼저 가려야 하는 이유
받은편지함에 있다고 다 메일은 아닙니다. 모임 요청, 읽음 확인, 배달 실패 보고서 같은 것도 섞여 있죠. 이런 항목을 MailItem 변수에 바로 넣으면 형식 불일치 오류가 납니다. 그래서 일단 Object로 받은 다음 TypeOf ... Is로 종류를 확인하고 맞는 형식의 변수에 담는 구조로 되어 있습니다. 메일이면 제목과 본문을, 일정·모임은 제목을, 작업은 본문을 읽습니다. 어디에도 해당하지 않으면 처음 넣어 둔 "Item is unknown." 문구가 그대로 남습니다.
주의할 곳이 하나 있습니다. 연락처 분기는 메시지에 "full name"이라고 적어 놓고 실제로는 contactItem.Subject를 읽습니다. 연락처의 Subject는 보통 표시 이름과 비슷하게 나오긴 하지만, 정확히 전체 이름이 필요하다면 contactItem.FullName을 쓰는 게 맞습니다.
실무에서 손볼 부분
Body는 서식이 빠진 일반 텍스트입니다. 표나 글꼴까지 필요하면 HTMLBody를 읽어야 하는데, 이건 HTML 소스 그대로라 파싱이 따로 필요합니다. 주석 처리된 Display (False)를 살리면 선택한 항목을 별도 창으로 열어 줍니다.
엑셀 VBA에서 이 코드를 쓰려면 Application이 아웃룩이 아니라 엑셀을 가리키기 때문에 그대로는 안 됩니다. 참조 설정에서 Microsoft Outlook 개체 라이브러리를 추가하고, GetObject(, "Outlook.Application")으로 실행 중인 아웃룩을 잡아 ActiveExplorer를 호출하는 식으로 바꿔야 합니다. 또 메일 대신 열어 둔 개별 창의 내용을 가져오고 싶다면 ActiveExplorer 대신 ActiveInspector.CurrentItem을 쓰면 됩니다. 선택한 여러 메일을 한꺼번에 처리하고 싶을 때는 Item(1) 부분을 For Each selObject In myOlSel 루프로 바꿔 주면 됩니다.