문서 안에 있는 표를 훑으면서 표 안에 있는 텍스트를 추출하는 프로그램을 개발하려고 합니다.
표와 셀을 훑는 것은 많은 분들이 공유해준 예제가 있어서 구현했습니다.
해당 셀이 '셀 합치기’로 합쳐진 셀인지 알 수 있는 방법이 궁금합니다.
합쳐진 셀이면 '셀 나누기’를 해서 나뉜 셀에 같은 값을 복사해 넣으려고 합니다.
제가 구현해서 테스트한 소스는 아래와 같습니다.
python으로 구현하고 있습니다만, 다른 언어로 방법을 알려주셔도 상관없습니다.
고맙습니다…
def extract_table_text(hwp_app):
ctrl = hwp_app.HeadCtrl # 첫번째 컨트롤(HaedCtrl)부터 탐색 시작.
row_text = ""
while ctrl != None:
if ctrl.CtrlID == "tbl":
hwp_app.SetPosBySet(ctrl.GetAnchorPos(0))
hwp_app.FindCtrl()
hwp_app.Run("ShapeObjTableSelCell")
row_text += get_table_cell_text(hwp_app) + "|"
while hwp_app.HAction.Run("TableRightCell"):
row_text += get_table_cell_text(hwp_app) + "|"
print(row_text, "\n\n")
row_text = ""
ctrl = ctrl.Next
def get_table_cell_text(hwp_app):
cell_text = ""
try:
hwp_app.InitScan(Range = 0x00ff)
state = 2
while state not in [0, 1]:
state, text = hwp_app.GetText()
cell_text += text
finally:
hwp_app.ReleaseScan()
return cell_text
2개의 좋아요
1. 위 방식은 (병합된 셀을 제외하고) 모든 셀의 너비와 높이가 일정한 경우에만 작동합니다ㅜ
2. 클립보드를 사용하지 않는 대신 셀 주소 이름의 필드를 활용하므로, 유의 바랍니다.
셀 주소 문자열을 이용하거나, 캐럿을 직접 옮겨다니면서 병합하는 방식이
훨씬 쿨한 것 같은데, 막상 구현해보면 한 가지 이상씩 예외들이 있었거든요…ㅜ
제가 임의로 짠 메서드(pyhwpx 모듈)가 일부 섞여 있기는 하지만
소스코드를 읽어보시면 프로세스는 쉽게 이해하시리라 생각합니다.
아래는 전체 소스코드입니다.
# 아래아한글 연결
from pyhwpx import Hwp
hwp = Hwp()
# 표너비/높이 및 행/열 수 추출
hwp.TableCellBlockExtendAbs()
hwp.TableCellBlockExtend()
sel_addr = hwp.get_selected_range()
cols = len({i[0] for i in sel_addr}) # 열 수
rows = len({i[1] for i in sel_addr}) # 행 수
table_width = hwp.get_table_width() # 표 너비
table_height = hwp.get_table_height() # 표 높이
hwp.Cancel()
hwp.TableColBegin() # A1 셀로 이동
hwp.TableColPageUp()
# 셀 순회하며 병합해제작업
hwp.fill_addr_field() # 모든 셀에 셀주소 필드명 달아놓기
hwp.TableColBegin() # A1셀로 이동
hwp.TableColPageUp()
fill_dict = {} # 병합해제 후 {채울주소:값} 사전 초기화
while True:
val = hwp.get_selected_text()
unit_col = table_width / cols # 단위열너비
unit_height = table_height / rows # 단위행너비
split_col = round(hwp.get_col_width() / unit_col) # 나눌 열 수
split_row = round(hwp.get_row_height() / unit_height) # 나눌 행 수
if split_row + split_col > 2:
hwp.TableCellBlock()
hwp.TableSplitCell(split_row, split_col) # 쪼개기
sel_addr = tuple(hwp.get_selected_range()) # 병합해제된 셀 범위 추출
fill_dict[sel_addr] = val # 셀범위:채울값 추가
if not hwp.TableRightCell(): # 표 끝에 도달하면 종료
break
hwp.Cancel()
hwp.fill_addr_field() # 병합해제된 모든 셀에 셀주소 필드 추가
[
hwp.put_field_text(addr, fill_dict[addrs])
for addrs in fill_dict
for addr in addrs
] # 빈 셀에 값 추가
hwp.unfill_addr_field() # 모든 셀의 필드 제거
# 판다스 데이터프레임 추출
df = hwp.table_to_df()
print(df)
간단한 작업 같은데 코드가 제법 기네요…
도움이 되었길 바랍니다ㅜㅜ
3개의 좋아요
(위 댓글에 이어서)
만약 표에 필드가 매겨져 있고, 필드정보를 유지하시려면
fill_addr_field 메서드를 사용하면 안 되므로ㅜ
아래 코드를 참고해 주시기 바랍니다.
(필드 대신 클립보드를 사용합니다.)
# 표너비/높이 및 행/열 정보 추출
hwp.TableCellBlockExtendAbs() # 셀 전체 선택
hwp.TableCellBlockExtend()
sel_addr = hwp.get_selected_range() # 셀 주소 리스트 추출
cols = len({i[0] for i in sel_addr}) # 열 갯수
rows = len({i[1] for i in sel_addr}) # 행 갯수
unit_width = table_width / cols # 셀 너비
unit_height = table_height / rows # 셀 높이
table_width = hwp.get_table_width() # 표 너비
table_height = hwp.get_table_height() # 표 높이
# 셀 순회하며 병합해제작업
hwp.TableColBegin() # A1셀로 이동
hwp.TableColPageUp()
while True:
hwp.SelectAll() #
hwp.Copy() # 셀 내용 복사
split_col = round(hwp.get_col_width() / unit_width) # 나눌 열 갯수
split_row = round(hwp.get_row_height() / unit_height) # 나눌 행 갯수
if split_row + split_col > 2:
hwp.TableCellBlock()
hwp.TableSplitCell(split_row, split_col) # 셀 나누기
hwp.paste(5) # 복사한 내용 일괄 붙여넣기
if not hwp.TableRightCell(): # 표 끝까지 반복
break
hwp.Cancel()
작동방식은 비슷한데, 코드는 다소 간결해지는 느낌이네요.
도움이 되었길 바랍니다.
3개의 좋아요
고맙습니다.
알려주신 소스는 아래 제가 구현하고 있는 소스에서 extract_table_text() 함수로 만들었습니다.
실행하면 "캐럿이 표 안에 있어야 합니다."라는 오류 문구가 보여서 해결해보려고 다른 함수도 그 전에 호출해보는데 잘 안 됩니다. 혹시 해결방법 아시는지요.
제가 HWP ActiveX 다루는 게 처음이라 어려움이 많습니다. HWP automation 개발 시작하는 사람에게 참고, 도움이 될 만한 글이 있으면 알려 주십시오. 다른 ActiveX 프로그램은 몇 번 해봤는데 HWP는 처음입니다. -_-
다시 한번 고맙단 말씀 드립니다.
def extract_all_table_text(hwp):
ctrl = hwp.HeadCtrl
while ctrl != None:
if ctrl.CtrlID == "tbl":
# hwp.set_pos_by_set(ctrl.GetAnchorPos(0))
# hwp.FindCtrl()
# hwp.ShapeObjTableSelCell()
extract_table_text(hwp)
ctrl = ctrl.Next
def extract_table_text1(hwp):
# 표너비/높이 및 행/열 수 추출
hwp.TableCellBlockExtendAbs()
hwp.TableCellBlockExtend()
sel_addr = hwp.get_selected_range()
... (이하 생략)
3개의 좋아요
해당 함수를 실행하기 전에 캐럿이 표 안에 들어가 있어야 합니다^^
1개의 좋아요
셀이 병합된 셀인지 아닌지만 알아보는 내용입니다.
vb.net 코드로 되어있습니다.
아래 링크에 소스코드 첨부해 놓았습니다.
https://blog.naver.com/kosohn/223394223308
3개의 좋아요