본문 바로가기
아래아한글 자동화/python+hwp 중급

[QnA] 스타일문서를 임의로 변경한 경우 복원하기

by 일코 2022. 12. 4.
안녕하세요. 한글자동화를 이용해 문서의 서식을 바꾸는 코드를 만들고 싶어 문의드립니다.
회사에서 보고서 작업을 하는데 동일한 문서에서 서식을 다르게 하여 수정 후 내용을 첨가하여 제출하는 경우가 많습니다.
"서식 유지한 채로 스타일을 모두 "바탕글"로 바꾸는 코딩" 에서 일부 수정하면 될 것 같은데
"스타일_조회"함수에서 "Act = hwp.CreateAction("Style")"에서 object가 추출되지 않아서 Nonetype object로 되고 그로 인해 "Set = Act.CreateSet()" 부분이 작동하지 않아 오류가 발생합니다.
그래서 "hwp" 자식 클래스를 "dir" 함수로 살펴보는데 "CreateAction"는 있으나 그 하부에는 "Style"이라는 자식 클래스가 없습니다. 설치 과정 중에 잘못된건지 몰라서 질문을 남깁니다.
1. 다음과 같은 경우에 어떻게 해결할 수 있는지 궁금합니다.
2. A라는 문서의 서식스타일에 맞춰 B라는 문서의 서식스타일을 바꾸는 코드를 만드려고 하는데 혹시 괜찮은 방법이 있는지 여쭤봅니다.

 

이전 포스팅

2022.12.04 - [아래아한글 자동화/python+hwp 중급] - [QnA] A문서 스타일을 B문서에 적용하는 가장 간편한 코딩

 

[QnA] A문서 스타일을 B문서에 적용하는 가장 간편한 코딩

안녕하세요. 한글자동화를 이용해 문서의 서식을 바꾸는 코드를 만들고 싶어 문의드립니다. 회사에서 보고서 작업을 하는데 동일한 문서에서 서식을 다르게 하여 수정 후 내용을 첨가하여 제출

martinii.fun

지난 포스팅에서는 다른 스타일 개요가 적용된 문서의 서식을

탬플릿문서의 스타일 개요로 변경하는 프로그램을 소개해드렸습니다.

하지만 위 프로그램으로도 문서서식이 변경이 안 되는 경우가 있는데,

바로 스타일은 적용되어 있지만, 임의로 서체나 글자크기 등을 변경해버리는 경우입니다.

한/글 스타일에 익숙하지 않은 분들이라면 열 명에 열 명 모두 임의로 서식을 변경하시겠죠.

 

그래서 이번 포스팅에서는

임의로 변경한 글자, 문단서식을 템플릿 스타일로 초기화하는 프로그램을 만들어보겠습니다.

사실 이 부분은 한/글에서 기본 제공하는 기능이 아니기 때문에

문서의 모든 문단을 순회하면서 문단마다 스타일을 조회하고 해당 스타일을 다시 적용하면 됩니다.

다행히 작성할 코드도 짧고 실행시간도 굉장히 짧기 때문에

이런 경우에 코딩으로 처리하면 굉장히 효율적으로 처리할 수 있습니다.

수작업으로 이런 짓을 하고 있으면 하루가 다 갈 수도 있겠지요.

 

이해를 돕기 위한 수작업 예시를 들어보겠습니다.

탬플릿문서의 스타일은 아래와 같습니다.

개요1, 2, 3의 글자크기가 각각 25pt, 18pt, 14pt 입니다.

 

 

그리고 변경할 문서는 아래와 같습니다.

스타일 개요1, 2, 3의 글자크기는 모두 10pt인데

임의로 모두 13pt로 변경해 놓은 상태입니다.

 

 

변경할 문서의 스타일을 열어보면(F6)

스타일은 10pt인데 임의변경해서 13pt임.

위와 같이 모든 스타일개요의 글자크기가 10pt인데,

어떤 작업자가 문서작업 중에 글자크기를 모두 13으로 임의변경해 놓은 상태입니다.

 

이런 경우에는 문서끼워넣기를 통해 스타일을 덮어씌워도

임의로 변경한 기존 13포인트의 글자크기가 변경되지 않고 그대로 유지되어버립니다.

 

 

지난 포스팅에서 보여드렸는데

사실 스타일을 임의수정해놓지 않으면 아래처럼 템플릿의 서식이 바로 적용되어야 하거든요.

변경할문서의 스타일이 탬플릿문서와 같이 변경됨.

 

 

그나마 다행인 것은

스타일을 다시 입혀주기만 하면 탬플릿의 스타일이 그대로 적용된다는 점입니다.

수작업으로 스타일을 지정해주니 다행히 잘 적용됨.

 

그래서 지금부터 우리가 해야 하는 작업은

이전 포스팅인 "끼워넣기" 코드 아래에다가

모든 문단을 순회하며 해당 문단의 스타일번호를 추출해서

스타일적용 명령을 한 번 더 내리는 코드를 추가하는 것입니다.

 

한/글 문서의 스타일을 다루는 포스팅을 예전에 다룬 적이 있어 링크를 남겨둡니다.

서식 유지한 채로 스타일을 모두 "바탕글"로 바꾸는 코딩 (tistory.com)

 

서식 유지한 채로 스타일을 모두 "바탕글"로 바꾸는 코딩

안녕하세요? 일상의코딩 신명진입니다. 회사 다니다 보면 가끔 이런 경우가 있었습니다. 수십페이지의 아래아한글 레거시 문서를 구조화하기 위해서 개요와 스타일을 새롭게 매기고 싶은데 기

martinii.fun

 

그럼 전체 코드를 한 번 보여드리겠습니다.

더보기
import os
from tkinter.filedialog import askopenfilenames

import win32com.client as win32


def 한글_시작(visible=True):
    hwp_app = win32.gencache.EnsureDispatch("hwpframe.hwpobject")  # 한/글 백그라운드에서 실행
    hwp_app.XHwpWindows.Item(0).Visible = visible  # 백그라운드 해제
    hwp_app.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule")  # 보안모듈 실행
    hwp_app.Run("FileOpen")  # 문서 열기 다이얼로그 실행
    doc_dir = os.path.dirname(hwp_app.XHwpDocuments.Item(0).Path)
    return hwp_app, doc_dir  # 실행된 한/글 오브젝트 리턴


def 전체삭제():
    hwp.HAction.Run("SelectAll")
    hwp.HAction.Run("DeleteBack")
    hwp.HAction.Run("DeleteBack")


def 문서삽입(문서경로):
    hwp.HAction.GetDefault("InsertFile", hwp.HParameterSet.HInsertFile.HSet)
    # hwp.HParameterSet.HInsertFile.FileName = "C:\\Users\\smj02\\OneDrive\\바탕 화면\\스타일적용\\변경할문서.hwp"
    hwp.HParameterSet.HInsertFile.filename = 문서경로
    hwp.HParameterSet.HInsertFile.KeepSection = 0
    hwp.HParameterSet.HInsertFile.KeepCharshape = 0
    hwp.HParameterSet.HInsertFile.KeepParashape = 0
    hwp.HParameterSet.HInsertFile.KeepStyle = 0
    hwp.HAction.Execute("InsertFile", hwp.HParameterSet.HInsertFile.HSet)


def 다른이름으로저장(저장경로):
    hwp.HAction.GetDefault("FileSaveAs_S", hwp.HParameterSet.HFileOpenSave.HSet)
    # hwp.HParameterSet.HFileOpenSave.FileName = "C:\\Users\\smj02\\OneDrive\\바탕 화면\\스타일적용\\변경한문서.hwp"
    hwp.HParameterSet.HFileOpenSave.filename = 저장경로
    hwp.HParameterSet.HFileOpenSave.Format = "HWP"
    hwp.HAction.Execute("FileSaveAs_S", hwp.HParameterSet.HFileOpenSave.HSet)


def 바꿀문서선택(기본경로):
    문서경로 = askopenfilenames(title="서식을 변경할 문서를 모두 선택해주세요.",
                            initialdir=기본경로, filetypes=[("한/글 문서", "*.hwp *.hwpx")])
    return 문서경로


def 완료메시지(문서갯수):
    msgbox = hwp.XHwpMessageBox  # 메시지박스 생성
    msgbox.string = f"총 {문서갯수} 개의 문서 서식 변경을 완료하였습니다."
    msgbox.Flag = 0  # [확인] 버튼만 나타나게 설정
    msgbox.DoModal()  # 메시지박스 보이기


def 한글종료():
    hwp.Clear(option=1)  # 1: 변경내용 버림
    hwp.Quit()


def 문서_끝으로():
    hwp.HAction.Run("MoveDocEnd")


def 현재위치_저장():
    return hwp.GetPos()


def 문서_처음으로():
    hwp.HAction.Run("MoveDocBegin")


def 스타일_조회():
    Act = hwp.CreateAction("Style")  # "Style" 액션 초기화
    Set = Act.CreateSet()  # 액션에 해당하는 파라미터셋 생성(현재는 빈 값)
    Act.GetDefault(Set)  # 비어있는 파라미터셋에 현재값 채워넣기
    return Set.Item("Apply")  # 정수 리턴(0:바탕글, 1:본문..)


def 스타일_적용(num):
    Act = hwp.CreateAction("Style")
    Set = Act.CreateSet()
    Act.GetDefault(Set)
    Set.SetItem("Apply", num)  # Apply 아이템의 값을 "개요{num}"으로 변경
    Act.Execute(Set)


def 다음_문단으로():
    hwp.HAction.Run("MoveNextParaBegin")


def 내용없는_줄바꿈인지():
    hwp.InitScan(Range=0x33)
    text = hwp.GetText()
    hwp.ReleaseScan()
    if text[1] == "\r\n":
        return True
    return False


if __name__ == '__main__':
    hwp, 탬플릿경로 = 한글_시작(visible=True)  # 탬플릿문서 선택
    전체삭제()  # 탬플릿문서 본문 전부 삭제
    바꿀문서리스트 = 바꿀문서선택(탬플릿경로)  # tk 파일선택 다이얼로그창 실행하여 바꿀 문서들 선택
    for 문서 in 바꿀문서리스트:
        문서삽입(문서)  # 끼워넣기 실행
        문서_끝으로()
        끝위치 = 현재위치_저장()
        문서_처음으로()
        while hwp.GetPos() != 끝위치:
            스타일 = 스타일_조회()
            스타일_적용(스타일)
            다음_문단으로()
        다른이름으로저장(문서.replace(".hwp", "_서식변경.hwp"))
        전체삭제()
    완료메시지(len(바꿀문서리스트))
    한글종료()

 

이대로 한 번 실행해보겠습니다.

사소한 문제가 하나 발생할 예정입니다.

아닛, 언제까지 클릭을 계속해야 하는 거야ㅜㅜㅜ

 

아닛, 서식 적용은 정상적으로 되고 있는데 무슨 팝업이 이렇게!?

"본문을 [개요#] 스타일 모양으로 덮어쓸 거냐"는 팝업이 계속해서 뜹니다. 일일이 클릭해줘야 하고요ㅜㅜㅜ

하지만 걱정마세요.

한/글에서는 이런 경우를 대비해 팝업이 나타날 때 

자동으로 특정 버튼을 클릭해주는 상세한 옵션을 제공하고 있습니다.

바로 SetMessageBoxMode 라는 메서드입니다. API 문서에 아래와 같이 사용법이 지세하게 나와 있습니다.

 

위 내용을 참고하여 아래와 같은 함수 두 개를 만들어 프로그램에 추가해줍니다.

def 스타일덮어쓰기_자동클릭():
    hwp.SetMessageBoxMode(0x10)


def 스타일덮어쓰기_자동클릭해제():
    hwp.SetMessageBoxMode(0xf0)

 

다시 변경된 코드를 보여드리겠습니다.

# ~~~


def 스타일덮어쓰기_자동클릭():
    hwp.SetMessageBoxMode(0x10)


def 스타일덮어쓰기_자동클릭해제():
    hwp.SetMessageBoxMode(0xf0)


if __name__ == '__main__':
    hwp, 탬플릿경로 = 한글_시작(visible=True)  # 탬플릿문서 선택
    전체삭제()  # 탬플릿문서 본문 전부 삭제
    바꿀문서리스트 = 바꿀문서선택(탬플릿경로)  # tk 파일선택 다이얼로그창 실행하여 바꿀 문서들 선택
    스타일덮어쓰기_자동클릭()  # <---
    for 문서 in 바꿀문서리스트:
        문서삽입(문서)  # 끼워넣기 실행
        문서_끝으로()
        끝위치 = 현재위치_저장()
        문서_처음으로()
        while hwp.GetPos() != 끝위치:
            스타일 = 스타일_조회()
            스타일_적용(스타일)
            다음_문단으로()
        다른이름으로저장(문서.replace(".hwp", "_서식변경.hwp"))
        전체삭제()
    스타일덮어쓰기_자동클릭해제()  # <---
    완료메시지(len(바꿀문서리스트))
    한글종료()

 

실행해보겠습니다. 두근두근~

최종 실행화면

오예! 의도했던 대로 잘 실행되네요.

조금 아쉬운 대로 이번 포스팅은 여기서 마치겠습니다.

행복한 하루 되세요!

 

 

여러분의 자습을 위한 소스코드와 본 포스팅에 사용한 예제문서, 컴파일한 실행파일을 첨부해 둡니다.

스타일적용#응용.zip
12.62MB

 

댓글