본문 바로가기

코딩/업무자동화

[파이썬/업무자동화] Outlook 메일 첨부 엑셀 내용 자동 취합하기

반응형

※ 이 글을 쓰는 사람은 SW 비전공자입니다.

※ 개인 공부를 위해 정리하는 글이며, 작성한 코드들은 효율성, 깔끔함(?) 등과는 거리가 멀 수 있습니다.

※ 이전 포스팅

1편 : 2021.03.01 - [코딩/Python] - [Python/파이썬] Outlook 메일 파싱(parsing) 정리 - 1

2편 : 2021.03.02 - [코딩/Python] - [Python/파이썬] Outlook 메일 파싱(parsing) 정리 - 2

3편 : 2021.03.23 - [코딩/Python] - [Python/파이썬] Outlook 여러 메일 첨부 파일 한번에 받기

4편 : 2021.04.28 - [코딩/Python] - [Python/파이썬] Outlook 메일 첨부 엑셀파일의 내용 자동 취합하기


  이전 포스팅에서 Outlook의 정해진 폴더에서 메일의 첨부 파일을 모두 다운받는 코드를 작성하였다. 이번 포스팅에서는 첨부파일로 모두 다운받는 엑셀파일을 한 파일에 취합하는 자동화 코드 부분을 정리하였다.(전체 코드는 하단에 첨부)

 

  전 포스팅 내용의 도식화 내용을 그대로 가져와보았다. 이번 포스팅은 아래 빨간상자 부분을 구현한다고 보면 된다. 그 전에 엑셀파일을 다운받는 부분은 전 포스팅 링크를 참고!

( 2021.03.23 - [코딩/Python] - [Python/파이썬] Outlook 여러 메일 첨부 파일 한번에 받기 )

 

프로그램 컨셉도

 

메일의 첨부파일도 이전 포스팅 내용과 동일하다.(총 3통의 메일이며, 첨부파일은 총 4개 엑셀파일임)

 

 

 

 

 

 

 

 

 

 

1. import 모듈

 

  import한 모듈은 총 3가지이다.

 

 

<코드>

import win32com.client
import os
import pandas as pd

 

-. win32com.client : outlook을 제어할 수 있는 모듈로 이전 포스팅에서 정리하였으므로 설명은 생략

-. os : 특정 폴더에서 엑셀파일의 목록을 리스트로 받아오기 위한 모듈

-. pandas : dataframe을 생성해서 원하는 데이터로 가공할 수 있는 기능을 제공 하는 모듈

 

pandas의 경우 이전에 필요한 부분을 쭉 정리하는 포스팅을 작성하였다. 이번 편에서 필요한 내용은 아래 내용을 작성하면서 링크를 첨부

 

 

 

2. 함수 정의

 

 -. 총 3 part로 나누어 작성하였다.

 

 

1) att_down(foldername, downpath)

 

 

-. 메일 폴더명과 첨부파일을 다운받을 위치를 입력받아 첨부메일을 자동으로 받아온다. 이 부분도 이전 포스팅에서 내

    을 정리하였으므로 생략하고 코드만 첨부

 

 

<코드>

#outlook 정해진 폴더에서 첨부파일을 다운로드 하는 함수
#flodername : outlook 폴더명, downpath : 다운받을 위치
def att_down(foldername, downpath):
    outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
    inbox = outlook.GetDefaultFolder(6).Folders[foldername]
    messages = inbox.Items
    
    no = 1 #중복 파일명이 있을 것을 대비해 추가한 파일명 인덱스
    m_count = 1 #메일 카운트
    #각 메일마다 첨부파일을 다운로드 하는 루프
    for ms in messages:
        
        attachments = ms.Attachments #해당 메일의 첨부파일 개수(integer)
        r = attachments.count
        print(str(m_count)+"번째 메일 첨부파일 개수 : ",str(r)+"개")
        m_count=m_count+1
        for i in range(1, r + 1):
            attachment = attachments.Item(i)
            attachment.SaveASFile(downpath + str(no) + "_" + str(attachment))  # 파일명을 넣어야 함.
            no = no + 1

 

 

2) att_df(downpath)

 

-. 1)에서 다운받은 첨부 엑셀 파일을 모두 dataframe화하여 리스트에 추가시킨다.

-. dataframe 생성 및 결측치 제거에 대한 부분은 이전에 포스팅을 했어서 아래 링크로 대신한다.

   (결측치 제거 함수  dropna)

 

2021.04.01 - [코딩/Python] - [Python/파이썬] Pandas 기초 정리 : 엑셀 파일(.xlsx) Dataframe으로 만들기

2021.04.13 - [코딩/Python] - [Python/파이썬] Pandas 기초 정리 : 원소 바꾸기, dropna(), fillna()

 

<코드>

def att_df(downpath):
    #downpath 경로에 있는 파일 리스트화(다운받은 엑셀파일 경로)
    filelist = os.listdir(downpath)
    
    #데이터프레임을 리스트화하기 위한 빈 리스트 선언
    df_list = []
    
    #각각 파일을 데이터프레임화해서 리스트에 넣기 
    for fn in filelist:
    	 #엑셀파일 데이터프레임화
         df = pd.read_excel(downpath+"/"+fn, engine="openpyxl")
         #결측치(NaN) 제거
         df.dropna(inplace =True)
         #각 생성한 데이터프레임을 df_list에 추가
         df_list.append(df)

    return df_list #리스트에 df를 모두 추가하고 해당 리스트를 return

 

 

-. df 모두 리스트에 추가 후 해당 리스트를 return한다.

-. 위 메일의 첨부파일이 4개였으므로 리스트의 요소도 4개이다.

 

<df를 리스트화한 결과>

 

 

3) att_merge(df_list)

 

-. 2)의 리턴 결과인 df_list를 통해 1개 엑셀파일로 통합하는 함수이다.

-. 자세한 내용은 주석을 참고하며, pandas의 concat함수의 경우 아래 링크 참고!!

( 2021.04.24 - [코딩/Python] - [Python/파이썬] Pandas Dataframe 결합 : Concat )

 

 

<코드>

def att_merge(df_list):
    count = len(df_list) #df_list의 요소 개수 반환
	
    #df가 1개일경우 결과는 리스트 첫요소로 정해짐
    if count == 1:
        result = df_list[0]
	
    #df가 2개일경우 concat 함수를 통해 결합, index는 초기화
    elif count == 2:
        result = pd.concat([df_list[0], df_list[1]], ignore_index=True)
	
    #df가 3개이상일 경우 concat 함수를 사용하되, temp 변수를 활용하여 결합을 반복함.
    else:
        temp = df_list[0]
        for i in range(1, count):
            result = pd.concat([temp, df_list[i]], ignore_index=True)
            temp = result
	
    #결과를 출력하고 df를 결과 엑셀파일로 변환
    print(result)
    result.to_excel("outlook결과파일.xlsx")

 

 

3. 실행 결과

 

-. 함수를 모두 작성 후, 실행 코드는 아래와 같다.

 

 

<코드>

###첨부파일 다운로드 하기
fn = "test" #메일 폴더명
downpath = "C:/~~" #첨부파일 다운받을 경로
att_down(fn, downpath) #첨부파일 다운 함수 호출
df_list = att_df(downpath)#다운받은 엑셀파일 데이터프레임화시키는 함수 호출(리턴값 리스트)
att_merge(df_list) #df 리스트를 입력받아서 각각 concat함수를 통해 결합 및 엑셀파일 추출

 

<결과>

 

1) 메일의 첨부 엑셀파일은 정해진 경로에 저장 됨.

<설정 경로에 첨부파일 모두 저장>

 

2) 각각 첨부파일을 데이터프레임화 시켜 결합시킨 결과를 터미널 창에 출력

<결합 결과 터미널 창에 출력>

3) 해당 결과 데이터프레임을 엑셀파일로 추출

< outlook결과파일.xlsx >

 

 

4. 전체 코드

  

   -. 하단에 실행부의 변수 fn과 downpath만 수정하면 사용할 수 있다.

 

import win32com.client
import os
import pandas as pd

#outlook 정해진 폴더에서 첨부파일을 다운로드 하는 함수
#flodername : outlook 폴더명, downpath : 다운받을 위치
def att_down(foldername, downpath):
    outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
    inbox = outlook.GetDefaultFolder(6).Folders[foldername]
    messages = inbox.Items
    
    no = 1 #중복 파일명이 있을 것을 대비해 추가한 파일명 인덱스
    m_count = 1 #메일 카운트
    #각 메일마다 첨부파일을 다운로드 하는 루프
    for ms in messages:
        
        attachments = ms.Attachments #해당 메일의 첨부파일 개수(integer)
        r = attachments.count
        print(str(m_count)+"번째 메일 첨부파일 개수 : ",str(r)+"개")
        m_count=m_count+1
        for i in range(1, r + 1):
            attachment = attachments.Item(i)
            attachment.SaveASFile(downpath + str(no) + "_" + str(attachment))  # 파일명을 넣어야 함.
            no = no + 1


def att_df(downpath):
    filelist = os.listdir(downpath)
    df_list = []

    #각각 파일을 데이터프레임화해서 리스트에 넣기 
    for fn in filelist:
         df = pd.read_excel(downpath+"/"+fn, engine="openpyxl")
         df.dropna(inplace =True)
         df_list.append(df)
    print(df_list)

    return df_list

def att_merge(df_list):
    count = len(df_list)

    if count == 1:
        result = df_list[0]

    elif count == 2:
        result = pd.concat([df_list[0], df_list[1]], ignore_index=True)

    else:
        temp = df_list[0]
        for i in range(1, count):
            result = pd.concat([temp, df_list[i]], ignore_index=True)
            temp = result

    print(result)
    result.to_excel("outlook결과파일.xlsx")


###첨부파일 다운로드 하기
fn = "받은편지함 폴더명"
downpath = "첨부파일 다운받을 경로"
att_down(fn, downpath)
df_list = att_df(downpath)
att_merge(df_list)

728x90