Python으로 파워포인트 내용 변경하기

가끔 파워포인트 파일 여러 개의 내용을 일괄적으로 변경해야 하는 경우가 있다. 이때 하나씩 하다보면 단순 반복 작업에 매우 지치고 귀찮음을 느끼게 된다.

pptx 파일 포맷은 XML 기반의 파일이 압축된 형태이기 때문에, 압축을 풀고 XML을 편집하면 일괄 변경할 수 있다.

주의: 이 글의 작성자는 pptx 파일 포맷에 대한 깊은 이해가 있지 않고, 슬라이드의 단순 링크 변경이 목표이다.

목표: a.pptx에 있는 모든 http://a.com/ 링크를 http://b.net/로 바꾸는 것

파일 a.pptx가 있을때, 확장자를 zip으로 변경하면 압축을 풀 수 있고, 내용물을 볼 수 있다.

압축을 해제하니 3개의 폴더 (_rels, docProps, ppt)와 1개의 파일 ([Content_Types].xml)가 있고, 폴더를 살펴보니 ppt/slides에 슬라이드 내용이 있는 것을 확인할 수 있다.

K페이지의 내용은 slideK.xml에 있고, 링크와 관련된 정보는 _rels/slideK.xml.rels에 있다.

어차피 링크만 바꾸는 것이 목적이기 때문에, XML을 파싱할 필요는 없다. XML 파일을 문자열로 읽고, 문자열 변경을 한 다음 다시 문자열 저장을 했다.

아래 go(f)는 파일 f에 들어있는 링크를 변경하는 함수이다. 파일 f의 파일명을 temp.zip으로 바꾸고, temp/ 에 압축을 푼다. 그 다음 적절한 처리를 하고 다시 temp.zip으로 압축한다. 마지막으로 파일명을 다시 f로 변경한다.

def go(f):
    # pptx -> zip
    f_zip = 'temp.zip'
    os.rename(f, f_zip)

    # unzip
    os.system('unzip -q -d temp %s' % f_zip)
    os.system('rm %s' % f_zip)

    find_xml()

    # zip again
    os.system('cd temp; zip -q -r9 ../%s *' % f_zip)
    os.system('rm -rf temp')

    # zip -> pptx
    os.rename(f_zip, f)

find_xml()ppt/slides/slideK.xml, ppt/slides/_rels/slideK.xml.rels 를 모두 찾는다.

def find_xml():
    slide_folder = 'temp/ppt/slides/'
    for f,d,files in os.walk(slide_folder):
        for fname in files:
            if '.xml' not in fname:
                continue
            print (f, d, fname)
            xml_file = os.path.join(f, fname)
            convert(xml_file)

convert(xml_file)은 XML 파일 xml_file에 있는 모든 링크를 원하는대로 변경하는 함수이다.

def convert(xml_file):
    with open(xml_file, 'r') as fp:
        s = fp.read()
    s = s.replace('http://a.com/', 'http://b.net/')
    with open(xml_file, 'w') as fp:
        fp.write(s)

좀 더 섬세한 작업을 하려면 XML을 파싱하거나 정규 표현식을 사용하면 될 것 같다. XML을 파싱하면 배경 색상 변경, 폰트 변경, 문단 설정 변경 등도 할 수 있지만, 현재는 그런 작업은 필요가 없어서 해보지 않았다.