인프런 커뮤니티 질문&답변

윤병현님의 프로필 이미지
윤병현

작성한 질문수

직장인에게 꼭 필요한 파이썬-아래아한글 자동화 레시피

개체 참조가 개체의 인스턴스로 설정되지 않았습니다.

해결된 질문

작성

·

1.3K

1

안녕하세요 일코님

저번 답변으로 큰 도움을 얻었습니다. 감사합니다.

 

현재 제가 코드를 실행하면 아래와같은 경고메시지가 뜨는데..
하나씩 실행해가면서 봤을떄는 문제가 없었는데 아래와 같은 문제가 왜 발생하는지 모르겠습니다.

 

 

 

어떨땐 뜨고, 어떨땐 안뜨는데, 도무지 알수가 없네요...

 

전체 코드를 첨부드립니다.

 

 

import os
from tkinter.filedialog import askopenfilename, askopenfilenames
from pyhwpx import Hwp


def 타겟인덱스찾기(target,학년):
    # FindReplace 설정 초기화
    hwp.HAction.GetDefault("RepeatFind", hwp.HParameterSet.HFindReplace.HSet)
    hwp.HParameterSet.HFindReplace.FindString = f"{target[0]}년도 {target[1]:02}월 {학년} 학평 {target[2]:02}번"
    hwp.HParameterSet.HFindReplace.Direction = hwp.FindDir("Forward")
    hwp.HParameterSet.HFindReplace.FindType = 1
    hwp.HParameterSet.HFindReplace.IgnoreMessage = 1  # 메시지 무시 설정
    output = hwp.HAction.Execute("RepeatFind", hwp.HParameterSet.HFindReplace.HSet)
    if output == False:
        hwp.HAction.GetDefault("RepeatFind", hwp.HParameterSet.HFindReplace.HSet)
        hwp.HParameterSet.HFindReplace.FindString = f"{target[0]}년 {target[1]:02}월 {학년} 학평 {target[2]:02}번"
        hwp.HParameterSet.HFindReplace.Direction = hwp.FindDir("Forward")
        hwp.HParameterSet.HFindReplace.FindType = 1
        hwp.HParameterSet.HFindReplace.IgnoreMessage = 1  # 메시지 무시 설정
        return hwp.HAction.Execute("RepeatFind", hwp.HParameterSet.HFindReplace.HSet)
    else : 
        return True
    


def 워크북복수선택():
    """
    선택한 모든 파일들의 전체경로를 가져오는 함수
    """
    filelist = askopenfilenames(title="문제를 추출할 아래아한글 문서를 모두 선택해주세요.",
                                initialdir=os.getcwd(),
                                filetypes=[("아래아한글파일", "*.hwp *.hwpx")])
    return filelist




# hwp = Hwp().hwp # 현재 열린 한글 실행

if __name__ == '__main__':
    hwp = Hwp(visible=True)
    학년 = "고2"
    타겟리스트 = [(21,11,30), (21,9,30), (20,6,3),
                (23,6,31), (22,11,31), (23,6,34) , (22,3,33), (21,6,33), (22,11,35),
                (22,6,35), 
                (23,6,36) , (21,3,37),
                (20,9,38), (23,6,38), (21,9,39), (20,11,38),
                (22,9,40), (20,6,40), 
                (23,9,30), (20,11,30)
                ]
    
    doc_1 = hwp.XHwpDocuments.Item(0)  # output 문서
    hwp.SetMessageBoxMode(0x20000) # 예,아니오 경고창은 노로 대답하기
    
    
    
    워크북리스트 = 워크북복수선택()
    for 파일인덱스, 워크북 in enumerate(워크북리스트, start=1):
        doc_2 = hwp.XHwpDocuments.Add(False) # input문서 새로운 hwp열고 할당 (False=새로운창 / True = 기존hwp의 탭으로)
        hwp.Open(워크북)
        
        hwp.SetMessageBoxMode(0x20000) # 예,아니오 경고창은 노로 대답하기
        doc_2.SetActive_XHwpDocument()  # input문서

        
        # Unit 추출하기
            # '게시금지 ' 로 검색 
        hwp.HAction.GetDefault("RepeatFind", hwp.HParameterSet.HFindReplace.HSet)
        hwp.HParameterSet.HFindReplace.FindString = "게시금지 "
        hwp.HParameterSet.HFindReplace.Direction = hwp.FindDir("Forward")
        hwp.HParameterSet.HFindReplace.FindType = 1
        hwp.HParameterSet.HFindReplace.IgnoreMessage = 1  # 메시지 무시 설정
        hwp.HAction.Execute("RepeatFind", hwp.HParameterSet.HFindReplace.HSet)
        hwp.HAction.Run("Cancel")
        
            # Unit 칸으로 이동하여 복사하기
        hwp.HAction.Run("MoveParaEnd")
        hwp.HAction.Run("MoveRight")
        hwp.HAction.Run("MoveSelParaEnd")  # 현재 문단의 끝까지 블록 설정
        hwp.HAction.Run("Copy")  # 블록 설정된 텍스트를 클립보드로 복사
        hwp.HAction.Run("Cancel")
        
        doc_1.SetActive_XHwpDocument()  # output 문서 활성화
        
        
        # 복사한 텍스트를 문서에 입력
        if 파일인덱스 != 1 :
            hwp.HAction.Run("MoveDocEnd")
            hwp.HAction.Run("BreakPage")
        hwp.HAction.Run("Paste")
        hwp.HAction.Run("MoveSelLineBegin")
        for _ in range(10):  
            hwp.HAction.Run("CharShapeHeightIncrease")  # 텍스트 크기 증가
        hwp.HAction.Run("Cancel")
        hwp.HAction.Run("MoveParaEnd")
        hwp.HAction.GetDefault("PageSetup", hwp.HParameterSet.HSecDef.HSet)
        
        hwp.HParameterSet.HSecDef.PageDef.Landscape = 1
        hwp.HParameterSet.HSecDef.PageDef.BottomMargin = 0
        hwp.HParameterSet.HSecDef.HSet.SetItem("ApplyClass", 28)
        hwp.HParameterSet.HSecDef.HSet.SetItem("ApplyTo", 2)
        hwp.HAction.Execute("PageSetup", hwp.HParameterSet.HSecDef.HSet)

        doc_2.SetActive_XHwpDocument()  # input 활성화
    
        
        for 인덱스,타겟튜플 in enumerate(타겟리스트, start=1) :
            hwp.HAction.Run("MoveDocBegin")
            # 타겟 찾아서 쪽 복사하기
            if 타겟인덱스찾기(타겟튜플,학년):
                hwp.HAction.Run("CopyPage")
                # 두번째 문서 활성화 하고 쪽 붙여넣기
                doc_1.SetActive_XHwpDocument()  # output 문서 활성화
                hwp.HAction.Run("MoveDocEnd")
                hwp.HAction.Run("BreakPage")
                hwp.HAction.Run("PastePage")        
                if 인덱스 > 1:
                    hwp.SetMessageBoxMode(0x20)
                    hwp.HAction.Run("MovePrevParaEnd")
                    hwp.HAction.Run("Delete")
                    hwp.HAction.Run("Delete")
                hwp.HAction.Run("MoveDocEnd")

                doc_2.SetActive_XHwpDocument()  # input 문서 활성화
        현재경로 = doc_2.FullName
        doc_2.Close(False) #TRUE : 내용이 변경된 경우 닫지 않음, FALSE : 강제로 닫음

    hwp.SetMessageBoxMode(0xF0000) # 경고창이 기본모드로 바뀜
    hwp.SetMessageBoxMode(0xF0) 


    현재디렉토리 = os.path.dirname(현재경로)
    파일이름 = "상세분석_작업완료.hwp"
    저장경로 = os.path.join(현재디렉토리, 파일이름)

    doc_1.SaveAs(저장경로)
    hwp.Quit()
        
        
    

 

한두개를 작업할떄는 문제가 없었는데 여러개를 작업하니까 문제가 생기네요..ㅠㅠ

너무 큰 질문을 드리는것 같아 죄송하고 감사한 마음입니다..

늘 강의 잘 보고있고 업무에 큰도움 받고있습니다 정말 감사합니다.

 

 

 

 

답변 1

1

일코님의 프로필 이미지
일코
지식공유자

안녕하세요?

이 오류 역시 코드 자체에는 문제가 없어 보입니다. (아마도요..)

지난 번 오류 때처럼 PC환경이나 한/글 설치 또는 버전 관련한 오류로 보입니다.

왜냐면

doc_1이나 doc_2를 열고닫는 과정에서 인스턴스가 닫히더라도

저런 오류팝업이 뜨지 않고

예를 들면 doc_2가 None이 되어서 코드에 오류가 발생했다는

파이썬 오류메시지가 뜨게 되거든요.

 

혹시 지금 사용하시는 한/글 버전이 어떻게 되나요?(두 개 이상 설치되어 있나요?)

 

우선 아래와 같이 조치해 보시기 바랍니다.

 

  1. pythonwin.exe를 실행합니다.

경로는 일반적으로 가상환경을 사용하는 경우에는 가상환경을 활성화하시고

venv/Lib/site-packages/pythonwin/pythonwin.exe 를 실행하시면 되고,

가상환경을 쓰지 않으신다면 (또는 가상환경이 뭔지 모르신다면)

파이썬 설치폴더/Lib/site-packages/pythonwin/pythonwin.exe 를 실행하시면 됩니다.

 

 

  1. 아래와 같은 창이 뜨면 상단 메뉴의 Tools - COM MakePy utility 를 선택합니다.

image

  1. HwpObject 1.0 Type Library(1.0) 을 찾아서 선택한 후, OK 버튼을 누릅니다.

image

  1. 파이썬 콘솔 또는 에디터를 재시작한 후 다시 코드를 실행해보세요.

 

그런 후에도 동일한 팝업이 뜬다면

코드를 명령하는 속도보다 한/글이 프로세스를 연산하는 과정이 더 길어서(혹은 PC 속도가 느려서)

SetActive_XHwpDocument 명령어가 씹히고

의도하지 않았던 창이 닫혔다든지 하는 경우일 수도 있어요.

한/글의 특정 메서드들은 비동기로 연산되기 때문에

명령이 수행되고 있는 짧은 시간에

다른 명령이 들어오면 오류가 나는 경우들이 있거든요.

보통 그런 경우에는 적당히 오류가 발생하는 라인 앞에 time.sleep()을 추가하거나,

콜백처럼 완료확인 후 다음명령을 실행해야 하는 방법들이 있습니다.

 

번거로우시겠지만,

보여주신 오류팝업에 확인을 누른 후에

파이썬 콘솔에 출력되는 오류메시지 전체를 복사해서

댓글로 남겨주시겠어요?

 

지금은 재현하기가 어려워 설명이 장황한데,

심각하거나 엄청 어려운 문제는 아닙니다.

 

댓글 기다릴게요^^

윤병현님의 프로필 이미지
윤병현
질문자

강의 한번 구매한 것으로 이렇게 정성스런 질답서비스를 그냥 받아도 될 지 모르겠습니다...

정말 친절한 답변 매번 너무 감사합니다 ㅠㅠ

$ C:/Users/samsung-user/anaconda3/envs/hwpgod/python.exe c:/User$ C:/Users/samsung-user/anaconda3/envs/hwpgod/python.exe c:/Users/samsung-user/Documents/code_project/hwp_local/아잉카올림포스_ 상세분석.py

Rebuilding cache of generated files for COM support...

Checking 7D2B6F3C-1D95-4E0C-BF5A-5EE564186FBCx0x1x0

Could not add module (IID('{7D2B6F3C-1D95-4E0C-BF5A-5EE564186FBC}'), 0, 1, 0) - <class 'ImportError'>: cannot import name 'Dispatch' from partially initialized module 'win32com.client' (most likely due to a circular import) (C:\Users\samsung-user\anaconda3\envs\hwpgod\Lib\site-packages\win32com\client\__init__.py)

^^^^^^^^^^^^^^^^^^^^^^^^^^^^

File "C:\Users\SAMSUN~1\AppData\Local\Temp\gen_py\3.12\7D2B6F3C-1D95-4E0C-BF5A-5EE564186FBCx0x1x0.py", line 11029, in Add

ret = self._oleobj_.InvokeTypes(15000, LCID, 1, (9, 0), ((11, 1),),isTab

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

pywintypes.com_error: (-2147023170, '원격 프로시저를 호출하지 못했습니다.', None, None)

현재 터미널에 뜬 오류메시지는 위와 같습니다. 확인 버튼을 누르고 나서 이렇게 나왔습니다.

 

감사합니다!

 

 

 

일코님의 프로필 이미지
일코
지식공유자

pywintypes.com_error: (-2147023170, '원격 프로시저를 호출하지 못했습니다.', None, None)

위 오류는 조작하려는 한/글 창이 닫혀버려서 출력되는 메시지입니다.

Close나 Add 메서드 위아래 어디선가 병목 같은 게 있어서

빠르게 열고닫고를 반복하는 중에 열기 명령어가 누락된다든지(?) 하는 문제로 보입니다.

 

오류메시지로 원인을 추측해보면 (확실하지는 않지만)

118번 라인에서 doc_2.Close 작업이 진행중인데

다시 for문 처음으로 돌아가서 Add를 수행하면서 오류가 나는 것으로 추정됩니다.

 

해결이 될지 모르겠지만

from time import sleep

을 상단에 추가하시고,

 

for문 블록의 제일 마지막에

        현재경로 = doc_2.FullName
        doc_2.Close(False)  # TRUE : 내용이 변경된 경우 닫지 않음, FALSE : 강제로 닫음
        sleep(0.5)  # <---------

식으로 잠깐 쉬어주시면

해결되지 않을까 싶습니다.

그리고 코드가 어느 정도 완성되었으면 visible=False

백그라운드에서 실행하는 방법을 추천드려요.

키보드나 마우스조작이 영향을 주니까요.

 

제 PC에서는 재현이 되지 않아서 답변이 모호한데

모쪼록 잘 해결되었으면 좋겠고, 댓글 남겨주세요^^

만약 sleep을 0.5~1초 줬는데도 오류가 계속 난다면

제가 잘 돌아가는 코드를 한 번 만들어드리겠습니다.

 

그리고 제 강의가 온라인 강의들 중 저렴한 편은 아닌데요.

요즘은 질문 주시는 분들이 많지 않습니다.

질문 자주 남겨주시면 사실 기분이 좋습니다.

 

병현님도 행복한 하루 보내시기 바랍니다!

윤병현님의 프로필 이미지
윤병현
질문자

안녕하세요!! 문제를 잘해결했는데요.

혹시

아래와 같이 visible=False로 설정해도,

 hwp = Hwp(visible=False)


doc_temp = hwp.XHwpDocuments.Add(False)


새로운 문서를 열때는 또 눈에 보이게끔 창이 뜨는데,

새로운 문서를 할당할때 눈에 안보이게 하려면 어떻게해야할까요~~?

감사합니다!!




일코님의 프로필 이미지
일코
지식공유자

안녕하세요?

크게 두 가지 방법이 있는데

저는 가급적 1번을 추천드립니다.

 

1. 새 창이 아니라 새 탭으로 열기

백그라운드에서 코드가 잘 돌아간다는 게 확인이 되었으면

hwp.XHwpDocuments.Add(0) 에서 괄호 안의 0(새 창)을 1(새 탭)로 바꿔서

사용하시는 것을 추천드립니다.

 

만약 탭이 아니라 창으로 쓰시겠다면

아래처럼 수정해주시면 되겠습니다.

 

2. doc_2를 한 번 열고 숨긴 후 닫지 않기

 

  1. doc_2.Close(False) 대신에 doc_2.Clear(False) 로 수정(118번 라인?)

image

  1. doc_2 = hwp.XHwpDocuments.Add(False) 라인(54)을 for문 밖으로 옮기기

image

이렇게 두 부분을 수정하시면 됩니다.

워크북리스트 = 워크북복수선택()
    doc_2 = hwp.XHwpDocuments.Add(False)  # <----- for문 밖으로 뺐음
    hwp.set_visible = False  # <----- 다시 숨기기 명령 입력
    for 파일인덱스, 워크북 in enumerate(워크북리스트, start=1):
        ...
        ...
        ...
        현재경로 = doc_2.FullName
        doc_2.Clear(False)  # <----- Close 대신 Clear 사용

 

 

참고

혹시라도 pyhwpx를 쓰지 않으시게 된다면

hwp.set_visible(False) 대신 아래처럼 직접 API 명령어를 사용하실 수도 있습니다.

hwp.XHwpWindows.Item(0).Visible = False  # API 명령어

set_visible은 한/글 API가 아니라 pyhwpx에만 있는 메서드니까요.

그리고 마지막으로 한 가지 유의하실 점은 괄호 안에 어떤 정수를 넣든지,

해당 인덱스의 창이 아니라 단순히 활성화되어 있는 창이 백그라운드로 이동하게 됩니다.

이게 처음엔 자주 헷갈려요.

윤병현님의 프로필 이미지
윤병현

작성한 질문수

질문하기