안녕하세요?
회사원코딩의 Martinii입니다.
이번 포스팅에서는 아래아한글의 "찾기/찾아바꾸기"를 파이썬 코드로 재현해보려고 합니다. 나아가 특정 단어를 포함한 문장 전체를 선택해서 서식을 바꾸는 작업까지 코딩해볼게요.
한/글에서 기본적으로 찾기는 Ctrl-F, 찾아바꾸기는 Ctrl-H죠.
예문은 아래 사이트에서 5문단 정도 따왔습니다.
이 문서에서 가장 먼저 출현하는 "대통령"을 찾는다든지, 문서 내 모든 "대통령"이라는 텍스트에 [진하게 / 글자색 빨강]을 적용하는 것은 코딩 없이도 금방 할 수 있죠. 문서 분량이 아무리 많더라도요. 아래 과정만 하면 돼요.
근데 이런 작업은 어떨까요?
"대통령"이라는 글자가 들어가는 모든 문장에 [진하게/글자색 빨강] 적용하기라면?
이런 작업은 경우가 달라지죠. 문서분량이 많아질수록 작업시간이 길어지는 작업이 돼요. 이럴 때는 코딩을 사용하면 훨씬 수월할 수 있어요. 코드도 간단하고요. 방법이 여러 가지가 있겠지만, 우선 제가 한 가지 방법을 자세히 설명해드리고, 하단에 추가로 가능한 몇 가지 방법들을 간단히 알려드려볼게요. 보고 연습해 보시는 분은 댓글로 직접 작성한 코드 남겨주시면 피드백 남겨드릴게요.
우선 가장 먼저 생각나는 방법은 이것 같아요.
1. 문서 시작부분으로 이동한 후에
2. 아랫방향 탐색으로 "대통령"을 찾는다.
3. 그 상태에서 윗방향 탐색으로 "."을 찾는다. 오른쪽으로 한 칸 이동하고 그 위치를 start_pos에 저장한다.
4. 그 상태에서 아랫방향 탐색으로 "."을 찾는다. 오른쪽으로 한 칸 이동하고 그 위치를 end_pos에 저장한다.
5. hwp.SetPos(*start_pos) 로 시작부분으로 이동한다.
6. Run("Select") 로 선택모드 실행한 후, hwp.SetPos(*end_pos)로 문장 전체를 선택한다.
7. 선택한 부분의 서식을 변경한다. start_pos를 pos_set이라는 세트에 저장한다.
8. 2번부터 7번까지를 반복한다. 새 start_pos가 pos_set 안에 있으면 while문을 종료한다.
끝.
위의 과정을 코드로 옮겨보았습니다.
# -*- coding: utf-8 -*-
import win32com.client as win32
import os
text = "정부는 회계연도마다 예산안을 편성하여 회계연도 개시 90일전까지 국회에 제출하고, 국회는 회계연도 개시 30일전까지" \
" 이를 의결하여야 한다. 국채를 모집하거나 예산외에 국가의 부담이 될 계약을 체결하려 할 때에는 정부는 미리 국회의" \
" 의결을 얻어야 한다. 국회에서 의결된 법률안은 정부에 이송되어 15일 이내에 대통령이 공포한다. 계엄을 선포한 때에" \
"는 대통령은 지체없이 국회에 통고하여야 한다. 정당은 그 목적/조직과 활동이 민주적이어야 하며, 국민의 정치적 의사" \
"형성에 참여하는데 필요한 조직을 가져야 한다. 국가는 법률이 정하는 바에 의하여 재외국민을 보호할 의무를 진다. 국" \
"회는 의원의 자격을 심사하며, 의원을 징계할 수 있다.\r\n선거에 있어서 최고득표자가 2인 이상인 때에는 국회의 재적" \
"의원 과반수가 출석한 공개회의에서 다수표를 얻은 자를 당선자로 한다. 국무총리/국무위원 또는 정부위원은 국회나 그" \
" 위원회에 출석하여 국정처리상황을 보고하거나 의견을 진술하고 질문에 응답할 수 있다. 근로자는 근로조건의 향상을 " \
"위하여 자주적인 단결권/단체교섭권 및 단체행동권을 가진다. 국가는 재해를 예방하고 그 위험으로부터 국민을 보호하" \
"기 위하여 노력하여야 한다. 대통령으로 선거될 수 있는 자는 국회의원의 피선거권이 있고 선거일 현재 40세에 달하여" \
"야 한다. 국가안전보장에 관련되는 대외정책/군사정책과 국내정책의 수립에 관하여 국무회의의 심의에 앞서 대통령의 " \
"자문에 응하기 위하여 국가안전보장회의를 둔다.\r\n국가유공자/상이군경 및 전몰군경의 유가족은 법률이 정하는 바에 " \
"의하여 우선적으로 근로의 기회를 부여받는다. 모든 국민은 소급입법에 의하여 참정권의 제한을 받거나 재산권을 박탈" \
"당하지 아니한다. 국가는 노인과 청소년의 복지향상을 위한 정책을 실시할 의무를 진다. 국민경제자문회의의 조직/직무" \
"범위 기타 필요한 사항은 법률로 정한다. 모든 국민은 인간다운 생활을 할 권리를 가진다. 여자의 근로는 특별한 보호" \
"를 받으며, 고용/임금 및 근로조건에 있어서 부당한 차별을 받지 아니한다. 연소자의 근로는 특별한 보호를 받는다. 대" \
"통령은 법률에서 구체적으로 범위를 정하여 위임받은 사항과 법률을 집행하기 위하여 필요한 사항에 관하여 대통령령을" \
" 발할 수 있다.\r\n대통령은 조약을 체결/비준하고, 외교사절을 신임/접수 또는 파견하며, 선전포고와 강화를 한다. 국" \
"무위원은 국정에 관하여 대통령을 보좌하며, 국무회의의 구성원으로서 국정을 심의한다. 법관이 중대한 심신상의 장해" \
"로 직무를 수행할 수 없을 때에는 법률이 정하는 바에 의하여 퇴직하게 할 수 있다. 대통령은 국가의 원수이며, 외국에" \
" 대하여 국가를 대표한다. 국무총리는 대통령을 보좌하며, 행정에 관하여 대통령의 명을 받아 행정각부를 통할한다. 국" \
"회의원과 정부는 법률안을 제출할 수 있다. 이 헌법은 1988년 2월 25일부터 시행한다. 다만, 이 헌법을 시행하기 위하" \
"여 필요한 법률의 제정/개정과 이 헌법에 의한 대통령 및 국회의원의 선거 기타 이 헌법시행에 관한 준비는 이 헌법시" \
"행 전에 할 수 있다.\r\n국회는 상호원조 또는 안전보장에 관한 조약, 중요한 국제조직에 관한 조약, 우호통상항해조약" \
", 주권의 제약에 관한 조약, 강화조약, 국가나 국민에게 중대한 재정적 부담을 지우는 조약 또는 입법사항에 관한 조약" \
"의 체결/비준에 대한 동의권을 가진다. 대통령은 법률이 정하는 바에 의하여 사면/감형 또는 복권을 명할 수 있다. 모" \
"든 국민은 헌법과 법률이 정한 법관에 의하여 법률에 의한 재판을 받을 권리를 가진다. 정당의 목적이나 활동이 민주적" \
" 기본질서에 위배될 때에는 정부는 헌법재판소에 그 해산을 제소할 수 있다.\r\n"
def init_hwp():
"""
한/글 열고 보안모듈 실행하고 백그라운드작업 해제하는 함수
사용법: hwp = init_hwp()
:return: hwp객체
:rtype: object
"""
hwp = win32.gencache.EnsureDispatch("HWPFrame.HwpObject") # 한/글 열고
hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule") # 보안모듈 실행
hwp.XHwpWindows.Item(0).Visible = True # 백그라운드작업 해제
return hwp
def type_text(word):
"""
한/글창에 문자열을 입력하는 함수
:param word: 입력할 문자열
:type word: str
:return: None
:rtype: None
"""
hwp.HAction.GetDefault("InsertText", hwp.HParameterSet.HInsertText.HSet) # 메서드 초기화
hwp.HParameterSet.HInsertText.Text = word # 파라미터에 문자열 word 추가
hwp.HAction.Execute("InsertText", hwp.HParameterSet.HInsertText.HSet) # 메서드 실행
return # 함수 종료
def find_word(word, direction="Forward"):
"""
문서 내에서 word를 검색하는 함수
:param word: 검색할 문자열
:type word: str
:param direction: 검색할 방향 ["BackWard", "Forward"]
:type direction: str
:return: None
:rtype: None
"""
hwp.HAction.GetDefault("RepeatFind", hwp.HParameterSet.HFindReplace.HSet)
hwp.HParameterSet.HFindReplace.Direction = hwp.FindDir(direction)
hwp.HParameterSet.HFindReplace.FindString = word
hwp.HParameterSet.HFindReplace.IgnoreMessage = 1
hwp.HParameterSet.HFindReplace.FindType = 1
status = hwp.HAction.Execute("RepeatFind", hwp.HParameterSet.HFindReplace.HSet)
return
def 특정단어포함문장선택(target="대통령", end="."):
"""
특정 단어를 포함한 문장 전체를 선택하는 함수. 문장구분은 "."가 기본값임.
:param target: 검색할 문자열
:type target: str
:param end: 문장 구분 단위. 기본은 온점 "."
:type end: str
:return: start_pos 튜플
:rtype: tuple
"""
find_word(target, "Forward")
find_word(end, "Backward")
hwp.Run("MoveRight")
start_pos = hwp.GetPos()
find_word(end, "Forward")
end_pos = hwp.GetPos()
hwp.Run("Cancel")
hwp.SetPos(*start_pos)
hwp.Run("Select")
hwp.SetPos(*end_pos)
return start_pos
def 선택구간속성변경(color="Red", bold=True):
"""
선택한 구간의 속성을 변경하는 함수.
:param color: 글자색
:type color: str
:param bold: 진하게할지말지
:type bold: bool
:return: None
:rtype: None
"""
if bold:
hwp.Run("CharShapeBold")
hwp.Run(f"CharShapeTextColor{color}")
hwp.Run("Cancel")
return
if __name__ == '__main__':
hwp = init_hwp()
type_text(text)
hwp.MovePos(2)
pos_set = set()
while True:
pos = 특정단어포함문장선택("대통령", ".")
if pos not in pos_set:
pos_set.add(pos)
else:
break
선택구간속성변경("Red", bold=True)
hwp.SaveAs(os.path.join(os.getcwd(), "example.hwp"))
결과는 아래와 같습니다.
위 코드 중에 잘 이해가 안 되거나 궁금한 부분은 댓글로 문의 남겨주시기 바랍니다.
주석이나 텍스트 때문에 코드가 조금 길어졌지만, 코드 자체는 간단합니다.
다만 파이썬 문법이나 한/글API가 생소한 분들은 좀 부담스러울 수 있겠네요..
여러분의 IDE로 옮겨서 한 번 실행해보시거나, BreakPoint를 아무 데나 하나 걸고 디버깅을 해보시면서 과정을 살펴보시면 훨씬 빠르고 쉽게 이해가 될 것입니다.
이번 포스팅은 여기서 마치겠습니다.
국내 유일의 파이썬+한컴오피스 업무자동화 입문강의
'아래아한글 자동화 > python+hwp 중급' 카테고리의 다른 글
2019년 파이콘 참석영상(코알못 직장인) (0) | 2020.08.17 |
---|---|
4. 문서여백을 파이썬으로 바꿀 수 있을까? (6) | 2020.08.12 |
3. 자동화 하실 거면 꼭 정품등록하시고 개발자커뮤니티 들어가보세요! (6) | 2020.08.12 |
댓글