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

GetText, 한/글 자동화 고급과정의 첫걸음①

by 일코 2022. 2. 4.

Quitryne님께서 질문 주신 내용

안녕하세요? 일상의 코딩, 일코입니다.

이전 포스팅에서 찾기 후 매크로 몇 줄을 보태서

문제를 간단히 해결했습니다.

2022.02.03 - [업무자동화/파이썬-아래아한글 자동화 기초] - 찾기로 탐색한 단어 말고 바로 뒤의 단어를 조작하고 싶다면?

 

찾기로 탐색한 단어 말고 바로 뒤의 단어를 조작하고 싶다면?

안녕하세요? 일상의 코딩, 일코입니다. (편하게 일코님~ 하고 불러주세요^^) 이번에 질문 주신 내용을 요약하면 "문자열 탐색 후 옆 단어를 조작하는 방법" 입니다. 지난 포스팅에서 "찾아바꾸기"

martinii.fun

 

그럼에도 이번 응용편 포스팅을 덧붙이는 이유는,

현업에서 복잡한 작업을 다루다 보면

한/글에서 찾기(Ctrl-F)나 찾아바꾸기(Ctrl-H) 매크로만으로는

해결할 수 없는 문제가 자주 발생합니다.

그런 경우 대부분 GetText로는 훨씬 간단히 해결할 수 있기 때문입니다.

 

어떤 경우에 찾기나 찾아바꾸기 대신

GetText를 사용해야 할까요?

당장 몇 가지만 예를 들어보면,

 

1. 조항번호 등 글머리의 숫자를 재정렬해야 하는 경우

2. 표 안의 내용만, 혹은 특정 범위의 문자열만 조작해야 하는 경우

3. 탐색할 문자열이 복잡해서 정규식을 써야 하는 경우 등

 

이런 작업들은 단순한 찾아바꾸기 매크로로는

해결하기가 쉽지 않죠.

의외로.. 엄청난 고급 예제들은 아니죠?ㅎ
제 경험상
정부부처, 기관, 개인을 막론하고
최근 도움 드린 거의 모든 코드에
GetText가 사용됐더라고요.

최근에도 GetText를 많이 사용했네요..

 

이번 질문도 간단히 GetText를 배워볼 수 있는 케이스인 것 같아서

무리해서 응용편을 준비했습니다.

 


 

지난 포스팅에서 코드의 진행과정은 대략 아래와 같았어요.

 

1. 찾기(Ctrl-F)

2. 파이프 지우고 뒤의 단어 선택하기

3. 진하게&밑줄 적용

 

2번과 3번 과정은 동일한 코드를 사용해도 되는데...........

한 가지 고백하자면,

3번 과정에는 작은 버그가 하나 존재해요.

그건 바로,

기존에 진하게&밑줄이 적용되어 있는 경우에는

진하게&밑줄 서식이 해제되어버린다는 것!

기존 진하게&밑줄 서식이 해제되어버렸다!

이건 사실 큰 문제가 될 수도 있죠.

특히 문서 분량이 어마어마한 경우에는,

언제 이 오류를 다 찾고 앉아있겠어요ㅜㅜㅜ

 

그래서 이번 포스팅을 진행하면서

이 부분도 다른 방법으로 살짝 보완을 해보겠습니다.

 

우선 GetText에 관한 간략한 설명은

예전 포스팅에도 한 번 다룬 적이 있습니다.

2021.08.14 - [업무자동화/파이썬-아래아한글 자동화 기초] - [파이썬-한/글]GetText 사용시 탐색범위 지정하는 방법

 

[파이썬-한/글]GetText 사용시 탐색범위 지정하는 방법

질문주신 내용 GetText는 한/글 문서 내의 모든 텍스트를 탐색하는 메서드입니다. 사용방법은 ①InitScan으로 초기화하고, ②GetText로 탐색한 후에 ③ReleaseScan으로 종료합니다. 재미있는 점은, 탐색범

martinii.fun

 

GetText는 기본적으로는

문서 시작점에서부터 마치는 곳까지

본문을 포함해서 표나 주석 등의 모든 문자열을

단락 단위로 탐색해줍니다.

 

이번에 예제로 쓸 한/글 문서는 아래와 같습니다.

food_unites_2.hwpx
0.07MB

위의 첨부파일을 다운받은 후에, 같이 진행해 보시기 바랍니다.

이전 포스팅의 예제와 내용은 같습니다.
차이점은, 문장을 5개의 단락으로 나누었고, 단락 하나는 표 안에 넣었습니다.

 

이번 포스팅에서 주로 다룰 GetText의 사용법은 아래와 같습니다.

 

1. hwp.InitScan(option, Range, spara, spos, epara, epos)으로 탐색 초기화

GetText는 실행 전에

InitScan으로 탐색 초기화 작업이 필요합니다.

이 때 재미있는 점은,

option 과 Range라는 두 개의 인자, 혹은

spara, spos, epara, epos 인자를 추가한 최대 여섯 개의 인자를 통해

탐색범위를 다양하게 설정할 수 있다는 것입니다.

입력 가능한 모든 파라미터는 아래와 같습니다.

 

(1) option 인자

설명
0x00 본문을 대상으로 검색한다.(서브리스트를 검색하지 않는다.)
0x01 char 타입 컨트롤 마스크를 대상으로 한다.(강제줄나눔, 문단 끝, 하이픈, 묶움빈칸, 고정폭빈칸, ...)
0x02 inline 타입 컨트롤 마스크를 대상으로 한다.(누름틀 필드 끝, ...)
0x04 extende 타입 컨트롤 마스크를 대상으로 한다.(바탕쪽, 프레젠테이션, 다단, 누름틀 필드 시작, Shape Object, 머리말, 꼬리말, 각주, 미주, 번호관련 컨트롤, 새 번호 관련 컨트롤, 감추기, 찾아보기, 글자 겹침, ...)
찾을 대상을 다음과 같은 옵션을 조합하여 지정할 수 있다. 생략하면 모든 컨트롤을 찾을 대상으로 한다.

 

(2) Range 인자

설명
0x0000 캐럿 위치부터. (시작 위치)
0x0010 특정 위치부터. (시작 위치)
0x0020 줄의 시작부터. (시작 위치)
0x0030 문단의 시작부터. (시작 위치)
0x0040 구역의 시작부터. (시작 위치)
0x0050 리스트의 시작부터. (시작 위치)
0x0060 컨트롤의 시작부터. (시작 위치)
0x0070 문서의 시작부터. (시작 위치)
0x0000 캐럿 위치까지. (끝 위치)
0x0001 특정 위치까지. (끝 위치)
0x0002 줄의 끝까지. (끝 위치)
0x0003 문단의 끝까지. (끝 위치)
0x0004 구역의 끝까지. (끝 위치)
0x0005 리스트의 끝까지. (끝 위치)
0x0006 컨트롤의 끝까지. (끝 위치)
0x0007 문서의 끝까지. (끝 위치)
0x00ff 검색의 범위를 블록으로 제한.
0x0000 정뱡향. (검색 방향)
0x0100 역방향. (검색 방향)
검색의 범위를 다음과 같은 옵션을 조합하여 지정할 수 있다.
생략하면 “문서 시작부터 - 문서의 끝까지” 검색 범위가 지정된다.

 

(3) spara, spos, epara, epos 인자

위의 인자들의 의미는 각각 차례대로,
spara : 탐색을 시작할 문단 번호
spos : 시작문단 내에서 탐색을 시작할 문자 위치
epara : 탐색을 마칠 문단번호
epos : 탐색종료 문단 내에서 탐색을 마칠 문자 위치
입니다.
 
얼핏 보면 어떤 파라미터를 넣어야 할지
굉장히 복잡해 보일 수 있지만,
예를 들어 설명하면 간단히 이해하실 겁니다.
 

① 본문첫 번째 문단 내에서만 탐색작업을 하고 싶다면?

첫 번째 문단(선택범위)에서만 탐색하고 싶다면?
이런 경우에는
hwp.InitScan(Range=0x0073)
이라고 초기화하시면 됩니다.

 

이 때 입력한 파라미터 0x0073의 의미는,

0x0070(문서의 시작부터) + 0x0003(문단의 끝까지) 의 조합입니다.

 

한 번 실행결과를 볼까요?

첫 문단만 탐색한 후 종료(hwp.GetText()[0] == 0)

 

우리의 의도대로,

GetText를 반복실행해도 가 첫 번째 문장만 리턴한 후

GetText()의 상태값[0]이 0을 리턴(탐색 종료)하였습니다.

다소 인터페이스가 암호 같고 생소하더라도,

직접 몇 번만 짜보시면 금방 이해하실 겁니다.

 

다른 예를 하나만 더 들어볼까요?

② 선택중인 표 안에서만 탐색하고 싶다면?

현재 선택중인 표 안에서만 탐색 및 수정작업을 하고 싶다면?

이런 때에는 아래와 같이 실행하면 됩니다.

hwp.InitScan(Range=0xff)  # 검색의 범위를 블록으로 제한

 

한 번 실행해볼까요?

표 선택 후, 그 안의 문자열만 탐색합니다.

 

Range=0xff 같은 파라미터는

어떤 경우에 사용할 수 있을까요?

 

가장 빈번한 예를 들자면,

문서 안에 아주 많은 갯수의 표가 있는데

제목열이나 표 안에 특정 문자열이 존재하는지 등

특정 조건을 충족하는 표만 편집하거나,

혹은 엑셀, 데이터프레임 등으로 추출하고 싶을 때

이 파라미터를 활용해볼 수 있겠죠?

 

하여튼 이렇게 유연하게 탐색작업을 할 수 있다는 점에서

좀 더 자유로운 코딩을 해보실 수 있습니다.

 

아이고, InitScan에 대한 설명이 너무 길어졌네요.

이제 GetText로 넘어가겠습니다.

 

2. GetText()로 본격적인 탐색 시작

hwp.InitScan으로 탐색을 초기화한 후에는

for문이나 while문으로

hwp.GetText()를 반복실행하면서

GetText()가 리턴하는 상태값과 문자열 값을 활용하시면 됩니다.

GetText()는 2개의 값을 가진 튜플을 리턴하는데,

 

0번 인덱스에는 상태값이,

1번 인덱스에는 해당 문단의 문자열 값이 들어 있습니다.

바로 위에서 실행했던 GetText의 리턴값입니다.

처음 상태값은 2(일반텍스트)였다가, 그 다음 상태값은 0(텍스트정보없음==종료)

 

상태값을 통해서도 다양한 정보를 취득할 수 있습니다.

GetText가 리턴하는 모든 상태값과 그 의미는 아래와 같습니다.

상태값 의미
0 텍스트 정보 없음
1 리스트의 끝
2 일반 텍스트
3 다음 문단
4 제어문자 내부로 들어감(표, 주석 등)
5 제어문자를 빠져나옴
101 초기화 안 됨 (InitScan() 실패 또는 InitScan()을 실행하지 않은 경우)
102 텍스트 변환 실패
 
그럼 예제파일에 hwp.InitScan() 후 hwp.GetText()를 반복해서 실행해보겠습니다.

 
리턴한 값들은 아래와 같습니다.
>>> hwp.InitScan()
True


>>> hwp.GetText()
(2, '')


>>> hwp.GetText()
(2, '')


>>> hwp.GetText()
(2, '"Food unites as well as distinguishes eaters |①because of what and how one eats forms much of one’s emotional tie to a group identity, |②is it a nation or an ethnicity.\r\n')


>>> hwp.GetText()
(3, ' The famous twentieth-century Chinese poet and scholar Lin Yutang remarks, “Our love for fatherland is largely a matter of recollection of the keen sensual pleasure of our childhood.\r\n')


>>> hwp.GetText()
(3, ' The loyalty to Uncle Sam is the loyalty to American doughnuts, and the loyalty to the Vaterland is the loyalty to Pfannkuchen and Stollen.”\r\n')


>>> hwp.GetText()
(3, '')


>>> hwp.GetText()
(4, '|③So keen connection between food and national or ethnic identification clearly indicates the truth that cuisine and table narrative occupy a significant place in the training grounds of a community and its civilization, and thus, eating, cooking, and talking about one’s cuisine |④are vital toa community’s wholeness and continuation? \r\n')


>>> hwp.GetText()
(5, '\r\n')


>>> hwp.GetText()
(3, 'In other words, the destiny of a community |⑤depends on how well it nourishes its members."\r\n')


>>> hwp.GetText()
(0, '')

>>> hwp.ReleaseScan()
상태값의 의미는 위의 표를 참고하시기 바랍니다.
GetText 메서드 사용을 마친 뒤에는
hwp.ReleaseScan()으로 "관련 정보를 초기화"해주어야 합니다.
 

 

그럼 여기서 어떻게 "|"로 찾아갈 수 있을까요?

그건 아래의 코드를 사용하시면 간단합니다.

hwp.MovePos(201)

 

이후의 과정은 한 번 끊고

다음 포스팅에서 이어서 알려드리겠습니다.

 

여기까지 정리하면

조금 장황하게 설명드렸지만,

이번 포스팅을 세 줄로 요약하면,

 

1. 찾아바꾸기 매크로를 hwp.InitScan, hwp.GetText 메서드로 대체해보자.

2. InitScan과 GetText는 파라미터가 다양한 만큼, 보다 자유로운 활용이 가능하기 때문이다.

3. GetText는 단순히 문자열만 리턴해준다. (찾아가서 수정하는 작업은 직접 코딩해야 한다.)

 

그리고 이후 작업,

즉, 다음 포스팅에서 다룰 내용은

MovePos나 문자열 인덱싱 등의 코드를 활용하는 방법이 되겠습니다.

 

GetText 실행 후에 찾아가서 수정하는 방법

안녕하세요? 일상의 코딩, 일코입니다. 지난 포스팅에서는, 문자열을 단락별로 탐색해서 리턴해주는 GetText라는 메서드를 소개해 드렸습니다. 2022.02.04 - [업무자동화/파이썬-아래아한글 자동화

martinii.fun

 

그럼 다음 포스팅에서 뵙겠습니다.

행복한 하루 되세요!

일코 드림

 

댓글