인프런 커뮤니티 질문&답변

dein01님의 프로필 이미지
dein01

작성한 질문수

직장인에게 꼭 필요한 파이썬-아래아한글 자동화 레시피

pdf 로 바꿀때 특정 페이지 까지바꿀 수 있나요?

해결된 질문

작성

·

1.2K

1

제가 파이썬으로 hwp를 다루고 있는데요~

 

가령 전체 10페이지 인데, 현재 케럿이 8페이제 위치해 있고

 

처음부터 8페이지 까지만 pdf로 저장되도록 하는게 가능한지요??

답변 1

1

일코님의 프로필 이미지
일코
지식공유자

아래와 같은 한/글 파일이 있다고 가정해봅시다.

image

제 커서는 현재 8페이지에 위치하고 있습니다.
우선 아래 코드를 참고해주시고,

import os

import win32com.client as win32

hwp = win32.gencache.EnsureDispatch("hwpframe.hwpobject")
hwp.XHwpWindows.Item(0).Visible = True
hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule")
hwp.Run("FileOpen")


def pdf_to_here():
    hwp.Run("MovePageEnd")  # 현재 페이지 마지막으로 이동해서
    hwp.Run("MoveSelDocEnd")  # 문서 끝까지 선택한 후
    hwp.Run("Delete")  # 임시로 삭제
    hwp.SaveAs(Path=os.path.join(os.getcwd(), "result.pdf"), Format="PDF")
    hwp.Run("Undo")  # 삭제 취소
    return hwp.HAction.Run("Cancel")  # 선택 취소(성공시 True 리턴)
    
# 8페이지 접근 후에

pdf_to_here()

 

파이썬 콘솔에서 pdf_to_here() 함수를 실행해보겠습니다.

image

의도하신 대로 잘 실행되었는지요?^^

dein01님의 프로필 이미지
dein01
질문자

우왕 고퀄 답변 감사합니다

선생님 그런데, 제가 상황을 자세히 전달 못드렸네요

 

제가 미주가 많은 파일에서

미주를 제외한 앞부분만 인쇄( 학습지에서 해설을 제외한 문제만 인쇄해야 하는 상황)

입니다. 그래서 지웠다가 인쇄하는 솔루션이 안될거 같은데 혹시 다른 방법이 있을까요??

일코님의 프로필 이미지
일코
지식공유자

혹시 이렇게는 어떨까요?
(다른 방법도 있으니, 의도대로 실행 안 되면 다시 알려주시기 바랍니다^^)

import os

import win32com.client as win32

hwp = win32.gencache.EnsureDispatch("hwpframe.hwpobject")
hwp.XHwpWindows.Item(0).Visible = True
hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule")
hwp.Run("FileOpen")


def pdf_to_here():
    hwp.Run("MovePageEnd")
    hwp.Run("MoveSelDocBegin")
    pset = hwp.HParameterSet.HFileOpenSave
    hwp.HAction.GetDefault("FileSaveBlock_S", pset.HSet)
    pset.filename = hwp.Path.replace(".hwpx", "#q.pdf").replace(".hwp", "#q.pdf")
    pset.Format = "PDF"
    pset.Attributes = 1
    hwp.HAction.Execute("FileSaveBlock_S", pset.HSet)
    return hwp.HAction.Run("Cancel")


# 페이지 접근 후에
pdf_to_here()

image

질문 남겨주셔서 감사해요.
행복한 하루 되세요^^

dein01님의 프로필 이미지
dein01
질문자

빠른 답변 진심으로 감사 드립니다

 

선생님 저 상황에서 저장 경로를 바탕화면이 아니라 원하는 곳에 하려면 어찌 수정 해야 하나요??

일코님의 프로필 이미지
일코
지식공유자

첫 번째 답변의 코드는 코드 실행위치에 저장하는 방식,
두 번째 답변의 코드는 해당 hwp 파일이 있는 폴더 안에 같이 저장하는 방식입니다.

특정 폴더에 따로 저장하고 싶으시면

아래 라인을

pset.filename = hwp.Path.replace(".hwpx", "#q.pdf").replace(".hwp", "#q.pdf")

 

아래 방식으로 바꿔주시면 됩니다. (예를 들자면요)

pset.filename = r"c:\users\사용자\desktop\20230218_문제모음\result.pdf"

그리고 해당 폴더가 미리 생성되어 있어야 오류가 나지 않습니다.

 

조금 더 응용해서
기존 hwp파일명에서 조금 보탠다든지 수정하고 싶으시다면
아래처럼 바꾸시면 되고요.

target_folder = r"c:\users\사용자\desktop\문제모음"  # 폴더경로
pset.filename = os.path.join(target_folder, os.path.basename(hwp.Path).replace(".hwp", "#1.hwp"))
dein01님의 프로필 이미지
dein01
질문자

감사합니다! 한번작업할때마다 적어도 1분은 아낄 수 있게 되었습니다!

일코님의 프로필 이미지
일코
지식공유자

아이고 감사하다고 해주시니 기쁩니다.
질문 있으면 정말 언제든 남겨주세요.

강의를 늘리자니 점점 번잡해지는 것 같아서
조심스럽습니다ㅜ

행복한 하루 되세요^^

dein01님의 프로필 이미지
dein01
질문자

인프런이라는 좋은 플렛폼으로 선생님과 이렇게 대화 할 수 있어서 참 감사하네요

응원합니다 건승하십시오!

dein01님의 프로필 이미지
dein01
질문자

하나만 더 어쭈어도 될까요??

 

현재 띄어져 있는 한글 파일을 활성화 시키는 코드가 있나요??

 

제가 한글을 띄어놓고 작업하다가 중간에 파이썬을 작동시키는 흐름을 갖는 작업흐름이라

 

기존에는 한글띄우는것부터 시작하니, 상관 없었는데.. 시작을 어찌 해야 할지 모르겠습니다

 

정확하게는

보통은 아래 코드로 일을 시작했는데 이건 빈 새창을 띄워서 여기에 파일을 여는 과정이었다면 지금은 현재 열려있는 창에 대하여 파이썬으로 제어 하려고 하는것입니다

hwp = win32com.client.gencache.EnsureDispatch("hwpframe.hwpobject")
hwp.XHwpWindows.Item(0).Visible = True
hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule")
hwp.Run(hwp_path)
일코님의 프로필 이미지
일코
지식공유자

저도 그 부분을 아직 해결하지 못했습니다.. API문서에는 접근방법이 상세히 씌어 있는데, 파이썬으로 그대로 해보면 오류가 나요ㅠㅠ 대신 알게 되는 즉시 이 질문글에 바로 남겨놓겠습니다^^

dein01님의 프로필 이미지
dein01
질문자

그렇군요^^..

 

그럼 대안으로 마지막페이지에서 한장 앞의 페이지로 이동하려면 어떤 명령어가 있을까요??

제가 문제지 마지막장에 빠른 정답이 있고

다음페이지부터 미주에 해당하는 해설들이 있어서

 

빠른정답 까지 가리고 인쇄 되게 해야하는 상황이라 마지막 페이지로 가는 명령어

hwp.HAction.Run("MoveTopLevelEnd")

를 준다음에 한페이지 앞으로 이동해서 인쇄 걸려고 합니다^^

일코님의 프로필 이미지
일코
지식공유자

hwp.HAction.Run("MovePageUp")

쓰시는 것을 추천드립니다.
대신 블록 선택으로 인쇄하실 거라면

hwp.HAction.Run("MoveTopLevelEnd")
hwp.HAction.Run("MovePageUp")
hwp.HAction.Run("MovePageEnd")
hwp.HAction.Run("MoveSelDocBegin")

이런 식으로, 마지막 앞페이지의 전체를 선택할 수 있게 하셔야 해요^^

 

dein01님의 프로필 이미지
dein01
질문자

아이공 선생님 이게 쉽지가 않네요 ㅠ^2

 

문제점이 2가지가 있는데요

하나는 폰트가 날아갑니다.

두번째는 지금 주신 코드가 혹시 복사해서 붙혀 넣고 인쇄하는 시스템으로 보이는데

미주는 복사해서 붙혀넣으면 딸려오기 때문에 의도했던 해설이 인쇄되는것을 막지를 못하네요 ㅠ

일코님의 프로필 이미지
일코
지식공유자

그러면 좋은 방법이 있습니다^^

전체 페이지를 PDF로 인쇄해버린 후에

PDF파일을 직접 조작해서,

마지막 페이지를 날려버리는 방법이에요.

아래 코드 실행하시기 전에 터미널에서 `pip install pypdf2' 로 모듈 설치하셔야 해요!^^

import win32com.client as win32
from PyPDF2 import PdfWriter, PdfReader


hwp = win32.gencache.EnsureDispatch("hwpframe.hwpobject")
hwp.XHwpWindows.Item(0).Visible = True
hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule")
hwp.Run("FileOpen")

# 페이지 접근 후에
마지막페이지 = hwp.PageCount
PDF파일명 = hwp.Path.replace(".hwpx", "#q.pdf").replace(".hwp", "#q.pdf")
hwp.SaveAs(Path=PDF파일명, Format="PDF")


지울페이지 = [마지막페이지-1, 마지막페이지-2]  # 0부터 카운트(끝에서 두 페이지 삭제)
입력PDF = PdfReader(PDF파일명, "rb")
출력PDF = PdfWriter()

for i in range(len(입력PDF.pages)):
    if i not in 지울페이지:
        p = 입력PDF._get_page(i)
        출력PDF.add_page(p)

with open(PDF파일명, 'wb') as f:
    출력PDF.write(f)

hwp.Clear(0)
hwp.Quit()

 실행해보면...

image

 

 

dein01님의 프로필 이미지
dein01
질문자

선생님 잠시만요!! 해설 페이지가 가변적입니다!

문제들이 미주로 해설이 되어 있어서

문제들이 많으면 미주페이지들도 많아 집니다!!

일코님의 프로필 이미지
일코
지식공유자

그럼 모든 문제에 미주가 달려 있겠네요?ㅎ

제가 생각하는 해법은,

[미주] 및 [번호달기] 컨트롤이 있는 마지막 페이지가

해설 직전 페이지라고 가정하고

거기까지만 출력하는 거예요.

메일 받았어요ㅎ 테스트해볼게요ㅋ

번호넣기가 연속으로 들어가는 페이지가 해설페이지 시작이라고 봐도 되겠네요?

image

dein01님의 프로필 이미지
dein01
질문자

아이고 너무 감사합니다

빠른 정답직전 까지 (테스트 페이지 기준으로 20p 까지 )pdf변환이 목표입니다

너무 감사해서 어찌 해야 할지 모르겠네요

dein01님의 프로필 이미지
dein01
질문자

네 맞습니다!

일코님의 프로필 이미지
일코
지식공유자

대충 테스트를 마친 것 같은데,

아래 코드로 한 번 실제문서에 적용해보시겠어요?

!pip install pypdf2  # pypdf2 모듈을 꼭 설치하셔야 합니다.
import win32com.client as win32
from PyPDF2 import PdfWriter, PdfReader


hwp = win32.gencache.EnsureDispatch("hwpframe.hwpobject")
hwp.XHwpWindows.Item(0).Visible = True
hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule")
hwp.Run("FileOpen")


ctrl = hwp.LastCtrl  # 마지막 컨트롤에서부터
while ctrl:
    if ctrl.UserDesc == "미주":  # 가장 먼저 만나는 (마지막) 미주에 닿으면
        break  # while 문 종료.
    ctrl = ctrl.Prev  # 그 전까지는 계속 이전 컨트롤 조회
hwp.SetPosBySet(ctrl.GetAnchorPos(0))  # 마지막 미주가 있는 곳으로 캐럿 이동
출력할마지막페이지 = hwp.KeyIndicator()[3] + 2  # 처음 두 페이지 고려(1페이지 이전에 두 페이지가 있어서)
문서마지막페이지 = hwp.PageCount  # 1부터 카운트

PDF파일명 = hwp.Path.replace(".hwpx", "#q.pdf").replace(".hwp", "#q.pdf")
hwp.SaveAs(Path=PDF파일명, Format="PDF")  # 전체 문서를 PDF로 변환

지울페이지 = list(range(출력할마지막페이지, 문서마지막페이지))  # 이건 0부터 카운트 시작
입력PDF = PdfReader(PDF파일명, "rb")  # 방금 저장한 PDF파일을
출력PDF = PdfWriter()  # 새로운 PDF에 한페이지씩 담기

for i in range(len(입력PDF.pages)):  # 0부터 전체페이지까지 순회하면서
    if i not in 지울페이지:  # 지울페이지에 포함되지 않은 (출력할) 페이지일 때만
        p = 입력PDF._get_page(i)  # 원본PDF에서 페이지를 가져와서
        출력PDF.add_page(p)  # 새로운 PDF에 하나씩 담기.

with open(PDF파일명, 'wb') as f:  # 다 담았으면 해당 바이너리 데이터를
    출력PDF.write(f)  # PDF문서로 만들기

hwp.Clear(1)  # 한/글 문서는 닫고(변경사항 버리고)
hwp.Quit()  # 한/글 종료

image

 현재 코드는 마지막 미주(31번 문제번호)가 있는 페이지까지 남기고 이후는 지우는 방식이에요.

번호뒤로 어정쩡하게 지문이나 수식이 다음 페이지로 넘어가는 일은 없겠죠?^^;

 

dein01님의 프로필 이미지
dein01
질문자

답변 감사합니다, 그냥 복붙하니 잘 안되어서 역시 제가 공부를 통해

이해하고 쓰는 과정이 필요 할거 같습니다

답변주신것들을 여러번 읽으면서 이해해서 다시한번 시도 해보겠습니다^^ 귀한 자료 감사합니다.

혹시 캐럿이 위치한 페이지를 파이썬에서 인식하는 코드가 없나요??

마지막 페이지로 이동후 (미주직전) 윗페이지로 이동 한다음

그 페이지 넘버를 알면

1페이지부터, 마지막페이지 넘버까지 한장씩 pdf 인쇄해서 합치는 구조

인데, 마지막 페이지를 알기위해 미주번호를 이용하신거 같아서요

일코님의 프로필 이미지
일코
지식공유자

캐럿이 위치한 페이지는

hwp.KeyIndicator()[3]

으로 알 수 있습니다ㅎ

제 컴퓨터에서만 실행된다니 이상하네요..

혹시 문서가 달라서 그런 거 아닌가 싶네요.

제가 인쇄할 마지막 페이지를 정할 때,

마지막 미주(31번 문제)가 있는 페이지(20p)로 했거든요.

코드에 주석이라도 넉넉하게 달아놓을테니

참고하시고, 꼭 해결하셨으면 좋겠습니다.

오류메시지나 증상을 알려주시면 이어서 답변을 드릴 수 있으니

막히면, 주저말고 질문 남겨주시기 바랍니다^^

dein01님의 프로필 이미지
dein01

작성한 질문수

질문하기