안녕하세요? 조금씩 천천히 강의를 따라가고 있습니다 ^^ 글자속성 변경하기 챕터에서 특정 범위의 서체 변경하기를 따라 해 보고 있는데요. 빈문서를 만들고, 텍스트를 입력한 다음, 블럭을 설정하고, charshape = True를 입력하고, 실행시키면 화면에 나오는 것처럼 글자 속성이 변하지 않네요. 참고로 저는 Visual Studio Code로 작업을 하고 있습니다. 추측으로는, 열어 놓은 한글 파일에 접근할 수 있어야 하고 블럭설정한 부분을 읽어야 하는 것 같은데, 이 코드는 빠져 있는 건가요? 멋진 강의 감사합니다! ^^
import win32com.client import os import shutil # 캐시 디렉토리 경로 cache_dir = os.path.join(os.getenv('LOCALAPPDATA'), 'Temp', 'gen_py') # 캐시 디렉토리 삭제 if os.path.exists(cache_dir): shutil.rmtree(cache_dir) # 캐시 재생성 및 한글 객체 생성 hwp = win32com.client.gencache.EnsureDispatch("hwpframe.hwpobject") hwp.XHwpWindows.Item(0).Visible = True hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule") # 문서 시작 위치로 커서 이동 hwp.MovePos(2) # 문서 시작으로 커서 이동 # 표 생성: 행(5), 열(3) act = hwp.CreateAction("TableCreate") pset = act.CreateSet() act.GetDefault(pset) pset.SetItem("Cols", 3) pset.SetItem("Rows", 5) act.Execute(pset) 이게 실행코드고 오류는 --------------------------------------------------------------------------- ModuleNotFoundError Traceback (most recent call last) File ~\AppData\Roaming\Python\Python312\site-packages\win32com\client\gencache.py:255, in GetModuleForCLSID(clsid) 254 try: --> 255 __import__(sub_mod_name) 256 except ImportError: ModuleNotFoundError: No module named 'win32com.gen_py.7D2B6F3C-1D95-4E0C-BF5A-5EE564186FBCx0x1x0.IDHwpAction' During handling of the above exception, another exception occurred: FileNotFoundError Traceback (most recent call last) Cell In[3], line 21 18 hwp.MovePos(2) # 문서 시작으로 커서 이동 20 # 표 생성: 행(5), 열(3) ---> 21 act = hwp.CreateAction("TableCreate") 22 pset = act.CreateSet() 23 act.GetDefault(pset) File ~\AppData\Local\Temp\gen_py\3.12\7D2B6F3C-1D95-4E0C-BF5A-5EE564186FBCx0x1x0\IHwpObject.py:106, in IHwpObject.CreateAction(self, actidstr) 103 ret = self._oleobj_.InvokeTypes(10031, LCID, 1, (9, 0), ((8, 1),),actidstr 104 ) 105 if ret is not None: --> 106 ret = Dispatch(ret, 'CreateAction', None) 107 return ret File ~\AppData\Roaming\Python\Python312\site-packages\win32com\client\__init__.py:119, in Dispatch(dispatch, userName, resultCLSID, typeinfo, UnicodeToString, clsctx) 117 assert UnicodeToString is None, "this is deprecated and will go away" 118 dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch, userName, clsctx) --> 119 return __WrapDispatch(dispatch, userName, resultCLSID, typeinfo, clsctx=clsctx) File ~\AppData\Roaming\Python\Python312\site-packages\win32com\client\__init__.py:47, in __WrapDispatch(dispatch, userName, resultCLSID, typeinfo, UnicodeToString, clsctx, WrapperClass) 43 from . import gencache 45 # Attempt to load generated module support 46 # This may load the module, and make it available ---> 47 klass = gencache.GetClassForCLSID(resultCLSID) 48 if klass is not None: 49 return klass(dispatch) File ~\AppData\Roaming\Python\Python312\site-packages\win32com\client\gencache.py:200, in GetClassForCLSID(clsid) 198 if CLSIDToClass.HasClass(clsid): 199 return CLSIDToClass.GetClass(clsid) --> 200 mod = GetModuleForCLSID(clsid) 201 if mod is None: 202 return None File ~\AppData\Roaming\Python\Python312\site-packages\win32com\client\gencache.py:264, in GetModuleForCLSID(clsid) 261 info = demandGeneratedTypeLibraries[info] 262 from . import makepy --> 264 makepy.GenerateChildFromTypeLibSpec(sub_mod, info) 265 # Generate does an import... 266 mod = sys.modules[sub_mod_name] File ~\AppData\Roaming\Python\Python312\site-packages\win32com\client\makepy.py:377, in GenerateChildFromTypeLibSpec(child, typelibInfo, verboseLevel, progressInstance, bUnicodeToString) 374 progress.LogBeginGenerate(dir_path_name) 376 gen = genpy.Generator(typelib, info.dll, progress) --> 377 gen.generate_child(child, dir_path_name) 378 progress.SetDescription("Importing module") 379 importlib.invalidate_caches() File ~\AppData\Roaming\Python\Python312\site-packages\win32com\client\genpy.py:1363, in Generator.generate_child(self, child, dir) 1361 out_name = os.path.join(dir, an_item.python_name) + ".py" 1362 worked = False -> 1363 self.file = self.open_writer(out_name) 1364 try: 1365 if oleitem is not None: File ~\AppData\Roaming\Python\Python312\site-packages\win32com\client\genpy.py:1049, in Generator.open_writer(self, filename, encoding) 1039 def open_writer(self, filename, encoding="mbcs"): 1040 # A place to put code to open a file with the appropriate encoding. 1041 # Does *not* set self.file - just opens and returns a file. (...) 1046 # don't step on each others' toes. 1047 # Could be a classmethod one day... 1048 temp_filename = self.get_temp_filename(filename) -> 1049 return open(temp_filename, "wt", encoding=encoding) FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\lemon\\AppData\\Local\\Temp\\gen_py\\3.12\\7D2B6F3C-1D95-4E0C-BF5A-5EE564186FBCx0x1x0\\IDHwpAction.py.7700.temp' 이렇게 나오는데 해결할 수 있는 방법 있을까요?
안녕하세요, 일코님. 강사로서 콘텐츠를 만드는 모습과 수업의 열정에 저도 한 수 배웁니다. 강의를 들으면서 제 상황과 함께 몇 가지 문의드립니다. 요새 Langchain과 엮어서 hwp 파일을 자동화하는 프로그램을 만들고 있습니다. LLM 활용하여 업무를 효율화 하는 콘테스트 같은 것에 참여하는데 한글 파일을 수정해야하는 난관이 있어서 수업을 듣게 되었어요. 개발 기간이 한 달 남짓 남은 상황이라서, 질문으로 가장 효과적인 방법을 알 수 있을까하여 강사님께 조언을 요청드립니다. (hwp 5.0 파일 전체 구조를 분석할 시간이 안되네요..) 질문 3가지 드립니다. 1. 도표의 특정 부분, 내용의 특정 부분에 어떻게 문자열을 삽입할 것인가. 제가 개발하고 있는 프로세스는 이렇습니다. 보고서나 기획안을 작성해야 할 문장을 길게 받는다. 프롬프팅을 해서 LLM에 넣어서 리턴을 받는다. 대제목, 중제목, 소제목으로 포맷팅하여 HWP파일에 끼워 넣어서 export한다. 현재 FastAPI로 개발을 하고 있고, HWP 파일에 끼워 넣기 전 단계까지는 어떻게 개발이 끝난 상황입니다. 대제목의 갯수, 중제목의 갯수, 소제목과 내용은 배열로 받든 JSON 형태로 받든 규격화된 형태로 받아서 제가 일일이 끼워 넣을 예정입니다. 문제는 이겁니다. 현재 제가 가지고 있는 양식에 내용을 채워 넣으려고 합니다. (양식이 이것 외에 여러 개 입니다.) 누름틀로 자동화하는 강좌도 영상과 글로 보았고, 파일 내용을 읽어오는 것도 배웠는데 회사 로고나 도표가 함께 섞여있는 복잡한 문서를 처리하기에는 예제 대비 너무 어려운 상황입니다. 양식이 정해진 파일을 읽어와서, 해당 문자열 위치에 다시 규격화해서 넣을 수 있는 가장 효과적인 방법을 찾고 있습니다. ㅁ, ㅇ, - 등은 제가 넣을 때 임의로 삽입해서 넣으려고 합니다. 여기에서 저 특정 부분(대제목, 중제목, 소제목, 내용 모두)의 위치에 LLM에서 받은 문자열을 규격화해서 넣으려고 하는데, 가장 좋은 방법은 무엇일까요? (폰트와 글자 크기가 전부 다름) 2. 현재 가지고 있는 hwp 파일을 쉽게 분석할 수 있는 방법? txt파일이나 마크다운 파일 같은 것은 특정 파일 포인터를 읽거나, 원래 가지고 있는 문자열을 대충 정리해서 밀어 넣으면 정리가 가능했는데, hwp 파일은 이 자체가 워낙 규격화가 특이하게 되어있어서 분석이 어렵습니다. 제가 처리할 양식이 5개가 됩니다. 그 중에는 도표가 많은 것도 있고, 저 위에 있는 것 처럼 단순한 것도 있습니다. 어떻게 해야지 기존의 양식을 분석하고, 해당 부분에 문자열이나 문구를 정확하게 삽입할 수 있을까요? 3. 서버에서 한글 프로그램을 띄워놓고 새롭게 생성한 파일을 서빙하는 방법 현재 한글 프로그램을 실행시킨 이후에 그 내부에서 작업을 하는 것처럼 보이는데요. (크롬을 크롬드라이버로 자동화하는 것처럼) 하나의 양식을 여러 클라이언트에서 요청 받아서 생성을 완료하고 리턴해주려면 어떤 방식이 좋을까요? 예) 누름틀로 모든 영역을 다 분리해놓은 상태에서 하나 클라이언트를 띄우고, 해당 문서에 내용을 모두 바꾼 뒤에 다른 이름으로 저장하고 해당 파일을 return? 혹시 좋은 예제나 방법이 있을까 하여 여쭤봅니다. 가장 위의 2가지 질문은 같은 계열의 질문입니다만, 혹시나하여 첫 번째 질문에 예제를 같이 넘겨드립니다. 선배 개발자님이자, 강사님의 고견 여쭙습니다. 감사합니다. 답변 기다리겠습니다.
1) 강의 챕터 : [응용] 폴더에 있는 한/글 파일을 모두 열기 2) 질문사항 : 일단 한글파일이 있는 탐색기 폴더의 주소창에서 python을 입력해서 cmd 창을 띄운다음, 강의 내용처럼 따라하는데 import win32com.client as win32 를 입력하고 나니까 아래와 같이 에러메세지가 나오는데 왜 그런거죠?
1)질문에 대한 답변 내용의 캡쳐 사진이 너무 작아서 글자가 안보이는데 크게 볼 수 있는 방법이 없을까요? 2)그리고 강의에 나오는 움짤로 설명을 해주시는 걸 참고하려고 하면 빨리 지나가버리는데 움짤을 잠시 정지시켜놓고 보려고 해도 그 방법을 모르겠어요. 혹시 방법이 있을까요?
pyinstaller 사용시 에러 4900 WARNING: Library not found: could not resolve 'api-ms-win-crt-string-l1-1-0.dll', dependency of 'C:\\Users\\***\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\tcl86t.dll'. 명령 프로프트에서 실행해도 4524 WARNING: Library not found: could not resolve 'api-ms-win-crt-string-l1-1-0.dll', dependency of 'C:\\Users\\이종익\\AppData\\Local\\Programs\\Python\\Python312\\DLLs\\tcl86t.dll'. 해결 방법을 알고 싶어요
현재 문제 자동적으로 여러개의 선택상자를 입력하고 어떤것이 체크되었는지 확인하여 리턴할 것을 정해야하는 함수를 구현하려 합니다. 1번, 3번이 선택 되었다면 1, 3을 리턴하는 방식을 구현하려 했습니다. 제가 질문드린 내용을 구현하려면 [HwpAutomation.hwp 내부 사진] 다음사진에서 IHwpObject - IXHwpDocuments - IXHwpFormCheckButtons의 IXHwpFormCheckButton:양식 개체 체크 버튼 오브젝트에서 caption값을 수정하는 방법 value 값을 리턴하는 것 여기에서 사실 XHwpDocuments.XHwpFormCheckButtons를 해야한다고 생각했는데 안되는거 같아서 혹여 이 부분을 참고하여서 개발을 하려면 어떻게 이해를 해야할까요 ㅠㅠ
순번 5번, 8번의 8번째 칸의 모습처럼, 줄나누기후 같은 숫자(12)와 O를 넣는 자동화를 하고 싶습니다. 즉, 1. 일정한 순번을 리스트를 통해 나열하면 EX) [5, 8, 10-2, 12 ....] 2. 그 값이 있는 셀을 찾은 후 오른쪽으로 이동, 줄나누기, 셀에 값입력 이런 작업을 자동화 하고 싶은 것입니다. 2번 작업은 일상의 코딩님 강의와 블로그를 통해 해결할 수 있을 거 같긴한데, 1번 작업을 어떻게 처리할지 도저히 감히 잡히지 않습니다. (블로그를 보면 찾기 명령어는 자동화에 사용하지 않는 것 같고, hwp.find()를 이용하는 것도 감이 잡히지 않습니다.) 저런식으로 단순히 1,2,3으로 진행되는 것이 아니고, 중간 중간 규칙성 없이 가지번호(10-1,10-2)가 등장합니다 ㅠ 또한 숫자가 여러 열에 존재하고 있어서 1열(즉 순번열)에 있는 숫자만을 찾아야 한다는 문제도 있습니다. 자동화가 필요한 이유가 저런 식의 순번이 5천개가 넘어서 반드시 필요합니다. 도와주세요!!!
안녕하세요 일코님. 늘 많은 도움 감사합니다. 셀필드명을 표에 차례대로 부여하는데, 매크로 녹화를 이용해서 아래와 같이 코드를 짜보았습니다. hwp.move_to_field("답안") index = 1 while hwp.TableLowerCell(): hwp.HAction.Run("TableCellBlock"); hwp.HAction.GetDefault("TablePropertyDialog", hwp.HParameterSet.HShapeObject.HSet); hwp.HParameterSet.HShapeObject.ShapeTableCell.CellCtrlData.Name = f"{index}" hwp.HAction.Execute("TablePropertyDialog", hwp.HParameterSet.HShapeObject.HSet) hwp.Run("Cancle") index += 1 그런데 이렇게 실행하였을 때, AttributeError: '<win32com.gen_py.HwpObject 1.0 Type Library.HCtrlData instance at 0x2683750010768>' object has no attribute 'Name' 위와 같이 오류가 나는데요.. 매크로 스크립트를 잘 복붙한거 같은데 어떻게 수정할 수 있을까요? 감사합니다!
질문 남겨주셔서 감사합니다. 막히면 언제든 무엇이든 자주 질문 던져주세요. 수학/과학이나 알고리즘과는 달리업무자동화 코딩은 고민해서 풀리는 경우가 정말 드뭅니다.다시 말씀드리지만, 질문을 자주자주 남겨주세요. 저도 최대한 빠르게 회신 드리겠습니다. 당부드릴 두 가지가 있습니다. ① 가급적 구체적으로 설명해주세요. ② 특정 챕터 관련 질문 남겨주실 때는, 어느 챕터인지 알려주세요ㅜ ====================================pyhwpx 라이브러리 사용 중 문의드립니다.win32라이브러리로 창을 키워뒀다가 pyhwpx로 텍스트를 삽입하기 위해 객체를 선언하면다시 창이 작아지는 문제가 있습니다.pyhwpx에서 한글 창을 최대로 키우는 코드가 무엇일까요?pyhwpx는 관련 정보를 찾을 수가 없어 문의드립니다.늘 감사합니다.
안녕하세요 일코님 좋은 강의를 해주셔서 감사합니다. 제가 지금 하고 있는 작업은 한글파일이 pdf파일로 변환된 파일을 다시 한글파일로 변환하는 것입니다. 이때, 한PDF를 사용하면 한글파일로 아주 나이스하게 변환되는 것을 보고 이걸 파이썬으로 자동화할 수 없을까 고민하고 있습니다. pdf를 일반 파이썬 라이브러리로 읽어와서 text로 변환하는 코드말고 한pdf의 기능을 이용하여 pdf를 한글파일로 바로 변경할 수 있는 라이브러리나 코드가 있을까요? 늘 감사드립니다
안녕하세요. 좋은 강의 잘 듣고 있습니다. 감사합니다. 이번에 실무에 적용해보려고 이 강의를 수강하였는데요, 제가 하고 싶은 자동화는 한글파일로 된 신청서의 표에 적힌 정보를 가져와서 다른 한글파일의 표에 넣는 것입니다. 강의를 듣던 중 한글 파일의 표를 생성하고 쓰는 것은 알게 되었는데 한글 파일에 작성된 표에서 정보를 가져오는 방법은 알지 못해 질문드립니다. 감사합니다.
안녕하세요 일코님 강의 잘 듣고 있습니다. 한글 찾기를 이용해서 작업을 하고 있습니다. 다른 부분은 모두 잘 작동하는 데 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('모두 완료')
감사합니다.!!! 열심히 따라가며 공부하고 있는데,, 아직은 파이썬 자체의 문법도 잘 모르고 있어서 열심히 검색하며 공부하고 있습니다. ㅠㅠ 필수보직기간 내 전보 사전승인통보서 자동화 프로젝트필수보직기간 내 전보 사전승인통보서 자동화 프로젝트 그 중에서 <필수보직기간 내 전보 사전승인통보서 자동화 프로젝트> for 행인덱스, 행데이터 in enumerate (엑셀데이터): 사전전보승인일, 직급, 전보대상자, 전보일, 기존부서, 전보부서, 근무시작일, 근무종료일, 근무기간, 전보유형 = 행데이터 요 부분이 이해가 안갑니다... 사전전보승인일, 직급, 전보대상자, 전보일, 기존부서, 전보부서, 근무시작일, 근무종료일, 근무기간, 전보유형 = 행데이터 이 과정이 어떤 과정을 처리하는건가요? a,b,c,d = e 구조인데 이것이 무엇을 의미하는지 모르겠습니다. 인덱스(??)를 붙이는건가여?
안녕하세요. 일코님 강의 들으면서, hwp를 데이터베이스로 활용하는 방법을 많이 고심하고있는데요. 예를들어 영어 구문 1000문장이 데이터베이스로 아래와같이 hwp상의 표로 존재한다고 할때, 위와 같이 번호별로 영어구문의 답지를 데이터베이스로 삼고, 학생별로 틀린 문장을 기록한뒤에 함수를 작동시키면 학생별로 틀린 문항번호의 답지만 hwp로 출력할 수 있게 해주고자 합니다. 그런데 문제는, 학생별로 틀린문장이 다 다르기 때문에, 학생별로 뽑아줄 hwp의 표의 행 수를 미리 정해놓을 수 없다는 점입니다. 그렇다고 표의 행수를 무작정 많이 만들어놓으면, 표의 행이 너무 많이 비게 되어 종이 낭비가 발생하구요.. 논리적으로 이 문제를 어떻게 해결할 수 있을까요? 늘 감사합니다^^