본문 바로가기

코딩/업무자동화

[파이썬/업무자동화] 여러개 pdf 파일 1개로 합치기(+엑셀 응용)

반응형

 

 

  이전 업무자동화 포스팅 중 여러개의 엑셀 파일을 시트별로 pdf로 변환하는 방법에 대해서 작성한 적이 있다. 이번에는 '여러개의 엑셀 파일(또는 여러개 엑셀 시트)을 1개 pdf 파일로 변환하려면 어떻게 하면 좋을까?'를 생각하다가 작성하는 포스팅이다.

(관련 포스팅 : 2021.06.21 - [코딩/업무자동화] - [파이썬/업무자동화] 엑셀 파일 시트별 pdf 저장/변환하기)

 

  구글링을 해보니 파이썬에서 PyPDF2 라는 라이브러리를 제공한다고 한다. PyPDF2는 파이썬에서 PDF 파일을 분할하거나 합칠 수 있는 라이브러리이다. 엑셀파일을 각각 시트별로 pdf로 모두 변환한 후, PyPDF2 라이브러리를 통해 1개 pdf 파일로 결합할 수 있다.

 

  이번 포스팅에서는 엑셀 파일 시트를 모두 각각 pdf 파일로 만들었다고 가정하고 그 결과물을 합치는 코드를 작성하는데 목적을 두었다. 추가로 합친 pdf 파일을 다시 1페이지씩 분리하는 코드까지 작성해볼 것이다. 엑셀 파일 시트를 각각 pdf로 변환하는 방법은 위 관련 포스팅 링크를 참고하자.

 

 

 

1. PyPDF2 라이브러리 설치

 

  PyPDF2는 파이썬 내장 라이브러리가 아니기 때문에, 따로 설치가 필요하다. 본인 개발 환경에 맞게 PyPDF2를 설치하도록 하자.

 

#개발환경 터미널창에 입력
pip install PyPDF2

 

 

  글쓴이의 PC에는 이미 설치가 완료되었기 때문에 pip install을 하면 'Requirement already statisfied : PyPDF2' 라는 메시지가 출력된다.

 

 

 

2. pdf 파일 합치기

 

  여러 pdf 파일을 합치는 방법은 PyPDF2 라이브러리의 PdfFileMerger 라는 클래스를 사용하면 된다. PdfFileMerger 클래스 내부를 살펴보면 여러 메서드가 있는데 내가 작성한 코드에서는 append 메서드를 사용했다.

 

< 참고 : PdfFileMerger 클래스 내부 메서드 >

 

  합칠 pdf 파일은 아래 내가 가지고 있는 pdf 악보파일 3개이다. 각각의 pdf 파일은 6 page씩 내용을 가지고 있다.

 

<합칠 대상>

 

 

<코드>

from PyPDF2 import PdfFileReader, PdfFileMerger
import os


def PDFMerger(path):
    #PdfFileMErger 클래스 인스턴스 선언
    pdf_merge = PdfFileMerger()
    
    #경로에 있는 pdf파일명 리스트로 저장
    pdflist = os.listdir(path)
    
    #위 리스트를 for문을 통해 반복
    for pdf in pdflist:
        #위에서 선언했던 객체 pdf_merge에 합칠 pdf파일 객체들을 추가
        pdf_merge.append(PdfFileReader(open(path+"/"+pdf, 'rb')))
    
    #결합한 pdf_merge 객체를 저장하는 과정
    pdf_merge.write(r"C:\Users\Desktop\VS CODE\Project\MergePDF\result.pdf")
    
    
 if __name__ == "__main__":
    #합칠 pdf파일 있는 경로
    path1 = r"C:\Users\Desktop\VS CODE\Project\MergePDF\test파일"
    
    #함수 실행
    PDFMerger(path1)

 

 

<결과>

pdf 파일 결합 결과 - result.pdf

 

 

  결과는 악보파일1,2,3(각 6 page)가 합쳐져 총 18 page의 pdf 파일 result.pdf가 생성된 것을 확인할 수 있다. 참고로 append 함수의 내부 매개변수는 fileobj(=File Object)이다. 즉, 파일위치(경로) 문자열을 입력하면 오류가 난다. 파일 객체 형태로 입력해주어야하기 때문에 PdfFileReader라는 클래스를 사용하여 또 다른 객체를 매개변수로 입력해야 한다.

 

 

반응형

 

 

3. pdf 파일 분리

 

  이번 코드는 위 2번에서 결과파일로 나온 result.pdf(총 18 page) 파일을 각각 1 page 씩 분리하여 총 18개 pdf 파일로 만들어보도록 하겠다. pdf 파일을 분리할 때는 PyPDF2 라이브러리의 PdfFileWriter라는 클래스를 사용하면 된다. 코드의 설명은 주석으로 대신하도록 한다.

 

 

<코드>

from PyPDF2 import PdfFileReader,PdfFileWriter
import os

def PDFsplit(path):
    #경로에 있는 pdf파일명 리스트로 저장
    pdffile = os.listdir(path)
    
    #위 리스트를 for문을 통해 반복
    for pdf in pdffile:  
        #pdf 파일 객체 생성
        pdf = PdfFileReader(path + "/" + pdf)    
        #생성한 객체 pdf의 페이지 수를 정수로 저장
        total_page = pdf.getNumPages()
        #pdf 파일 page 별로 Writer 통해 객체에 추가
        for page in range(total_page):
            pdf_writer = PdfFileWriter()
            pdf_writer.addPage(pdf.getPage(page))

            #분리한 각 pdf 파일 객체를 저장하는 과정
            with open("C:/Users/Desktop/VS CODE/Project/MergePDF/"+ str(page) + "_page.pdf", 'wb') as fh:
                pdf_writer.write(fh)
          


if __name__ == "__main__":
   
    #분리 할 pdf 파일이 있는 경로
    path2 = r"C:\Users\Desktop\VS CODE\Project\MergePDF\test파일2"
    #분리 함수 실행
    PDFsplit(path2)

 

<결과>

< 분리 결과 >

결과 이미지를 보면 resut.pdf 파일이 각 1 page씩  총 18개로 분리되었다.

 

 

 

4. 엑셀 응용(모든 엑셀 파일의 정보를 1개 pdf 파일로)

 

  다시 이전 포스팅 내용으로 돌아가서 기능을 추가해보자. 이전 포스팅에서는 여러 엑셀파일을 각 시트 별로 분리해서 pdf 로 저장하는 코드를 작성했다. 여기에 위 PDFMerger 함수를 추가하면 분리된 각 pdf 시트를 1개로 합칠 수 있다. 각 엑셀 파일을 pdf로 저장하는 내용은 아래 링크를 참고하면 된다. 

(이전 포스팅 : 2021.06.21 - [코딩/업무자동화] - [파이썬/업무자동화] 엑셀 파일 시트별 pdf 저장/변환하기)

 

  아래 전체 코드는 이전 포스팅 코드에서  + PDFMerger 함수만 추가한 내용이다. 복사가 불가능하면 아래 첨부파일을 업로드하였으니 참고!!

 

 

<전체 코드>

import win32com.client
import openpyxl as op
import os
from PyPDF2 import PdfFileMerger, PdfFileReader


def excelInfo(filepath):
    excel_list = os.listdir(filepath) #폴더안에 잇는 엑셀파일 명을 리스트로 저장
    result = [] #빈 리스트 생성
    for file in excel_list: #엑셀파일명 리스트를 for문을 통해 반복
        wb = op.load_workbook(filepath+"/"+file) #openpyxl workbook 생성
        ws_list = wb.sheetnames #해당 workbook의 시트명을 리스트로 받음
        filename = file.replace(".xlsx","") #파일명을 저장하기 위해 문자열에서 확장자 제거
        for sht in ws_list: #시트명 리스트를 for문을 통해 반복
            temp_tuple = (filepath+"/"+file, filename, sht) #파일경로, 파일명, sht를 튜플에 저장
            result.append(temp_tuple) #위 튜플을 빈 리스트에 추가
    print(result)
    return result # 튜플로 이루어진 리스트 리턴


def transPDF(fileinfo, savepath):

    excel = win32com.client.Dispatch("Excel.Application")
    i=0 #파일명 중복을 방지하기 위한 인덱싱 번호
    
    #excelinfo를 입력받아 for문 실행
    for info in fileinfo:
        wb = excel.Workbooks.Open(info[0]) #info가 튜플이므로 인덱싱으로 접근(0번째는 파일경로)
        ws = wb.Worksheets(info[2]) #튜플의 2번째 요소는 시트명임. 

        ws.Select() #위 설정한 시트 선택
        wb.ActiveSheet.ExportAsFixedFormat(0, savepath+"/"+str(i)+"_"+info[1]+"_"+info[2]+".pdf") #파일명, 시트명으로 pdf 파일명 저장
        i=i+1
        wb.Close(False) #workbook 닫기, True일 경우 그 상태를 저장한다.
        excel.Quit()  # excel application 닫기

def PDFMerger(path):
    #PdfFileMErger 클래스 인스턴스 선언
    pdf_merge = PdfFileMerger()
    
    #경로에 있는 pdf파일명 리스트로 저장
    pdflist = os.listdir(path)
    
    #위 리스트를 for문을 통해 반복
    for pdf in pdflist:
        #위에서 선언했던 객체 pdf_merge에 합칠 pdf파일 객체들을 추가
        pdf_merge.append(PdfFileReader(open(path+"/"+pdf, 'rb')))
    
    #결합한 pdf_merge 객체를 저장하는 과정
    pdf_merge.write("result.pdf")


if __name__ == "__main__":
    filepath = r"C:\Users\Desktop\VS CODE\Project\pdf_transform\새 폴더"
    pdfpath = r"C:\Users\Desktop\VS CODE\Project\pdf_transform\분리파일"
    
    #엑셀파일의 파일경로, 파일명, sht 정보를 저장하는 함수 실행
    excelinfo = excelInfo(filepath)
    
    #위 excelinfo 리턴값을 받아서 pdf로 각 시트를 저장하는 함수 실행
    transPDF(excelinfo, pdfpath)
    
    #tranPDF 함수 통해 저장된 pdf파일을 합치기
    PDFMerger(pdfpath)

 

<첨부파일>

ExcelPDF+mergePDF.zip
0.00MB


※ 참고링크

https://python-explorer.tistory.com/14

https://nadure.tistory.com/29

https://blog.naver.com/goglkms/221817310571

 

728x90