파이썬 - 파워포인트 편지봉투 출력하기

2025. 2. 2. 20:38IT

드디어 계획을 했던 프로젝트, 편지 봉투에 주소록을 읽어와 출력하는 것을 만들어 보겠습니다. 앞서서 기초적인 사항들을 모두 훑어봤기 때문에 하나씩 하나씩 조합을 해 나가면 될 것 같습니다. 

완성되지도 않은 프로그램 코드를 보니 90여줄이 됩니다. 기존과 같이 파이참을 스크린샷 뜨는 것도 안됩니다. 그래도 전체 코드는 있어야 참고가 될 것 같아 우선 다음과 같이 넣었습니다. 이 코드는 편지봉투를 열기 → 파워포인트 업데이트를 위한 슬라이드 내 구성요소 목록 만들기 → 주소록 열기 → for문의 형태로 되어 있습니다. 다시 for문으로 들어가면 제목을 뺀 두 번째 부터 100번째까지 반복을 하도록 되어 있는데 그 순서는 받는 사람 출력하기 → 주소 출력하기 → 우편번호 출력하기 → 새로운 페이지 만들어 구성요소들 복사해 넣기의 순서로 이루어져 있습니다. 먼저 코드를 살펴보시기 바랍니다.

 

039_envelopAddr.py

 import collections

 import collections.abc

 from pptx import Presentation

 from pptx.util import Pt

 from pptx.dml.color import RGBColor

 import copy

 import openpyxl

 

 # 편지봉투 열기

 prs = Presentation(r".\files\mail.pptx")

 slide = prs.slides[0]

 shape_list = slide.shapes

 shape_idx = {}

 source_slide = prs.slides[0]

 

 for idx, value in enumerate(shape_list):

shape_idx[value.name] = idx

 

 # 주소록 열기

 wb = openpyxl.load_workbook(r".\files\codefilex.xlsx")

 ws = wb['codefilex']

 

 for i in range(2, 100): # 첫번째 줄은 제목이 나타남

      name = f"{ws.cell(i, 2).value} {ws.cell(i, 3).value} 귀하"

postcode = ws.cell(i, 6).value

addr = ws.cell(i, 7).value

 

# print(name, postcode, addr)

### 받는 사람

shape = shape_list[shape_idx['name']]

text_frame = shape.text_frame

text_frame.clear()

p = text_frame.paragraphs[0]

run = p.add_run()

run.text = name

 

font = run.font

font.name = '맑은 고딕'

font.size = Pt(18)

font.bold = True

font.italic = None

font.color.rgb = RGBColor(0, 0, 0)

 

### 주소

shape = shape_list[shape_idx['address']]

text_frame = shape.text_frame

text_frame.clear()

p = text_frame.paragraphs[0]

run = p.add_run()

run.text = addr

 

font = run.font

font.name = '맑은 고딕'

font.size = Pt(16)

font.bold = True

font.italic = None

font.color.rgb = RGBColor(0, 0, 0)

 

### 우편번호

shape = shape_list[shape_idx['pCode1']]

text_frame = shape.text_frame

text_frame.clear()

p = text_frame.paragraphs[0]

run = p.add_run()

try:

     run.text = postcode

except:

  ...

 

font = run.font

font.name = '맑은 고딕'

font.size = Pt(14)

font.bold = True

font.italic = None

font.color.rgb = RGBColor(0, 0, 0)

 

### 편지봉투 복사

slide_layout = prs.slide_layouts[6] # 빈 페이지

copy_slide = prs.slides.add_slide(slide_layout)

 

for shape1 in source_slide.shapes:

     el = shape1.element

     newel = copy.deepcopy(el)

     copy_slide.shapes._spTree.insert_element_before(newel, 'p:extLst')

 

prs.save(r".\files\envelops.pptx")

 

프로그램 코드를 본 소감이 어떠신가요? 복잡하게 느껴지나요? 차근차근 살펴보시면 모두 앞에서 배웠던 코드들입니다. 좀 길고 중복된 부분이 있어서 그렇지 처음 보는 코드는 아닙니다. 우선 실행을 시켜 보겠습니다. 그리고 그 결과를 보면 다음과 같습니다.

 

 

우리가 원하는대로 두번째 부터 100번째까지의 주소록을 모두 파워포인트에 각각 출력하는 것은 성공한 듯 보입니다만, 출력된 것이 영 깔끔하지가 않습니다.

첫번째로 받는 사람의 은행명과 지점명 그리고 ‘귀하’가 너무 멀리 떨어져 있어 수정이 필요해 보입니다. 두 번째는 우편번호입니다. 코드가 너무 길어질 것 같아서 우선 첫번째 박스에 우편번호를 모두 출력하도록 코딩을 한 탓에 첫번째 줄에 세로로 나타납니다. 이 부분도 수정을 해야겠습니다. 먼저 코드들을 간단하게 살펴보고 수정해야 할 부분에 대해서도 이야기해 볼까 합니다.

 

 import collections

 import collections.abc

 from pptx import Presentation

 from pptx.util import Pt

 from pptx.dml.color import RGBColor

 import copy

 import openpyxl

 

이미 한번씩 다 살펴본 내용입니다. python-pptx에서 사용하는 collections와 collections.abc를 import했고 다음은 파워포인트를 자체와 폰트의 크기를 지정하는데 사용하는 Pt, 폰트의 색상을 지정할 때 사용하는 RGBColor 클래스를 import 했습니다. 그리고 deepcopy를 사용하기 위한 파이썬 내장 패키지 copy도 import했습니다. 마지막으로 엑셀 주소록을 하나 하나씩 살펴보기 위한 openpyxl이 있습니다.

 

 # 편지봉투 열기

 prs = Presentation(r".\files\mail.pptx")

 slide = prs.slides[0]

 shape_list = slide.shapes

 shape_idx = {}

 source_slide = prs.slides[0]

 

 for idx, value in enumerate(shape_list):

shape_idx[value.name] = idx

 

Presentation 클래스를 이용해 편지봉투 파워포인트 파일을 열고 shape_idx라는 딕셔너리를 만듭니다. 파이썬에서 파워포인트의 어떤 내용을 변경하거나 참조하기 위해서는 파워포인트 내의 구성요소인 shape가 몇 번째 위치하고 있는지를 알아야 합니다. 우리가 파워포인트의 구성요소들에 부여한 이름을 가지고 몇 번째 위치에 있는지를 파악하기 위해서 딕셔너리를 만들어 둡니다. 

그리고 원본 슬라이드를 가지고 있어야 새로운 슬라이드를 추가할 때 사용할 수 있으므로 source_slide에 프리젠테이션 파일의 첫번째 슬라이드를 저장합니다. 컴퓨터에선 0부터 숫자를 세는 것이 기본이라 사람 기준의 첫번째 슬라이드는 컴퓨터 기준 0번째가 됩니다. 그래서 slides[0]으로 표기합니다.



# 주소록 열기

wb = openpyxl.load_workbook(r".\files\codefilex.xlsx")

ws = wb['codefilex']

 

엑셀로 된 주소록 파일을 열고 실제 데이터가 들어 있는 ws에 ‘codefilex’라는 시트를 할당해 둡니다. 

 

 for i in range(2, 100): # 첫번째 줄은 제목이 나타남

name = f"{ws.cell(i, 2).value} {ws.cell(i, 3).value} 귀하"

postcode = ws.cell(i, 6).value

addr = ws.cell(i, 7).value

 

for 반복문의 시작입니다. 이 for 문에서는 제목을 뺀 두 번째 줄 부터 100번째 줄까지 총 99개 줄의 정보를 읽습니다. name에 저장되는 값은 엑셀의 두번째 컬럼에 있는 은행명과 세번째 컬럼에 있는 지점명에 ‘귀하’를 더한 값입니다. postcode는 6번째 컬럼에 있는 우편번호가 그대로 저장이되고, addr에는 7번째 컬럼에 있는 주소가 각각 저장됩니다. 나중에 코드를 보고 읽기 쉽게 이름을 부여했습니다. 

 

### 받는 사람
 shape =  
shape_list[shape_idx['name']]
 text_frame =   
 shape.text_frame 
 text_frame.clear()
 p = text_frame.paragraphs[0]
 run = p.add_run()
 run.text = name


 font = run.font
 font.name = '맑은 고딕'
 font.size = Pt(18)
 font.bold = True
 font.italic = None
 font.color.rgb = RGBColor(0, 0, 0)
### 주소
 shape = shape_list[shape_idx['address']]
 text_frame = shape.text_frame
 text_frame.clear()
 p = text_frame.paragraphs[0]
 run = p.add_run()
 run.text = addr


 font = run.font
 font.name = '맑은 고딕'
 font.size = Pt(16)
 font.bold = True
 font.italic = None
 font.color.rgb = RGBColor(0, 0, 0)
### 우편번호
 shape = shape_list[shape_idx['pCode1']]
 text_frame =  shape.text_frame 
 text_frame.clear()
 p = text_frame.paragraphs[0]
 run = p.add_run()
 run.text = postcode


 font = run.font
 font.name = '맑은 고딕'
 font.size = Pt(14)
 font.bold = True
 font.italic = None
 font.color.rgb =  RGBColor(0, 0, 0)

 

다음은 for문에서 ‘받는 사람’, ‘주소’ 그리고 ‘우편번호’를 파워포인트에 직접 입력하는 부분입니다. 앞에서 이미 설명 드렸지만 우편번호는 맨 첫 칸에 다섯자리를 모두 출력했습니다. 나중에 이 부분은 각각의 다섯 칸에 나누어 출력하도록 수정을 할 예정입니다. 그러면 우편번호 부분이 한 개에서 다섯개로 늘어나서 위의 세 칸이 아니라 총 7칸으로 늘어나게 됩니다. for 문이 지금보다도 더 늘어나게 된다는 얘기죠.

 

그런데 세 칸을 좌우로 비교해 보면 많은 부분이 동일하죠. 총 13줄이고 그 중에서 다른 부분은 shape_idx 딕셔너리에 넣어 주는 파워포인트의 구성요소 이름, 실제로 파워포인트에 입력이 될 run.text에 들어갈 정보가 있는 부분, 마지막으로 폰트 크기 부분만 다릅니다. 이렇게 동일한 부분이 대부분이고 특정 부분만 바뀌는 것들은 함수로 바꿀 수 있습니다. 바뀌는 부분은 매개변수로 넘겨주면 됩니다. 

 

현재 13줄 X 3 = 39줄인데 함수로 만들면 절반 이하로 만들 수 있습니다. 나중에 우편번호까지 다섯개로 나누게 되면 총 소스코드는 13 X 7 = 91줄이 될 것이고 함수를 만들면 20줄 내외로 줄어들지 않을까 예상이 됩니다. 이처럼 유사하게 반복되는 부분을 함수로 만들면 이해하기도 쉽고 소스코드의 양도 줄어드는 긍정적인 효과가 있습니다. 

 

 ### 편지봉투 복사

 slide_layout = prs.slide_layouts[6] # 빈 페이지

 copy_slide = prs.slides.add_slide(slide_layout)

 

 for shape1 in source_slide.shapes:

el = shape1.element

newel = copy.deepcopy(el)

copy_slide.shapes._spTree.insert_element_before(newel, 'p:extLst')

 

for문의 마지막은 편지 봉투를 복사하는 것입니다. 빈 페이지를 만들고 거기에 각 엘리먼트를 복사해 넣음으로써 새 페이지를 만듭니다. 

 

 prs.save(r".\files\envelops.pptx")

 

마지막으로 지금까지 만든 슬라이드를 envelops.pptx로 저장을 합니다.



반응형