인프런 커뮤니티 질문&답변
hwp.Execute 의 True,False를 이용한 반복문
해결된 질문
작성
·
337
2
안녕하세요 일코님 강의 잘 듣고 있습니다.
한글 찾기를 이용해서 작업을 하고 있습니다.
다른 부분은 모두 잘 작동하는 데
while문 제어가 어려워서 문의 드립니다.
문서에서 직접 ctrl+f로 찾기를 해보면 마지막이 나오는데
파이썬 코드를 이용하면 False값을 뱉지 않고 무한루프에 빠집니다.
작업 내용은 "[1 " 를 찾아서
표 안에 있으면 표 전체를 저장하고,
"[1"이 본문에 있으면 본문 내용을 저장해서 다른 문서에 저장하는 작업입니다.

import os
from tkinter import Tk
from tkinter.filedialog import askopenfilename
import win32com.client as win32
def 한글_열기(한글파일):
hwp = win32.gencache.EnsureDispatch("hwpframe.hwpobject")
hwp.XHwpWindows.Item(0).Visible = True
hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule")
hwp.Open(한글파일)
return hwp
def 한글_찾기(문자열):
hwp.HAction.GetDefault("RepeatFind", hwp.HParameterSet.HFindReplace.HSet)
hwp.HParameterSet.HFindReplace.FindString = 문자열
hwp.HParameterSet.HFindReplace.Direction = hwp.FindDir("Forward")
hwp.HParameterSet.HFindReplace.IgnoreMessage = 1
hwp.HParameterSet.HFindReplace.FindType = 1
cond = hwp.HAction.Execute("RepeatFind", hwp.HParameterSet.HFindReplace.HSet)
print(cond)
return cond
def 문서_처리():
if (hwp.GetPosBySet().Item("List") == 0) :
hwp.HAction.Run("MoveParaBegin")
spara = hwp.GetPosBySet().Item("Para")
spos = hwp.GetPosBySet().Item("Pos")
hwp.HAction.Run("MoveParaEnd")
epara = hwp.GetPosBySet().Item("Para")
epos = hwp.GetPosBySet().Item("Pos")
blockSelect(spara, spos, epara, epos)
textArr.append(hwp.GetTextFile("HWP", "saveblock"))
hwp.HAction.Run("Cancel")
else :
hwp.HAction.Run("CloseEx")
spara = hwp.GetPosBySet().Item("Para")
spos = hwp.GetPosBySet().Item("Pos")
hwp.HAction.Run("MoveParaEnd")
epara = hwp.GetPosBySet().Item("Para")
epos = hwp.GetPosBySet().Item("Pos")
blockSelect(spara, spos, epara, epos)
textArr.append(hwp.GetTextFile("HWP", "saveblock"))
hwp.HAction.Run("MoveParaEnd")
hwp.HAction.Run("Cancel")
def blockSelect(spara, spos, epara, epos):
hwp.SelectText(spara, spos, epara, epos)
if __name__ == '__main__':
os.chdir(os.path.join(os.environ["USERPROFILE"], "desktop"))
BASE_DIR = os.getcwd()
root = Tk()
한글파일 = askopenfilename(title=" HWPX 파일을 선택해 주세요.",
initialdir=BASE_DIR,
filetypes=[("아래아한글", "*.hwp *.hwpx")])
root.destroy()
hwp = 한글_열기(한글파일)
hwp.MovePos(2, 0, 0)
textArr = []
while True:
# for _ in range(8):
if 한글_찾기("[1"):
문서_처리()
else:
break
hwp.Run("FileNew") # 빈 문서 생성
for k in range(len(textArr)):
hwp.SetTextFile(textArr[k], "HWP", "insertfile")
hwp.HAction.Run("MoveParaEnd")
hwp.HAction.Run("BreakPara")
hwp.HAction.Run("BreakPara")
hwp.HAction.Run("StyleShortcut1")
hwp.HAction.Run("StyleShortcut1")
hwp.SaveAs(os.path.join(os.getcwd(), "result2.hwpx")) # 현재 위치에 다른이름으로 저장
hwp.Quit()
print('모두 완료')답변 3
2
korea_354님, 안녕하세요?
코드가 너무 깔끔합니다! (부럽습니다ㅎ)
한/글 API 중 RepeatFind는
찾기 중에 문서 내 특정 조작이 발생하는 경우,
시작위치가 리셋되어버립니다.. (그래서 False 리턴을 안 하고 무한루프에 빠짐ㅜ)
이를 해결하는 방법이 몇 가지가 있는데
가장 단순한 방법은 (조금 번거롭더라도)
최초 검색위치의 GetPos() 결과를 start_pos 같은 변수에 저장해 뒀다가
매번 찾기 실행시 GetPos()를 start_pos와 비교하면서,
최초위치로 돌아왔으면 break로 while문 종료하기!
정도일 것 같습니다.
액션의 리턴값에 의존하지 않고 종료로직을 따로 짜는 거죠ㅜ
그리고 두 번째 방법은 (개인적으로는 이걸 추천)
바로 복붙이나 어떤 조작도 보태지 않고
순수하게 "찾기"만 진행하면서
복사하여 옮길 표나 블록의 시작/끝 위치만 파이썬 리스트로 저장해 두는 겁니다.
그렇게 탐색이 완료되면 해당 리스트로 순회하면서
구간구간을 블록저장하는 코드만 따로 돌리는 거죠.
한/글 문서 내에서는 조작이 일어나지 않았으니
RepeatFind는 한 바퀴 돌면 정상적으로 False를 리턴합니다.
취향에 따라 두 가지 방법 중 하나를 쓰시면 됩니다.
혹시 구현이 조금 막연하시거나, 막히는 부분이 있다면
(공개해도 괜찮은) 예시문서를 하나만 만들어서 보내주세요.
포스팅이나 영상으로 제작하여 설명드리겠습니다.
감사합니다.
행복한 하루 되세요^^
1
kun님 안녕하세요?
kun님 사례 같은 경우는
표 안에 여러 개의 "[1"이 있기 때문에
표를 한 번 추출하고 나면 해당 표를 패스하는 것보다,
표를 지워버리는 게 간편하기 때문에(대신 저장하지 않고 버리기 필수!)
아래와 같이 코드를 짜보았습니다.
우선 시연화면과 pyhwpx를 이용한 코드 보여드리고
이어서 부가설명을 드리겠습니다.
<영상>
https://drive.google.com/file/d/1T9ZrxLJ6YLkbpP-qXFMg-XF70DR5aP44/view?usp=drive_web
<코드>
from pyhwpx import Hwp
hwp = Hwp()
hwp.open("도덕.hwpx")
#%% 개요
# 표 안에 있는 "[1"을 찾아서,
# 표 안에 있으면 표 전체를 저장
# 표 밖(본문)에 있으면 본문 내용을 저장
# 집계결과는 빈 문서에 삽입하기
#%% [1/3] 원본에서 "[1"을 찾아 해당 부분 저장하기
data_list = [] # 블록을 저장할 빈 리스트 생성
hwp.MoveDocBegin() # 문서 처음으로 이동해서
while hwp.find("[1"):
if hwp.is_cell(): # 셀이면
hwp.select_ctrl(hwp.ParentCtrl) # 표 전체 선택
else:
hwp.MoveParaBegin() # 표가 아닌 본문이면 해당 문단 시작부터
hwp.MoveSelParaEnd() # 끝까지 선택해서
result = hwp.GetTextFile(format="HWP", option="saveblock") # 블록저장
data_list.append(result) # 저장한 블록을 리스트에 추가
hwp.Delete() # 검색결과는 원본에서 (임시)삭제
#%% [2/3] 빈 문서 열고 역순으로 붙여넣기
hwp2 = Hwp(new=True)
for i in data_list[::-1]: # 캐럿 뒤에 블록이 붙으므로, 역순삽입이 더 간편함
hwp2.SetTextFile(i, format="HWP")
hwp2.BreakPara()
hwp2.MoveDocBegin()
#%% [3/3] 모든 표문단의 스타일을 바탕글(Style1)로 변경
for i in hwp2.ctrl_list:
if i.UserDesc == "표":
hwp2.move_to_ctrl(i)
hwp2.StyleShortcut1() # 스타일 변경
hwp2.StyleShortcut1() # 서체, 들여쓰기 등 글자/문단형식 초기화
# 스타일 변경은 (이렇게 두 번 실행해야 함ㅜ)
pyhwpx의 작동방식은 내부적으로 win32 API와 아무 차이가 없지만
사용편의를 위해서 몇 가지 추가기능을 제공하고 있습니다.
예를 들어 hwp.find()의 소스코드는 아래와 같이 구성되어 있습니다.
def find(self, src, direction: Literal["Forward", "Backward", "AllDoc"] = "Forward", regex=False):
"""
direction 방향으로 특정 단어를 찾아가는 메서드.
해당 단어를 선택한 상태가 되며,
탐색방향에 src 문자열이 없는 경우 False를 리턴
:param src:
찾을 단어
:param direction:
탐색방향
"Forward": 아래쪽으로
"Backward": 위쪽으로
"AllDoc": 아래쪽 우선으로 찾고 문서끝 도달시 처음으로 돌아감.
:return:
단어를 찾으면 찾아가서 선택한 후 True를 리턴,
단어가 더이상 없으면 False를 리턴
"""
self.SetMessageBoxMode(0x2fff1)
init_pos = str(self.KeyIndicator())
pset = self.hwp.HParameterSet.HFindReplace
# GetDefault를 사용하지 않음
pset.MatchCase = 1
pset.SeveralWords = 1
pset.UseWildCards = 1
pset.AutoSpell = 1
pset.Direction = self.find_dir(direction)
pset.FindString = src
pset.IgnoreMessage = 0
pset.HanjaFromHangul = 1
pset.FindRegExp = regex
try:
return self.hwp.HAction.Execute("RepeatFind", pset.HSet)
finally:
self.SetMessageBoxMode(0xfffff)왜 이렇게 구현했는지 의아할 수 있는 부분 중에,
IgnoreMessage를 0으로 주는 대신 SetMessageBoxMode를 사용했는데요.
당시 진행중이던 작업 특성상, 무한루프에 빠지지 않기 위한 당시의 최선책이었습니다.
AllDoc 대신에 Forward를 기본값으로 넣은 것도, 역시 무한루프를 방지하기 위함입니다.
코드를 보시면 아시겠지만,
hwp.HAction.Run("액션아이디")는, pyhwpx 사용시에는
hwp.액션아이디() 방식으로 실행 가능합니다. (일일이 정의했기 때문에 일부 빠진 액션도 있습니다ㅜ)
기존에 없는 pyhwpx 고유의 메서드나 속성은, API와 구분하기 위해 스네이크케이스로 만들었습니다.
hwp.ctrl_list, hwp.move_to_ctrl, hwp.select_ctrl 등입니다.
혹시 코드나 진행방식 중에 추가로 궁금하신 점이 있으면
자유롭게 댓글 남겨주시기 바랍니다.
감사합니다.
행복한 하루 되세요^^
1
안녕하세요, 인프런 AI 인턴입니다.
korea_354님께서 파이썬과 한글 오토메이션을 이용하여 특정 문자열을 찾아 표 혹은 본문 내용을 다른 문서에 저장하는 작업 중 while 반복문 제어에 어려움을 겪고 계신 것 같습니다.
반복문 내에서 한글_찾기() 함수가 마지막 항목을 찾은 뒤에도 False를 반환하지 않고 무한 루프에 빠지는 문제를 해결하는 데에 도움이 될 만한 파이썬으로 한글 오피스 자동화를 다룬 질문에서 비슷한 상황을 다룬 답변을 찾았습니다.
특히, 반복문 제어와 관련하여 한/글 자동화 스크립트에서 반복적으로 특정 조건을 만족할 때까지 작업을 수행하다가 특정 조건에 의해 반복문을 종료하는 예시를 참고하시는 것이 유익할 것입니다. 해당 답변에서는 작업 실패 시 예외 처리의 중요성과 반복문 내에서 조건을 활용하여 효율적으로 반복작업을 종료하는 방법에 대한 설명이 있습니다.
또한, 한글 자동화 작업과 관련한 보다 구체적인 문제 해결 방법을 탐색하는 경우, 한글 자동화 작업에 관한 전반적인 이해도를 높일 수 있는 다른 자동화 스크립트 관련 질문에 대한 답변도 참고해보실 것을 추천드립니다.
어쨌든 이 경우에도 while 문 내에 구현된 로직이 정확히 특정 조건에서 반복을 멈추도록 설계되었는지, 그리고 조건 검사가 적절히 이루어지고 있는지 확인하는 것이 중요합니다. 또한, 한글_찾기() 함수가 마지막 항목을 찾은 후 종료 조건을 명확히 할 수 있도록 조정할 필요가 있습니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.






조금 막히는 부분이 있어서 메일 보냈습니다.
항상 감사합니다.