1번문항채점가능

This commit is contained in:
devdra9
2025-01-08 17:43:24 +09:00
parent ec3a3ba833
commit a4b6e22e4f
80 changed files with 1219 additions and 56 deletions

34
.gitignore vendored Normal file
View File

@@ -0,0 +1,34 @@
output/워드(한글)-009926-진성훈.hml
output/워드(한글)-009927-한지수.hml
output/워드(한글)-009928-윤아르.hml
output/워드(한글)-009929-김준영.hml
output/워드(한글)-009930-문윤재.hml
output/워드(한글)-009931-이선우.hml
output/워드(한글)-009932-최다솜.hml
output/워드(한글)-009933-이지한.hml
output/워드(한글)-009934-고서진.hml
output/워드(한글)-009935-이가은.hml
output/워드(한글)-009936-이라현.hml
output/워드(한글)-009937-진성준.hml
output/워드(한글)-009938-김규리.hml
output/워드(한글)-009939-이준.hml
output/워드(한글)-009940-김지민.hml
output/워드(한글)-009941-윤지후.hml
output/워드(한글)-009942-최원준.hml
output/워드(한글)-009943-윤헤르.hml
output/워드(한글)-009944-현지후.hml
output/워드(한글)-009945-고재웅.hml
output/워드(한글)-009946-홍규진.hml
output/워드(한글)-010120-고하진.hml
output/워드(한글)-010121-고한율.hml
output/워드(한글)-010122-손서아.hml
output/워드(한글)-010123-김지온.hml
output/워드(한글)-010124-안서정.hml
output/워드(한글)-010125-강지환.hml
output/워드(한글)-010126-고여진.hml
output/워드(한글)-010127-고재범.hml
output/워드(한글)-010128-윤빈.hml
output/워드(한글)-010129-유승재.hml
output/워드(한글)-010130-고강은.hml
output/원본 copy.hml
output/원본.hml

Binary file not shown.

Binary file not shown.

Binary file not shown.

18
demicalToRGB.py Normal file
View File

@@ -0,0 +1,18 @@
def demicalToRGB(demical_value):
b = demical_value // 65536
g = ( demical_value % 65536 ) // 256
r = ( demical_value % 65536 % 256 )
return (r, g, b)
def RGBtoDemical(r, g, b):
return (b * 65536) + (g * 256) + r
def main():
rgb = demicalToRGB(10040115)
print( rgb )
demical = RGBtoDemical(11, 22, 33)
print( demical )
if __name__ == "__main__":
main()

47
diff_hwp.py Normal file
View File

@@ -0,0 +1,47 @@
import olefile
import difflib
def extract_text_from_hwp(file_path):
"""
HWP 파일에서 텍스트를 추출합니다.
"""
try:
ole = olefile.OleFileIO(file_path)
if ole.exists('BodyText/Section0'):
content = ole.openstream('BodyText/Section0').read()
text = content.decode('utf-16le', errors='ignore')
return text
else:
print(f"No 'BodyText/Section0' stream found in {file_path}")
return ''
except Exception as e:
print(f"Error extracting text from {file_path}: {e}")
return ''
def compare_texts(text1, text2):
"""
두 텍스트의 차이를 비교하고 차이점을 카운트합니다.
"""
diff = difflib.ndiff(text1.splitlines(), text2.splitlines())
diff_count = 0
for line in diff:
if line.startswith('+ ') or line.startswith('- '):
diff_count += 1
return diff_count
def main():
file1 = r'C:\Users\dra\project\HWP-Scoring\input\원본.hwp'
file2 = r'C:\Users\dra\project\HWP-Scoring\input\원본 copy.hwp'
text1 = extract_text_from_hwp(file1)
text2 = extract_text_from_hwp(file2)
if not text1 or not text2:
print("텍스트를 추출하지 못했습니다.")
return
diff_count = compare_texts(text1, text2)
print(f"차이점 개수: {diff_count}")
if __name__ == "__main__":
main()

View File

@@ -1,12 +1,370 @@
2024-11-06 15:06:07,560 - INFO - 변환 성공: 1.hwp -> 1.xml 2024-11-06 15:06:07,560 - INFO - ?? ??: 1.hwp -> 1.xml
2024-11-06 15:06:07,857 - INFO - 변환 성공: 2.hwp -> 2.xml 2024-11-06 15:06:07,857 - INFO - ?? ??: 2.hwp -> 2.xml
2024-11-06 15:28:35,640 - INFO - 변환 성공: 1.hwp -> 1.xml 2024-11-06 15:28:35,640 - INFO - ?? ??: 1.hwp -> 1.xml
2024-11-06 15:28:35,654 - INFO - BINDATA 섹션 제거 완료: C:\Users\gzero-ser7-win11\Documents\hwpTest\Output\1.xml 2024-11-06 15:28:35,654 - INFO - BINDATA ?? ?? ??: C:\Users\gzero-ser7-win11\Documents\hwpTest\Output\1.xml
2024-11-06 15:28:35,933 - INFO - 변환 성공: 2.hwp -> 2.xml 2024-11-06 15:28:35,933 - INFO - ?? ??: 2.hwp -> 2.xml
2024-11-06 15:28:35,948 - INFO - BINDATA 섹션 제거 완료: C:\Users\gzero-ser7-win11\Documents\hwpTest\Output\2.xml 2024-11-06 15:28:35,948 - INFO - BINDATA ?? ?? ??: C:\Users\gzero-ser7-win11\Documents\hwpTest\Output\2.xml
2024-11-06 15:31:54,423 - INFO - 변환 성공: 1.hwp -> 1.xml 2024-11-06 15:31:54,423 - INFO - ?? ??: 1.hwp -> 1.xml
2024-11-06 15:31:54,437 - INFO - BINDATASTORAGE 섹션 제거 완료: C:\Users\gzero-ser7-win11\Documents\hwpTest\Output\1.xml 2024-11-06 15:31:54,437 - INFO - BINDATASTORAGE ?? ?? ??: C:\Users\gzero-ser7-win11\Documents\hwpTest\Output\1.xml
2024-11-06 15:31:54,697 - INFO - 변환 성공: 2.hwp -> 2.xml 2024-11-06 15:31:54,697 - INFO - ?? ??: 2.hwp -> 2.xml
2024-11-06 15:31:54,711 - INFO - BINDATASTORAGE 섹션 제거 완료: C:\Users\gzero-ser7-win11\Documents\hwpTest\Output\2.xml 2024-11-06 15:31:54,711 - INFO - BINDATASTORAGE ?? ?? ??: C:\Users\gzero-ser7-win11\Documents\hwpTest\Output\2.xml
2024-11-06 15:34:34,911 - INFO - 변환 성공: 1.hwp -> 1.xml 2024-11-06 15:34:34,911 - INFO - ?? ??: 1.hwp -> 1.xml
2024-11-06 15:34:35,179 - INFO - 변환 성공: 2.hwp -> 2.xml 2024-11-06 15:34:35,179 - INFO - ?? ??: 2.hwp -> 2.xml
2024-12-12 17:13:54,311 - ERROR - ?????? ???? ????: (-2147221005, '????? ????? ?????????.', None, None)
2024-12-12 17:17:08,151 - ERROR - ?????? ???? ????: (-2147221005, '????? ????? ?????????.', None, None)
2024-12-12 17:19:09,440 - ERROR - 프로그램 실행 오류: (-2147221005, '잘못된 클래스 문자열입니다.', None, None)
2024-12-12 17:24:27,480 - ERROR - 프로그램 실행 오류: (-2147221005, '잘못된 클래스 문자열입니다.', None, None)
2024-12-12 17:24:34,564 - ERROR - 프로그램 실행 오류: (-2147221005, '잘못된 클래스 문자열입니다.', None, None)
2024-12-12 17:41:38,095 - ERROR - 프로그램 실행 오류: (-2147221005, '잘못된 클래스 문자열입니다.', None, None)
2024-12-12 17:42:57,301 - ERROR - 프로그램 실행 오류: (-2147221005, '잘못된 클래스 문자열입니다.', None, None)
2024-12-12 17:43:21,267 - ERROR - 프로그램 실행 오류: (-2147221005, '잘못된 클래스 문자열입니다.', None, None)
2024-12-12 17:43:34,587 - ERROR - 프로그램 실행 오류: (-2147221005, '잘못된 클래스 문자열입니다.', None, None)
2024-12-19 16:04:58,214 - ERROR - 프로그램 실행 오류: can only concatenate str (not "WindowsPath") to str
2024-12-19 16:06:37,560 - ERROR - 프로그램 실행 오류: can only concatenate str (not "WindowsPath") to str
2024-12-19 16:12:24,688 - ERROR - 프로그램 실행 오류: can only concatenate str (not "WindowsPath") to str
2024-12-19 16:13:25,067 - ERROR - 프로그램 실행 오류: can only concatenate str (not "WindowsPath") to str
2024-12-19 16:17:52,881 - ERROR - 프로그램 실행 오류: can only concatenate str (not "WindowsPath") to str
2024-12-19 16:18:31,219 - ERROR - 프로그램 실행 오류: can only concatenate str (not "WindowsPath") to str
2024-12-19 16:20:20,736 - ERROR - 프로그램 실행 오류: can only concatenate str (not "WindowsPath") to str
2024-12-19 16:20:33,588 - ERROR - 프로그램 실행 오류: can only concatenate str (not "WindowsPath") to str
2024-12-19 16:22:35,234 - ERROR - 프로그램 실행 오류: can only concatenate str (not "WindowsPath") to str
2024-12-19 16:24:13,766 - ERROR - 프로그램 실행 오류: can only concatenate str (not "WindowsPath") to str
2024-12-19 16:26:11,624 - ERROR - 프로그램 실행 오류: can only concatenate str (not "WindowsPath") to str
2024-12-19 16:28:35,545 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:28:35,556 - ERROR - 파일 변환 실패: 제2401회_디지털정보활용능력_워드프로세서한글NEO버전_D형.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:30:34,181 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:30:34,194 - ERROR - 파일 변환 실패: 제2401회_디지털정보활용능력_워드프로세서한글NEO버전_D형.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:35:16,841 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:35:16,863 - ERROR - 파일 변환 실패: 제2401회_디지털정보활용능력_워드프로세서한글NEO버전_D형.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:38:21,076 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:38:21,095 - ERROR - 파일 변환 실패: 제2401회_디지털정보활용능력_워드프로세서한글NEO버전_D형.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:39:16,265 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:39:16,288 - ERROR - 파일 변환 실패: 제2401회_디지털정보활용능력_워드프로세서한글NEO버전_D형.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:39:53,545 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:39:53,567 - ERROR - 파일 변환 실패: 제2401회_디지털정보활용능력_워드프로세서한글NEO버전_D형.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:40:04,690 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:40:04,712 - ERROR - 파일 변환 실패: 제2401회_디지털정보활용능력_워드프로세서한글NEO버전_D형.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:40:51,845 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:40:51,870 - ERROR - 파일 변환 실패: 제2401회_디지털정보활용능력_워드프로세서한글NEO버전_D형.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:43:08,169 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:43:08,179 - ERROR - 파일 변환 실패: 제2401회_디지털정보활용능력_워드프로세서한글NEO버전_D형.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:44:03,210 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:44:03,220 - ERROR - 파일 변환 실패: 제2401회_디지털정보활용능력_워드프로세서한글NEO버전_D형.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:45:56,659 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-19 16:45:56,669 - ERROR - 파일 변환 실패: 제2401회_디지털정보활용능력_워드프로세서한글NEO버전_D형.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:07:45,854 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:10:43,692 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:11:34,642 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:12:06,072 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:13:14,726 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:13:57,663 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:15:12,205 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:15:35,127 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:16:03,096 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:16:33,628 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:19:37,416 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:21:19,021 - ERROR - 파일 변환 실패: 글맵씨레드.hwp - (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:22:18,656 - ERROR - 파일 변환 실패: 글맵씨레드.hwp -> (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:23:17,429 - ERROR - 파일 변환 실패: 글맵씨레드.hwp -> (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:25:14,538 - ERROR - 파일 변환 실패: 글맵씨레드.hwp -> (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:25:34,197 - ERROR - 파일 변환 실패: 글맵씨레드.hwp -> (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:27:16,535 - ERROR - 프로그램 실행 오류: (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:27:40,425 - ERROR - 프로그램 실행 오류: (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:27:59,717 - ERROR - 프로그램 실행 오류: (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:28:53,820 - ERROR - 프로그램 실행 오류: (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:29:30,598 - ERROR - 프로그램 실행 오류: (-2147352562, '매개 변수의 개수가 잘못되었습니다.', None, None)
2024-12-20 15:32:04,671 - INFO - 변환 성공: 글맵씨레드.hwp -> 글맵씨레드.xml
2024-12-20 15:34:16,298 - INFO - 변환 성공: 글맵씨레드.hwp -> 글맵씨레드.xml
2024-12-20 15:36:29,131 - INFO - 변환 성공: 글맵씨레드.hwp -> 글맵씨레드.hml
2024-12-20 15:51:05,324 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 15:54:14,192 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 15:58:20,482 - INFO - 변환 성공: 레드.hwp -> 레드.hwp
2024-12-20 15:59:21,068 - INFO - 변환 성공: 레드.hwp -> 레드.hwp
2024-12-20 16:01:19,262 - INFO - 변환 성공: 레드.hwp -> 레드.hwp
2024-12-20 16:04:32,762 - ERROR - 파일 변환 실패: 레드.hwp -> IHwpObject.SaveAs() got an unexpected keyword argument 'compress'
2024-12-20 16:07:38,479 - INFO - 변환 성공: 레드.hwp -> 레드.hwpx
2024-12-20 16:12:26,303 - ERROR - 파일 변환 실패: 레드.hwp -> IHwpObject.Open() got an unexpected keyword argument 'format'
2024-12-20 16:12:44,903 - ERROR - 파일 변환 실패: 레드.hwp -> IHwpObject.SaveAs() got an unexpected keyword argument 'format'
2024-12-20 16:13:11,506 - ERROR - 파일 변환 실패: 레드.hwp -> IHwpObject.SaveAs() got an unexpected keyword argument 'format'
2024-12-20 16:17:17,544 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 16:38:34,069 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 16:44:11,425 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 16:44:50,795 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 16:45:38,040 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 16:46:54,074 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 16:47:23,854 - ERROR - 파일 변환 실패: 레드.hwp -> cannot access local variable 'xml_path' where it is not associated with a value
2024-12-20 16:48:03,734 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 16:49:02,069 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 16:54:06,270 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 16:54:06,601 - INFO - 변환 성공: 레드_글자처럼취급_선택해제.hwp -> 레드_글자처럼취급_선택해제.hml
2024-12-20 16:55:24,158 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 16:55:24,379 - INFO - 변환 성공: 레드_글자처럼취급_선택해제.hwp -> 레드_글자처럼취급_선택해제.hml
2024-12-20 17:18:01,548 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 17:18:01,839 - INFO - 변환 성공: 레드_글자처럼취급_선택해제.hwp -> 레드_글자처럼취급_선택해제.hml
2024-12-20 17:18:01,978 - INFO - 변환 성공: 왼쪽정렬.hwp -> 왼쪽정렬.hml
2024-12-20 17:20:12,682 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 17:20:12,978 - INFO - 변환 성공: 레드_글자처럼취급_선택해제.hwp -> 레드_글자처럼취급_선택해제.hml
2024-12-20 17:20:13,117 - INFO - 변환 성공: 레드_왼쪽정렬.hwp -> 레드_왼쪽정렬.hml
2024-12-20 17:21:23,098 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 17:21:23,417 - INFO - 변환 성공: 레드_글자처럼취급_선택해제.hwp -> 레드_글자처럼취급_선택해제.hml
2024-12-20 17:21:23,544 - INFO - 변환 성공: 레드_센터정렬.hwp -> 레드_센터정렬.hml
2024-12-20 17:21:23,669 - INFO - 변환 성공: 레드_왼쪽정렬.hwp -> 레드_왼쪽정렬.hml
2024-12-20 17:21:25,438 - ERROR - 프로그램 실행 오류: (-2147417851, '서버에서 예외 오류가 발생했습니다.', None, None)
2024-12-20 17:23:58,327 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 17:23:58,686 - INFO - 변환 성공: 레드_글자처럼취급_선택해제.hwp -> 레드_글자처럼취급_선택해제.hml
2024-12-20 17:23:58,812 - INFO - 변환 성공: 레드_센터정렬.hwp -> 레드_센터정렬.hml
2024-12-20 17:23:58,932 - INFO - 변환 성공: 레드_오른쪽정렬.hwp -> 레드_오른쪽정렬.hml
2024-12-20 17:26:38,105 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 17:26:38,400 - INFO - 변환 성공: 레드_글자처럼취급_선택해제.hwp -> 레드_글자처럼취급_선택해제.hml
2024-12-20 17:26:38,510 - INFO - 변환 성공: 레드_센터정렬.hwp -> 레드_센터정렬.hml
2024-12-20 17:26:38,601 - INFO - 변환 성공: 레드_오른쪽정렬.hwp -> 레드_오른쪽정렬.hml
2024-12-20 17:32:04,152 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 17:32:04,435 - INFO - 변환 성공: 레드_center.hwp -> 레드_center.hml
2024-12-20 17:32:06,413 - INFO - 변환 성공: 레드_right.hwp -> 레드_right.hml
2024-12-20 17:32:06,531 - INFO - 변환 성공: 레드_글자처럼취급_선택해제.hwp -> 레드_글자처럼취급_선택해제.hml
2024-12-20 17:32:15,159 - INFO - 변환 성공: 레드.hwp -> 레드.hml
2024-12-20 17:32:15,448 - INFO - 변환 성공: 레드_center.hwp -> 레드_center.hml
2024-12-20 17:32:15,586 - INFO - 변환 성공: 레드_right.hwp -> 레드_right.hml
2024-12-20 17:32:15,716 - INFO - 변환 성공: 레드_글자처럼취급_선택해제.hwp -> 레드_글자처럼취급_선택해제.hml
2024-12-23 13:04:30,302 - INFO - 변환 성공: 원본-글자처럼취급제외.hwp -> 원본-글자처럼취급제외.hml
2024-12-23 13:04:30,598 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-23 13:17:25,923 - INFO - 변환 성공: 원본-글자처럼취급제외.hwp -> 원본-글자처럼취급제외.hml
2024-12-23 13:17:26,252 - INFO - 변환 성공: 원본-좌측정렬.hwp -> 원본-좌측정렬.hml
2024-12-23 13:17:26,392 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-23 13:34:31,540 - INFO - 변환 성공: 원본-글자처럼취급제외.hwp -> 원본-글자처럼취급제외.hml
2024-12-23 13:34:31,900 - INFO - 변환 성공: 원본-좌측정렬.hwp -> 원본-좌측정렬.hml
2024-12-23 13:34:32,041 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-23 14:22:43,185 - INFO - 변환 성공: 원본-글자처럼취급제외.hwp -> 원본-글자처럼취급제외.hml
2024-12-23 14:22:43,452 - INFO - 변환 성공: 원본-밑줄추가.hwp -> 원본-밑줄추가.hml
2024-12-23 14:22:43,572 - INFO - 변환 성공: 원본-좌측정렬.hwp -> 원본-좌측정렬.hml
2024-12-23 14:22:43,706 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-23 14:29:55,647 - INFO - 변환 성공: 원본-글자처럼취급제외.hwp -> 원본-글자처럼취급제외.hml
2024-12-23 14:29:55,873 - INFO - 변환 성공: 원본-밑줄추가.hwp -> 원본-밑줄추가.hml
2024-12-23 14:29:56,007 - INFO - 변환 성공: 원본-좌측정렬.hwp -> 원본-좌측정렬.hml
2024-12-23 14:29:56,143 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-23 14:39:24,817 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-23 14:39:25,098 - INFO - 변환 성공: 원본_기울기제거.hwp -> 원본_기울기제거.hml
2024-12-24 14:08:03,643 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-24 14:08:03,926 - INFO - 변환 성공: 원본_기울기제거.hwp -> 원본_기울기제거.hml
2024-12-24 14:08:04,050 - INFO - 변환 성공: 원본_행사안내_궁서체.hwp -> 원본_행사안내_궁서체.hml
2024-12-24 14:50:20,311 - INFO - 변환 성공: 원본-행사안내-양쪽정렬.hwp -> 원본-행사안내-양쪽정렬.hml
2024-12-24 14:50:20,563 - INFO - 변환 성공: 원본-행사안내-왼쪽정렬.hwp -> 원본-행사안내-왼쪽정렬.hml
2024-12-24 14:50:20,655 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-24 14:50:20,766 - INFO - 변환 성공: 원본_기울기제거.hwp -> 원본_기울기제거.hml
2024-12-24 14:50:20,878 - INFO - 변환 성공: 원본_행사안내_궁서체.hwp -> 원본_행사안내_궁서체.hml
2024-12-24 14:53:08,208 - INFO - 변환 성공: 원본-행사안내-양쪽정렬.hwp -> 원본-행사안내-양쪽정렬.hml
2024-12-24 14:53:08,436 - INFO - 변환 성공: 원본-행사안내-왼쪽정렬.hwp -> 원본-행사안내-왼쪽정렬.hml
2024-12-24 14:53:08,527 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-24 14:53:09,646 - INFO - 변환 성공: 원본_기울기제거.hwp -> 원본_기울기제거.hml
2024-12-24 14:53:09,764 - INFO - 변환 성공: 원본_행사안내_궁서체.hwp -> 원본_행사안내_궁서체.hml
2024-12-24 14:56:02,692 - INFO - 변환 성공: 원본-행사안내-양쪽정렬.hwp -> 원본-행사안내-양쪽정렬.hml
2024-12-24 14:56:02,990 - INFO - 변환 성공: 원본-행사안내-왼쪽정렬.hwp -> 원본-행사안내-왼쪽정렬.hml
2024-12-24 14:56:03,103 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-24 14:56:03,208 - INFO - 변환 성공: 원본_기울기제거.hwp -> 원본_기울기제거.hml
2024-12-24 14:56:03,401 - INFO - 변환 성공: 원본_행사안내_궁서체.hwp -> 원본_행사안내_궁서체.hml
2024-12-24 15:25:51,208 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-24 15:25:51,495 - INFO - 변환 성공: 원본_기타이하공백확인용.hwp -> 원본_기타이하공백확인용.hml
2024-12-24 17:51:36,557 - INFO - 변환 성공: 원본-쪽번호.hwp -> 원본-쪽번호.hml
2024-12-24 17:51:37,641 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-24 17:51:37,814 - INFO - 변환 성공: 원본_기타이하공백확인용.hwp -> 원본_기타이하공백확인용.hml
2024-12-24 17:51:51,605 - INFO - 변환 성공: 원본-쪽번호.hwp -> 원본-쪽번호.hml
2024-12-24 17:51:51,902 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-24 17:51:52,029 - INFO - 변환 성공: 원본_기타이하공백확인용.hwp -> 원본_기타이하공백확인용.hml
2024-12-27 12:54:51,238 - INFO - 변환 성공: 원본-쪽번호.hwp -> 원본-쪽번호.hml
2024-12-27 12:54:51,539 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 12:54:51,654 - INFO - 변환 성공: 원본_기타이하공백확인용.hwp -> 원본_기타이하공백확인용.hml
2024-12-27 12:54:51,760 - INFO - 변환 성공: 원본_쪽테두리없음.hwp -> 원본_쪽테두리없음.hml
2024-12-27 12:54:53,135 - ERROR - 프로그램 실행 오류: (-2147417851, '서버에서 예외 오류가 발생했습니다.', None, None)
2024-12-27 12:55:20,258 - INFO - 변환 성공: 원본-쪽번호.hwp -> 원본-쪽번호.hml
2024-12-27 12:55:20,553 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 12:55:20,669 - INFO - 변환 성공: 원본_기타이하공백확인용.hwp -> 원본_기타이하공백확인용.hml
2024-12-27 12:55:20,777 - INFO - 변환 성공: 원본_쪽테두리없음.hwp -> 원본_쪽테두리없음.hml
2024-12-27 12:55:31,365 - INFO - 변환 성공: 원본-쪽번호.hwp -> 원본-쪽번호.hml
2024-12-27 12:55:31,678 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 12:55:31,794 - INFO - 변환 성공: 원본_기타이하공백확인용.hwp -> 원본_기타이하공백확인용.hml
2024-12-27 12:55:31,896 - INFO - 변환 성공: 원본_쪽테두리없음.hwp -> 원본_쪽테두리없음.hml
2024-12-27 13:51:23,576 - INFO - 변환 성공: 원본-쪽번호.hwp -> 원본-쪽번호.hml
2024-12-27 13:51:23,975 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 13:51:24,120 - INFO - 변환 성공: 원본_기타이하공백확인용.hwp -> 원본_기타이하공백확인용.hml
2024-12-27 13:51:24,269 - INFO - 변환 성공: 원본_쪽테두리없음.hwp -> 원본_쪽테두리없음.hml
2024-12-27 13:51:25,602 - ERROR - 프로그램 실행 오류: (-2147417851, '서버에서 예외 오류가 발생했습니다.', None, None)
2024-12-27 13:51:38,264 - INFO - 변환 성공: 원본-쪽번호.hwp -> 원본-쪽번호.hml
2024-12-27 13:51:38,578 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 13:51:38,704 - INFO - 변환 성공: 원본_기타이하공백확인용.hwp -> 원본_기타이하공백확인용.hml
2024-12-27 13:51:38,868 - INFO - 변환 성공: 원본_쪽테두리없음.hwp -> 원본_쪽테두리없음.hml
2024-12-27 14:09:37,600 - INFO - 변환 성공: 원본-쪽번호.hwp -> 원본-쪽번호.hml
2024-12-27 14:09:37,939 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 14:09:38,163 - INFO - 변환 성공: 원본_기타이하공백확인용.hwp -> 원본_기타이하공백확인용.hml
2024-12-27 14:09:38,333 - INFO - 변환 성공: 원본_쪽테두리변경.hwp -> 원본_쪽테두리변경.hml
2024-12-27 14:09:38,489 - INFO - 변환 성공: 원본_쪽테두리없음.hwp -> 원본_쪽테두리없음.hml
2024-12-27 15:11:30,668 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 15:11:31,023 - INFO - 변환 성공: 원본_구역.hwp -> 원본_구역.hml
2024-12-27 15:17:10,183 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 15:17:10,529 - INFO - 변환 성공: 원본_구역.hwp -> 원본_구역.hml
2024-12-27 15:17:10,669 - INFO - 변환 성공: 원본_단.hwp -> 원본_단.hml
2024-12-27 15:18:22,647 - INFO - 변환 성공: 원본-단.hwp -> 원본-단.hml
2024-12-27 15:18:22,954 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 15:52:05,282 - INFO - 변환 성공: 왼쪽정렬.hwp -> 왼쪽정렬.hml
2024-12-27 15:52:05,520 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 15:52:58,856 - INFO - 변환 성공: 왼쪽정렬.hwp -> 왼쪽정렬.hml
2024-12-27 15:52:59,137 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 16:39:47,178 - INFO - 변환 성공: 왼쪽.hwp -> 왼쪽.hml
2024-12-27 16:39:47,446 - INFO - 변환 성공: 왼쪽정렬.hwp -> 왼쪽정렬.hml
2024-12-27 16:39:47,691 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 16:40:38,579 - INFO - 변환 성공: 왼쪽.hwp -> 왼쪽.hml
2024-12-27 16:40:38,883 - INFO - 변환 성공: 왼쪽정렬.hwp -> 왼쪽정렬.hml
2024-12-27 16:40:39,031 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 16:54:08,680 - INFO - 변환 성공: 왼쪽.hwp -> 왼쪽.hml
2024-12-27 16:54:08,989 - INFO - 변환 성공: 왼쪽정렬.hwp -> 왼쪽정렬.hml
2024-12-27 16:54:09,141 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 16:54:09,287 - INFO - 변환 성공: 차트제거.hwp -> 차트제거.hml
2024-12-27 16:59:49,986 - INFO - 변환 성공: 왼쪽.hwp -> 왼쪽.hml
2024-12-27 16:59:50,288 - INFO - 변환 성공: 왼쪽정렬.hwp -> 왼쪽정렬.hml
2024-12-27 16:59:50,425 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 16:59:50,584 - INFO - 변환 성공: 이미지사이즈수정.hwp -> 이미지사이즈수정.hml
2024-12-27 16:59:50,728 - INFO - 변환 성공: 차트제거.hwp -> 차트제거.hml
2024-12-27 17:18:12,196 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-27 17:18:12,490 - INFO - 변환 성공: 이미지사이즈수정.hwp -> 이미지사이즈수정.hml
2024-12-27 17:18:12,631 - INFO - 변환 성공: 이미지위치조정.hwp -> 이미지위치조정.hml
2024-12-30 15:46:24,053 - ERROR - 프로그램 실행 오류: module 'win32com.gen_py.7D2B6F3C-1D95-4E0C-BF5A-5EE564186FBCx0x1x0' has no attribute 'CLSIDToClassMap'
2024-12-30 15:46:38,452 - ERROR - 프로그램 실행 오류: module 'win32com.gen_py.7D2B6F3C-1D95-4E0C-BF5A-5EE564186FBCx0x1x0' has no attribute 'CLSIDToClassMap'
2024-12-30 15:47:04,147 - ERROR - 프로그램 실행 오류: module 'win32com.gen_py.7D2B6F3C-1D95-4E0C-BF5A-5EE564186FBCx0x1x0' has no attribute 'CLSIDToClassMap'
2024-12-30 15:47:10,951 - ERROR - 프로그램 실행 오류: module 'win32com.gen_py.7D2B6F3C-1D95-4E0C-BF5A-5EE564186FBCx0x1x0' has no attribute 'CLSIDToClassMap'
2024-12-30 15:48:03,142 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-30 15:48:04,731 - INFO - 변환 성공: 이미지사이즈수정.hwp -> 이미지사이즈수정.hml
2024-12-30 15:48:04,976 - INFO - 변환 성공: 이미지위치조정.hwp -> 이미지위치조정.hml
2024-12-30 15:48:05,118 - INFO - 변환 성공: 표배경색변경.hwp -> 표배경색변경.hml
2024-12-30 15:48:13,082 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-30 15:48:13,362 - INFO - 변환 성공: 이미지사이즈수정.hwp -> 이미지사이즈수정.hml
2024-12-30 15:48:13,493 - INFO - 변환 성공: 이미지위치조정.hwp -> 이미지위치조정.hml
2024-12-30 15:48:13,638 - INFO - 변환 성공: 표배경색변경.hwp -> 표배경색변경.hml
2024-12-31 16:41:22,813 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2024-12-31 16:41:24,083 - INFO - 변환 성공: 이미지사이즈수정.hwp -> 이미지사이즈수정.hml
2024-12-31 16:41:24,366 - INFO - 변환 성공: 이미지위치조정.hwp -> 이미지위치조정.hml
2024-12-31 16:41:24,496 - INFO - 변환 성공: 표배경색변경.hwp -> 표배경색변경.hml
2024-12-31 16:47:00,682 - INFO - 변환 성공: 우측정렬.hwp -> 우측정렬.hml
2024-12-31 16:47:00,972 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2025-01-02 16:22:47,085 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2025-01-03 14:08:26,257 - INFO - 변환 성공: 워드(한글)-009926-진성훈.hwp -> 워드(한글)-009926-진성훈.hml
2025-01-03 14:08:26,712 - INFO - 변환 성공: 워드(한글)-009927-한지수.hwp -> 워드(한글)-009927-한지수.hml
2025-01-03 14:08:26,832 - INFO - 변환 성공: 워드(한글)-009928-윤아르.hwp -> 워드(한글)-009928-윤아르.hml
2025-01-03 14:08:27,088 - INFO - 변환 성공: 워드(한글)-009929-김준영.hwp -> 워드(한글)-009929-김준영.hml
2025-01-03 14:08:27,386 - INFO - 변환 성공: 워드(한글)-009930-문윤재.hwp -> 워드(한글)-009930-문윤재.hml
2025-01-03 14:08:27,585 - INFO - 변환 성공: 워드(한글)-009931-이선우.hwp -> 워드(한글)-009931-이선우.hml
2025-01-03 14:08:27,711 - INFO - 변환 성공: 워드(한글)-009932-최다솜.hwp -> 워드(한글)-009932-최다솜.hml
2025-01-03 14:08:27,892 - INFO - 변환 성공: 워드(한글)-009933-이지한.hwp -> 워드(한글)-009933-이지한.hml
2025-01-03 14:08:28,027 - INFO - 변환 성공: 워드(한글)-009934-고서진.hwp -> 워드(한글)-009934-고서진.hml
2025-01-03 14:08:28,212 - INFO - 변환 성공: 워드(한글)-009935-이가은.hwp -> 워드(한글)-009935-이가은.hml
2025-01-03 14:08:28,349 - INFO - 변환 성공: 워드(한글)-009936-이라현.hwp -> 워드(한글)-009936-이라현.hml
2025-01-03 14:08:28,504 - INFO - 변환 성공: 워드(한글)-009937-진성준.hwp -> 워드(한글)-009937-진성준.hml
2025-01-03 14:08:28,638 - INFO - 변환 성공: 워드(한글)-009938-김규리.hwp -> 워드(한글)-009938-김규리.hml
2025-01-03 14:08:28,775 - INFO - 변환 성공: 워드(한글)-009939-이준.hwp -> 워드(한글)-009939-이준.hml
2025-01-03 14:08:28,922 - INFO - 변환 성공: 워드(한글)-009940-김지민.hwp -> 워드(한글)-009940-김지민.hml
2025-01-03 14:08:29,098 - INFO - 변환 성공: 워드(한글)-009941-윤지후.hwp -> 워드(한글)-009941-윤지후.hml
2025-01-03 14:08:29,252 - INFO - 변환 성공: 워드(한글)-009942-최원준.hwp -> 워드(한글)-009942-최원준.hml
2025-01-03 14:08:29,473 - INFO - 변환 성공: 워드(한글)-009943-윤헤르.hwp -> 워드(한글)-009943-윤헤르.hml
2025-01-03 14:08:29,615 - INFO - 변환 성공: 워드(한글)-009944-현지후.hwp -> 워드(한글)-009944-현지후.hml
2025-01-03 14:08:29,762 - INFO - 변환 성공: 워드(한글)-009945-고재웅.hwp -> 워드(한글)-009945-고재웅.hml
2025-01-03 14:08:29,900 - INFO - 변환 성공: 워드(한글)-009946-홍규진.hwp -> 워드(한글)-009946-홍규진.hml
2025-01-03 14:08:30,103 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2025-01-07 16:38:47,771 - ERROR - 프로그램 실행 오류: module 'win32com.gen_py.7D2B6F3C-1D95-4E0C-BF5A-5EE564186FBCx0x1x0' has no attribute 'CLSIDToClassMap'
2025-01-07 16:43:55,695 - ERROR - 프로그램 실행 오류: module 'win32com.gen_py.7D2B6F3C-1D95-4E0C-BF5A-5EE564186FBCx0x1x0' has no attribute 'CLSIDToClassMap'
2025-01-07 16:44:23,461 - INFO - 변환 성공: 워드(한글)-009926-진성훈.hwp -> 워드(한글)-009926-진성훈.hml
2025-01-07 16:44:23,856 - INFO - 변환 성공: 워드(한글)-009927-한지수.hwp -> 워드(한글)-009927-한지수.hml
2025-01-07 16:44:23,999 - INFO - 변환 성공: 워드(한글)-009928-윤아르.hwp -> 워드(한글)-009928-윤아르.hml
2025-01-07 16:44:24,138 - INFO - 변환 성공: 워드(한글)-009929-김준영.hwp -> 워드(한글)-009929-김준영.hml
2025-01-07 16:44:24,276 - INFO - 변환 성공: 워드(한글)-009930-문윤재.hwp -> 워드(한글)-009930-문윤재.hml
2025-01-07 16:44:24,564 - INFO - 변환 성공: 워드(한글)-009931-이선우.hwp -> 워드(한글)-009931-이선우.hml
2025-01-07 16:44:24,833 - INFO - 변환 성공: 워드(한글)-009932-최다솜.hwp -> 워드(한글)-009932-최다솜.hml
2025-01-07 16:44:25,906 - INFO - 변환 성공: 워드(한글)-009933-이지한.hwp -> 워드(한글)-009933-이지한.hml
2025-01-07 16:44:26,052 - INFO - 변환 성공: 워드(한글)-009934-고서진.hwp -> 워드(한글)-009934-고서진.hml
2025-01-07 16:44:26,236 - INFO - 변환 성공: 워드(한글)-009935-이가은.hwp -> 워드(한글)-009935-이가은.hml
2025-01-07 16:44:26,382 - INFO - 변환 성공: 워드(한글)-009936-이라현.hwp -> 워드(한글)-009936-이라현.hml
2025-01-07 16:44:26,540 - INFO - 변환 성공: 워드(한글)-009937-진성준.hwp -> 워드(한글)-009937-진성준.hml
2025-01-07 16:44:26,690 - INFO - 변환 성공: 워드(한글)-009938-김규리.hwp -> 워드(한글)-009938-김규리.hml
2025-01-07 16:44:26,862 - INFO - 변환 성공: 워드(한글)-009939-이준.hwp -> 워드(한글)-009939-이준.hml
2025-01-07 16:44:27,018 - INFO - 변환 성공: 워드(한글)-009940-김지민.hwp -> 워드(한글)-009940-김지민.hml
2025-01-07 16:44:27,269 - INFO - 변환 성공: 워드(한글)-009941-윤지후.hwp -> 워드(한글)-009941-윤지후.hml
2025-01-07 16:44:27,439 - INFO - 변환 성공: 워드(한글)-009942-최원준.hwp -> 워드(한글)-009942-최원준.hml
2025-01-07 16:44:27,651 - INFO - 변환 성공: 워드(한글)-009943-윤헤르.hwp -> 워드(한글)-009943-윤헤르.hml
2025-01-07 16:44:27,803 - INFO - 변환 성공: 워드(한글)-009944-현지후.hwp -> 워드(한글)-009944-현지후.hml
2025-01-07 16:44:27,958 - INFO - 변환 성공: 워드(한글)-009945-고재웅.hwp -> 워드(한글)-009945-고재웅.hml
2025-01-07 16:44:28,104 - INFO - 변환 성공: 워드(한글)-009946-홍규진.hwp -> 워드(한글)-009946-홍규진.hml
2025-01-07 16:44:28,297 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2025-01-07 16:45:42,803 - INFO - 변환 성공: 워드(한글)-009926-진성훈.hwp -> 워드(한글)-009926-진성훈.hml
2025-01-07 16:45:43,080 - INFO - 변환 성공: 워드(한글)-009927-한지수.hwp -> 워드(한글)-009927-한지수.hml
2025-01-07 16:45:43,235 - INFO - 변환 성공: 워드(한글)-009928-윤아르.hwp -> 워드(한글)-009928-윤아르.hml
2025-01-07 16:45:43,370 - INFO - 변환 성공: 워드(한글)-009929-김준영.hwp -> 워드(한글)-009929-김준영.hml
2025-01-07 16:45:43,563 - INFO - 변환 성공: 워드(한글)-009930-문윤재.hwp -> 워드(한글)-009930-문윤재.hml
2025-01-07 16:45:43,693 - INFO - 변환 성공: 워드(한글)-009931-이선우.hwp -> 워드(한글)-009931-이선우.hml
2025-01-07 16:45:43,853 - INFO - 변환 성공: 워드(한글)-009932-최다솜.hwp -> 워드(한글)-009932-최다솜.hml
2025-01-07 16:45:44,065 - INFO - 변환 성공: 워드(한글)-009933-이지한.hwp -> 워드(한글)-009933-이지한.hml
2025-01-07 16:45:44,214 - INFO - 변환 성공: 워드(한글)-009934-고서진.hwp -> 워드(한글)-009934-고서진.hml
2025-01-07 16:45:44,424 - INFO - 변환 성공: 워드(한글)-009935-이가은.hwp -> 워드(한글)-009935-이가은.hml
2025-01-07 16:45:44,570 - INFO - 변환 성공: 워드(한글)-009936-이라현.hwp -> 워드(한글)-009936-이라현.hml
2025-01-07 16:45:44,731 - INFO - 변환 성공: 워드(한글)-009937-진성준.hwp -> 워드(한글)-009937-진성준.hml
2025-01-07 16:45:44,878 - INFO - 변환 성공: 워드(한글)-009938-김규리.hwp -> 워드(한글)-009938-김규리.hml
2025-01-07 16:45:45,026 - INFO - 변환 성공: 워드(한글)-009939-이준.hwp -> 워드(한글)-009939-이준.hml
2025-01-07 16:45:45,176 - INFO - 변환 성공: 워드(한글)-009940-김지민.hwp -> 워드(한글)-009940-김지민.hml
2025-01-07 16:45:45,355 - INFO - 변환 성공: 워드(한글)-009941-윤지후.hwp -> 워드(한글)-009941-윤지후.hml
2025-01-07 16:45:45,526 - INFO - 변환 성공: 워드(한글)-009942-최원준.hwp -> 워드(한글)-009942-최원준.hml
2025-01-07 16:45:45,757 - INFO - 변환 성공: 워드(한글)-009943-윤헤르.hwp -> 워드(한글)-009943-윤헤르.hml
2025-01-07 16:45:45,901 - INFO - 변환 성공: 워드(한글)-009944-현지후.hwp -> 워드(한글)-009944-현지후.hml
2025-01-07 16:45:46,067 - INFO - 변환 성공: 워드(한글)-009945-고재웅.hwp -> 워드(한글)-009945-고재웅.hml
2025-01-07 16:45:46,212 - INFO - 변환 성공: 워드(한글)-009946-홍규진.hwp -> 워드(한글)-009946-홍규진.hml
2025-01-07 16:45:46,401 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2025-01-07 16:46:08,144 - INFO - 변환 성공: 워드(한글)-009926-진성훈.hwp -> 워드(한글)-009926-진성훈.hml
2025-01-07 16:46:08,413 - INFO - 변환 성공: 워드(한글)-009927-한지수.hwp -> 워드(한글)-009927-한지수.hml
2025-01-07 16:46:08,566 - INFO - 변환 성공: 워드(한글)-009928-윤아르.hwp -> 워드(한글)-009928-윤아르.hml
2025-01-07 16:46:08,692 - INFO - 변환 성공: 워드(한글)-009929-김준영.hwp -> 워드(한글)-009929-김준영.hml
2025-01-07 16:46:08,828 - INFO - 변환 성공: 워드(한글)-009930-문윤재.hwp -> 워드(한글)-009930-문윤재.hml
2025-01-07 16:46:09,054 - INFO - 변환 성공: 워드(한글)-009931-이선우.hwp -> 워드(한글)-009931-이선우.hml
2025-01-07 16:46:09,187 - INFO - 변환 성공: 워드(한글)-009932-최다솜.hwp -> 워드(한글)-009932-최다솜.hml
2025-01-07 16:46:09,374 - INFO - 변환 성공: 워드(한글)-009933-이지한.hwp -> 워드(한글)-009933-이지한.hml
2025-01-07 16:46:09,513 - INFO - 변환 성공: 워드(한글)-009934-고서진.hwp -> 워드(한글)-009934-고서진.hml
2025-01-07 16:46:09,694 - INFO - 변환 성공: 워드(한글)-009935-이가은.hwp -> 워드(한글)-009935-이가은.hml
2025-01-07 16:46:09,839 - INFO - 변환 성공: 워드(한글)-009936-이라현.hwp -> 워드(한글)-009936-이라현.hml
2025-01-07 16:46:09,984 - INFO - 변환 성공: 워드(한글)-009937-진성준.hwp -> 워드(한글)-009937-진성준.hml
2025-01-07 16:46:10,135 - INFO - 변환 성공: 워드(한글)-009938-김규리.hwp -> 워드(한글)-009938-김규리.hml
2025-01-07 16:46:10,281 - INFO - 변환 성공: 워드(한글)-009939-이준.hwp -> 워드(한글)-009939-이준.hml
2025-01-07 16:46:10,424 - INFO - 변환 성공: 워드(한글)-009940-김지민.hwp -> 워드(한글)-009940-김지민.hml
2025-01-07 16:46:10,607 - INFO - 변환 성공: 워드(한글)-009941-윤지후.hwp -> 워드(한글)-009941-윤지후.hml
2025-01-07 16:46:10,746 - INFO - 변환 성공: 워드(한글)-009942-최원준.hwp -> 워드(한글)-009942-최원준.hml
2025-01-07 16:46:10,924 - INFO - 변환 성공: 워드(한글)-009943-윤헤르.hwp -> 워드(한글)-009943-윤헤르.hml
2025-01-07 16:46:11,070 - INFO - 변환 성공: 워드(한글)-009944-현지후.hwp -> 워드(한글)-009944-현지후.hml
2025-01-07 16:46:11,194 - INFO - 변환 성공: 워드(한글)-009945-고재웅.hwp -> 워드(한글)-009945-고재웅.hml
2025-01-07 16:46:11,330 - INFO - 변환 성공: 워드(한글)-009946-홍규진.hwp -> 워드(한글)-009946-홍규진.hml
2025-01-07 16:46:11,466 - INFO - 변환 성공: 원본.hwp -> 원본.hml
2025-01-07 18:06:33,653 - INFO - 변환 성공: 워드(한글)-009926-진성훈.hwp -> 워드(한글)-009926-진성훈.hml
2025-01-07 18:06:34,053 - INFO - 변환 성공: 워드(한글)-009927-한지수.hwp -> 워드(한글)-009927-한지수.hml
2025-01-07 18:06:34,227 - INFO - 변환 성공: 워드(한글)-009928-윤아르.hwp -> 워드(한글)-009928-윤아르.hml
2025-01-07 18:06:34,382 - INFO - 변환 성공: 워드(한글)-009929-김준영.hwp -> 워드(한글)-009929-김준영.hml
2025-01-07 18:06:34,545 - INFO - 변환 성공: 워드(한글)-009930-문윤재.hwp -> 워드(한글)-009930-문윤재.hml
2025-01-07 18:06:34,698 - INFO - 변환 성공: 워드(한글)-009931-이선우.hwp -> 워드(한글)-009931-이선우.hml
2025-01-07 18:06:35,008 - INFO - 변환 성공: 워드(한글)-009932-최다솜.hwp -> 워드(한글)-009932-최다솜.hml
2025-01-07 18:06:35,168 - INFO - 변환 성공: 워드(한글)-009933-이지한.hwp -> 워드(한글)-009933-이지한.hml
2025-01-07 18:06:35,328 - INFO - 변환 성공: 워드(한글)-009934-고서진.hwp -> 워드(한글)-009934-고서진.hml
2025-01-07 18:06:35,486 - INFO - 변환 성공: 워드(한글)-009935-이가은.hwp -> 워드(한글)-009935-이가은.hml
2025-01-07 18:06:35,714 - INFO - 변환 성공: 워드(한글)-009936-이라현.hwp -> 워드(한글)-009936-이라현.hml
2025-01-07 18:06:35,916 - INFO - 변환 성공: 워드(한글)-009937-진성준.hwp -> 워드(한글)-009937-진성준.hml
2025-01-07 18:06:36,071 - INFO - 변환 성공: 워드(한글)-009938-김규리.hwp -> 워드(한글)-009938-김규리.hml
2025-01-07 18:06:36,247 - INFO - 변환 성공: 워드(한글)-009939-이준.hwp -> 워드(한글)-009939-이준.hml
2025-01-07 18:06:36,418 - INFO - 변환 성공: 워드(한글)-009940-김지민.hwp -> 워드(한글)-009940-김지민.hml
2025-01-07 18:06:36,656 - INFO - 변환 성공: 워드(한글)-009941-윤지후.hwp -> 워드(한글)-009941-윤지후.hml
2025-01-07 18:06:36,848 - INFO - 변환 성공: 워드(한글)-009942-최원준.hwp -> 워드(한글)-009942-최원준.hml
2025-01-07 18:06:37,086 - INFO - 변환 성공: 워드(한글)-009943-윤헤르.hwp -> 워드(한글)-009943-윤헤르.hml
2025-01-07 18:06:37,243 - INFO - 변환 성공: 워드(한글)-009944-현지후.hwp -> 워드(한글)-009944-현지후.hml
2025-01-07 18:06:37,419 - INFO - 변환 성공: 워드(한글)-009945-고재웅.hwp -> 워드(한글)-009945-고재웅.hml
2025-01-07 18:06:37,575 - INFO - 변환 성공: 워드(한글)-009946-홍규진.hwp -> 워드(한글)-009946-홍규진.hml
2025-01-07 18:06:37,789 - INFO - 변환 성공: 워드(한글)-010120-고하진.hwp -> 워드(한글)-010120-고하진.hml
2025-01-07 18:06:37,935 - INFO - 변환 성공: 워드(한글)-010121-고한율.hwp -> 워드(한글)-010121-고한율.hml
2025-01-07 18:06:38,084 - INFO - 변환 성공: 워드(한글)-010122-손서아.hwp -> 워드(한글)-010122-손서아.hml
2025-01-07 18:06:38,240 - INFO - 변환 성공: 워드(한글)-010123-김지온.hwp -> 워드(한글)-010123-김지온.hml
2025-01-07 18:06:38,402 - INFO - 변환 성공: 워드(한글)-010124-안서정.hwp -> 워드(한글)-010124-안서정.hml
2025-01-07 18:06:38,561 - INFO - 변환 성공: 워드(한글)-010125-강지환.hwp -> 워드(한글)-010125-강지환.hml
2025-01-07 18:06:38,768 - INFO - 변환 성공: 워드(한글)-010126-고여진.hwp -> 워드(한글)-010126-고여진.hml
2025-01-07 18:06:38,909 - INFO - 변환 성공: 워드(한글)-010127-고재범.hwp -> 워드(한글)-010127-고재범.hml
2025-01-07 18:06:39,067 - INFO - 변환 성공: 워드(한글)-010128-윤빈.hwp -> 워드(한글)-010128-윤빈.hml
2025-01-07 18:06:39,264 - INFO - 변환 성공: 워드(한글)-010129-유승재.hwp -> 워드(한글)-010129-유승재.hml
2025-01-07 18:06:39,420 - INFO - 변환 성공: 워드(한글)-010130-고강은.hwp -> 워드(한글)-010130-고강은.hml
2025-01-07 18:06:39,586 - INFO - 변환 성공: 원본.hwp -> 원본.hml

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
input/원본 copy.hwp Normal file

Binary file not shown.

BIN
input/원본.hwp Normal file

Binary file not shown.

1
page1.xbook Normal file

File diff suppressed because one or more lines are too long

1
page2-2.xbook Normal file
View File

@@ -0,0 +1 @@
[{"kind":2,"language":"xpath","value":"//CHAR[contains(text(),'과일야채 항산화지수 비교')]/parent::TEXT/@CharShape"},{"kind":2,"language":"xpath","value":"//CHARSHAPE[@Id='12']/FONTID/@Hangul"},{"kind":2,"language":"xpath","value":"//FONTFACE[@Lang='Hangul']/FONT[@Id='1']/@Name='굴림체'"},{"kind":2,"language":"xpath","value":"//CHARSHAPE[@Id='12']/@Height='1100'"},{"kind":2,"language":"xpath","value":"boolean(//CHARSHAPE[@Id='12']/BOLD)"},{"kind":2,"language":"xpath","value":"//CHAR[contains(text(),'과일야채 항산화지수 비교')]/ancestor::P/@ParaShape"},{"kind":2,"language":"xpath","value":"//PARASHAPE[@Id='15']/@Align='Center'"},{"kind":2,"language":"xpath","value":"//CELL//CHAR[text()='종류']/ancestor::CELL/@BorderFill"},{"kind":2,"language":"xpath","value":"//BORDERFILL[@Id='6']/FILLBRUSH/WINDOWBRUSH/@FaceColor=6268159"},{"kind":2,"language":"xpath","value":"//TABLE/ROW[1]/CELL/@BorderFill='6'"},{"kind":2,"language":"xpath","value":"boolean(//TABLE/ROW[1]/CELL[@BorderFill = following-sibling::CELL/@BorderFill])"},{"kind":2,"language":"xpath","value":"//TABLE/ROW[1]/CELL/@BorderFill"},{"kind":2,"language":"xpath","value":"//CELL//CHAR[text()='종류']/parent::TEXT/@CharShape"},{"kind":2,"language":"xpath","value":"//CELL//CHAR[text()='항산화지수(100g당)']/parent::TEXT/@CharShape"},{"kind":2,"language":"xpath","value":"boolean(//CHARSHAPE[@Id='13']/BOLD)"},{"kind":2,"language":"xpath","value":"//TABLE/ROW[1]/CELL/@BorderFill"},{"kind":2,"language":"xpath","value":"boolean(//BORDERFILL[@Id='6']/BOTTOMBORDER[@Type='DoubleSlim' and @Width='0.5mm'])"},{"kind":2,"language":"xpath","value":"//CELL[descendant::TEXT/@CharShape = following-sibling::CELL/descendant::TEXT/@CharShape]"},{"kind":2,"language":"xpath","value":"//CHARSHAPE[@Id='2']/FONTID/@Hangul"},{"kind":2,"language":"xpath","value":"//FONTFACE[@Lang='Hangul']/FONT[@Id='5']/@Name"},{"kind":2,"language":"xpath","value":"//TABLE/descendant::TEXT[not(@CharShape = preceding::TEXT/@CharShape)]/@CharShape"},{"kind":2,"language":"xpath","value":"//CHARSHAPE[@Id='13' or @Id='1']/FONTID[not(@Hangul = preceding::FONTID/@Hangul)]/@Hangul"},{"kind":2,"language":"xpath","value":"//CHARSHAPE[@Id='13']/FONTID/@Hangul"},{"kind":2,"language":"xpath","value":"//FONTFACE[@Lang='Hangul']/FONT[@Id='2']/@Name"},{"kind":2,"language":"xpath","value":"//CHARSHAPE[@Id='13' or @Id='1']/@Height='100'"},{"kind":2,"language":"xpath","value":"//TABLE/descendant::TEXT[not(@CharShape = preceding::TEXT/@CharShape)]"},{"kind":2,"language":"xpath","value":"//TABLE/descendant::P[not(@ParaShape = preceding::P/@ParaShape)]"},{"kind":2,"language":"xpath","value":"//TABLE/descendant::P[not(@ParaShape = preceding::P/@ParaShape)]/@ParaShape"},{"kind":2,"language":"xpath","value":"//TABLE/descendant::P[not(@ParaShape=preceding::P/@ParaShape)]/@ParaShape"},{"kind":2,"language":"xpath","value":"//TABLE/descendant::CELL[not(@BorderFill = preceding::CELL/@BorderFill)]/@BorderFill"},{"kind":1,"language":"markdown","value":""}]

1
page2.xbook Normal file

File diff suppressed because one or more lines are too long

2
pip.py Normal file
View File

@@ -0,0 +1,2 @@
import sys
print(sys.executable)

View File

@@ -6,11 +6,16 @@ import pandas as pd
from datetime import datetime from datetime import datetime
from difflib import SequenceMatcher from difflib import SequenceMatcher
import re import re
import demicalToRGB
class XMLScorer: class XMLScorer:
# 채점 기준 경로 초기화
def __init__(self, scoring_criteria_path): def __init__(self, scoring_criteria_path):
# 채점 기준 로드
self.scoring_criteria = self._load_scoring_criteria(scoring_criteria_path) self.scoring_criteria = self._load_scoring_criteria(scoring_criteria_path)
print(self.scoring_criteria)
# 채점 기준파일 로드(JSON 파일)
def _load_scoring_criteria(self, file_path): def _load_scoring_criteria(self, file_path):
with open(file_path, 'r', encoding='utf-8') as f: with open(file_path, 'r', encoding='utf-8') as f:
return json.load(f) return json.load(f)
@@ -113,15 +118,17 @@ class XMLScorer:
return None, False return None, False
# XML 파일 채점
def score_xml_file(self, xml_path): def score_xml_file(self, xml_path):
try: try:
tree = ET.parse(xml_path) tree = ET.parse(xml_path)
root = tree.getroot() root = tree.getroot()
total_score = 0 total_score = 0
# 결과값을 Dictionary로 저장
results = { results = {
'filename': os.path.basename(xml_path), 'filename': os.path.basename(xml_path),
'criteria_matches': [], 'criteria_matches': [], # 채점 항목별 결과
'total_score': 0, 'total_score': 0,
'deductions': [] # 감점 상세 내역 추가 'deductions': [] # 감점 상세 내역 추가
} }
@@ -135,11 +142,12 @@ class XMLScorer:
actual_value, has_element_typo = self._find_element_value( actual_value, has_element_typo = self._find_element_value(
root, element_name, attribute_name) root, element_name, attribute_name)
# 채점 결과 저장
match = { match = {
'criterion': f"{element_name}.{attribute_name}", 'criterion': f"{element_name}.{attribute_name}", # 채점 항목
'expected': expected_value, 'expected': expected_value, # 기대값
'actual': actual_value, 'actual': actual_value, # 실제값
'points': 0, 'points': 0, # 획득 점수
'deductions': [] # 각 기준별 감점 내역 'deductions': [] # 각 기준별 감점 내역
} }
@@ -247,7 +255,8 @@ class XMLScorer:
def score_directory(self, xml_directory): def score_directory(self, xml_directory):
results = [] results = []
xml_files = Path(xml_directory).glob('*.xml') # xml_files = Path(xml_directory).glob('*.xml')
xml_files = Path(xml_directory).glob('*.hml')
for xml_file in xml_files: for xml_file in xml_files:
result = self.score_xml_file(str(xml_file)) result = self.score_xml_file(str(xml_file))
@@ -255,14 +264,13 @@ class XMLScorer:
return results return results
# 사용 예시 # 사용 예시
def main(): def main():
# 채점기준표 파일 경로 # 채점기준표 파일 경로
scoring_criteria_path = "scoring_criteria.json" scoring_criteria_path = "scoring_criteria.json"
# XML 파일들이 있는 디렉토리 경로 # XML 파일들이 있는 디렉토리 경로
xml_directory = r"C:\Users\gzero-ser7-win11\Documents\hwpTest\Output" # xml_directory = r"C:\Users\gzero-ser7-win11\Documents\hwpTest\Output"
xml_directory = r"C:\Users\dra\project\HWP-Scoring\output"
# 채점기 초기화 # 채점기 초기화
scorer = XMLScorer(scoring_criteria_path) scorer = XMLScorer(scoring_criteria_path)

50
score4.py Normal file
View File

@@ -0,0 +1,50 @@
from lxml import etree
from difflib import SequenceMatcher
def get_all_text_xml_file(root):
# all_text = root.xpath("//CHAR/text() | //TEXTART/@Text")
all_text = root.xpath("//CHAR/text()")
print(f'all_text length: {len(all_text)}')
return all_text
def find_typos_and_spaces(original, target):
typos = []
spaces = []
space_differences = 0
for text in original:
# 오타 검사
words = text.split()
for word in words:
if not any(SequenceMatcher(None, word, target_word).ratio() >= 0.9 for target_word in target):
typos.append(word)
# 공백 차이 검사
for orig_text, targ_text in zip(original, target):
min_length = min(len(orig_text), len(targ_text))
orig_text = orig_text[:min_length]
targ_text = targ_text[:min_length]
orig_spaces = orig_text.count(' ')
targ_spaces = targ_text.count(' ')
space_differences += abs(orig_spaces - targ_spaces)
print(f'space_differences : {space_differences}')
return typos, spaces
# XML 파일 파싱
original_file = r"C:\Users\dra\project\HWP-Scoring\output\워드(한글)-010128-윤빈.hml"
target_file = r"C:\Users\dra\project\HWP-Scoring\output\워드(한글)-009939-이준.hml"
# target_file = r"C:\Users\dra\project\HWP-Scoring\output\원본 copy.hml"
tree = etree.parse(original_file)
root = tree.getroot()
original_text = get_all_text_xml_file(root)
tree = etree.parse(target_file)
root = tree.getroot()
target_text = get_all_text_xml_file(root)
typos, spaces = find_typos_and_spaces(original_text, target_text)
# print(f'Typos: {typos}')
# print(f'Spaces: {spaces}')

265
score5.py Normal file
View File

@@ -0,0 +1,265 @@
from datetime import datetime
import json
import glob
from pathlib import Path
import os
from lxml import etree as ET
from difflib import SequenceMatcher
import pandas as pd
# from xpathSearch import XMLPathHandler
class XMLScorer:
# 채점 기준 경로 초기화
def __init__(self, scoring_criteria_path):
# 채점 기준 로드
self.scoring_criteria = self._load_scoring_criteria(scoring_criteria_path)
# 채점 기준파일 로드(JSON 파일)
def _load_scoring_criteria(self, file_path):
with open(file_path, 'r', encoding='utf-8') as f:
return json.load(f)
# XML 파일에서 element의 값을 찾아 반환
def query_xml(self, root, query):
try:
result = root.xpath(query)
if type(result) is list and len(result) == 0:
return None
return result
except ET.XPathEvalError as e:
return None
# 유사한 텍스트 찾기
def find_similar_text(self, root, target_text, threshold=0.3):
"""
전체 문서에서 유사한 텍스트를 찾아 반환
Args:
root (_type_): xml root element 객체
target_text (_type_): 찾을 텍스트
threshold (float, optional): 유사도 설정 Defaults to 0.3.
Returns:
str: 유사도 기준을 만족하는 텍스트
"""
# 전체 텍스트 추출
# all_text = root.xpath(f"//CHAR/text()")
# all_text.append(root.xpath(f"//TEXTART/@text"))
all_text = root.xpath(f"//CHAR/text() | //TEXTART/@Text")
# 유사도 비교
max_score = 0
similar_text = ''
for text in all_text:
score = SequenceMatcher(None, target_text, text).ratio()
if score > max_score:
max_score = score
similar_text = text
if max_score >= threshold:
return similar_text
else:
return None
# 하나의 XML 파일 채점
def _score_xml_file(self, xml_path):
try:
tree = ET.parse(xml_path)
root = tree.getroot()
total_score = 0
# 결과값을 Dictionary로 저장
results = {
'filename': os.path.basename(xml_path),
'score_results': [],
'total_score': 0,
}
print(f"File name: {results['filename']}")
for criterion_id, criterion in self.scoring_criteria.items():
xpath = criterion['path']
search_value = criterion['searchValue']
right_answer = criterion['value']
points = criterion['points']
category = criterion['category']
item = criterion['item']
simliar_text = None
# searchValue가 있을 경우 유사한 텍스트 찾기
if search_value is not None:
simliar_text = self.find_similar_text(root, search_value)
if simliar_text is None:
continue
else:
xpath = xpath.replace('{searchValue}', simliar_text)
# xpath로 실제 작성 답안 찾기
result = self.query_xml(root, xpath)
# [ boolean 타입 ]
# 1. 이텔릭체, 굵게, 밑줄 등 효과가 적용 여부에 따라
# [ITALIC] [BOLD] [UNDERLINE] 태그가 있거나 없을 수 있으므로
# 존재 유무에 따라 True, False로 판단
# 2. 두 가지 이상의 조건을 모두 만족해야 하는 경우 and 연산자로 연결되어
# 반환값 True/False로 판단
# [ float 타입 ]
# 1. 부분점수의 합산으로 반환되는 경우 float 타입으로 반환
if type(result) is not list:
actual_answer = result
else:
actual_answer = result[0]
scoring = {
'category': category, # 채점 분류
'item': item, # 채점 항목
'right_answer': right_answer, # 정답
'actual_answer': actual_answer, # 실제 작성 답안
'points': 0,
'deductions': [] # 각 기준별 감점 내역
}
scoring['points'] = points
# 점수 차감 조건
# 1. 정답이 실수형으로 반환받은 경우는 채점항목의 부분점수 합산 결과이므로
# 반환받은 값 그대로를 점수로 사용
# 2. 그 외의 경우 정답과 실제 작성 답안이 다른 경우 점수 차감
if type(actual_answer) is float:
scoring['points'] = actual_answer
else:
if right_answer != actual_answer:
scoring['points'] -= points
results['score_results'].append(scoring)
total_score += scoring['points']
print(f'scoring: {scoring}')
results['total_score'] = total_score
return results
except ET.ParseError as e:
return {
'filename': os.path.basename(xml_path),
'error': f"XML 파싱 오류: {str(e)}",
'total_score': 0
}
# XML 파일 채점
def score_directory(self, xml_directory):
# xml 파일 불러오기
xml_files = Path(xml_directory).glob('*.hml')
# 결과 저장할 리스트
results = []
for xml_file in xml_files:
result = self._score_xml_file(xml_file)
results.append(result)
return results
def export_to_excel(self, results, output_path=None):
if output_path is None:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_path = f"scoring_results_{timestamp}.xlsx"
summary_data = []
detail_data = []
for result in results:
# 요약 정보
summary_row = {
'파일명': result['filename'],
'총점': result.get('total_score', 0)
}
if 'error' in result:
summary_row['오류'] = result['error']
summary_data.append(summary_row)
# 상세 정보
if 'score_results' in result:
detail_data.append({'파일명': result['filename']})
for scoring in result['score_results']:
# detail_row = {
# '파일명': result['filename'],
# # '채점분류': scoring['category'],
# # '채점항목': scoring['item'],
# # '채점기준': scoring['right_answer'],
# # '적용답안': scoring['actual_answer'],
# '획득점수': scoring['points'],
# # '감점내역': '; '.join(scoring.get('deductions', []))
# }
# detail_data.append(detail_row)
summary_df = pd.DataFrame(summary_data)
detail_df = pd.DataFrame(detail_data)
# ExcelWriter 객체 생성
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
summary_df.to_excel(writer, sheet_name='채점결과요약', index=False)
detail_df.to_excel(writer, sheet_name='채점상세내역', index=False)
# 열 너비 자동 조정
for sheet_name in writer.sheets:
worksheet = writer.sheets[sheet_name]
for column_cells in worksheet.columns:
max_length = 0
column = column_cells[0].column_letter # 열의 문자
for cell in column_cells:
try:
if cell.value:
max_length = max(max_length, len(str(cell.value)))
except:
pass
adjusted_width = (max_length + 2)
worksheet.column_dimensions[column].width = adjusted_width
return output_path
def main():
scoring_criteria_path = r'C:\Users\dra\project\HWP-Scoring\scoring_criteria.json'
# xml(hml)파일 디렉토리 경로
xml_directory = r'C:\Users\dra\project\HWP-Scoring\output'
# 채점 클래스 초기화
scorer = XMLScorer(scoring_criteria_path)
# 폴더 내 모든 xml 파일 채점
results = scorer.score_directory(xml_directory)
# for result in results:
# print(f"\n파일: {result['filename']}")
# if 'error' in result:
# print(f"오류: {result['error']}")
# continue
# print(f"총점: {result['total_score']}")
# print("\n채점 세부사항:")
# for scoring in result['score_results']:
# print(f"채점분류: {scoring['category']}")
# print(f"채점항목: {scoring['item']}")
# print(f"요구 답안: {scoring['right_answer']}")
# print(f"작성 답안: {scoring['actual_answer']}")
# print(f"획득 점수: {scoring['points']}")
# print(f"감점 내역: {scoring['deductions']}")
# print("---")
# 채점 결과 엑셀로 저장
output_excel_path = scorer.export_to_excel(results)
print(f"채점 결과 엑셀 파일: {output_excel_path}")
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,26 @@
{
"0": {
"ele": "TEXTART",
"arg": "Text",
"value": "즐거운컬러푸드영양교실",
"points": 10
},
"1": {
"ele": "TEXTARTSHAPE",
"arg": "FontName",
"value": "궁서체",
"points": 2
},
"2": {
"ele": "TEXTARTSHAPE",
"arg": "Align",
"value": "Center",
"points": 2
},
"3": {
"ele": "WINDOWBRUSH",
"arg": "FaceColor",
"value": "10040115",
"points": 2
}
}

View File

@@ -1,20 +1,203 @@
{ {
"0": {
"ele": "TEXTART",
"arg": "Text",
"value": "즐거운컬러푸드영양교실",
"points": 10
},
"1":{ "1":{
"ele": "TEXTARTSHAPE", "path": "//TEXTART[@Text='{searchValue}']/TEXTARTSHAPE/@FontName",
"arg": "FontName", "searchValue": "즐거운컬러푸드영양교실",
"value": "궁서체", "value": "궁서체",
"points": 2 "points": 2,
"category": "글맵시",
"item":"글씨체 (궁서체)"
}, },
"2": { "2": {
"ele": "TEXTARTSHAPE", "path": "//TEXTART[@Text='{searchValue}']/descendant::WINDOWBRUSH/@FaceColor",
"arg": "Align", "searchValue": "즐거운컬러푸드영양교실",
"value": "10040115",
"points": 2,
"category": "글맵시",
"item":"채우기 : 색상(RGB:51,51,153)"
},
"3": {
"path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/SIZE/@Width",
"searchValue": "즐거운컬러푸드영양교실",
"value": "36850",
"points": 2,
"category": "글맵시",
"item":"크기-너비 (130mm)"
},
"4": {
"path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/SIZE/@Height",
"searchValue": "즐거운컬러푸드영양교실",
"value": "5669",
"points": 2,
"category": "글맵시",
"item":"크기-높이 (20mm)"
},
"5": {
"path": "//TEXTART[@Text='{searchValue}']/SHAPEOBJECT/POSITION/@TreatAsChar",
"searchValue": "즐거운컬러푸드영양교실",
"value": "true",
"points": 2,
"category": "글맵시",
"item":"위치 (글자처럼 취급)"
},
"6": {
"path": "//PARASHAPE[@Id=//TEXTART[@Text='{searchValue}']/ancestor::P/@ParaShape]/@Align",
"searchValue": "즐거운컬러푸드영양교실",
"value": "Center", "value": "Center",
"points": 2 "points": 2,
"category": "글맵시",
"item":"정렬 (가운데 정렬)"
},
"7":{
"path": "",
"searchValue": "즐거운컬러푸드영양교실",
"value": null,
"points": 2,
"category": "글맵시",
"item":"글맵시모양 (육안확인)"
},
"8": {
"path": "boolean(//CHARSHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/@CharShape][BOLD])",
"searchValue": "‘즐거운 컬러푸드 영양교실’",
"value": true,
"points": 2,
"category": "글꼴속성",
"item":"진하게"
},
"9": {
"path": "boolean(//CHARSHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/@CharShape][ITALIC])",
"searchValue": "‘즐거운 컬러푸드 영양교실’",
"value": true,
"points": 2,
"category": "글꼴속성",
"item":"기울임"
},
"10": {
"path": "string-length(//CHAR[contains(text(),'♤')]) - string-length(translate(//CHAR[contains(text(),'♤')], '♤', '')) + string-length(//CHAR[contains(text(),'※')]) - string-length(translate(//CHAR[contains(text(),'※')], '※', ''))",
"searchValue": null,
"value": 3.0,
"points": 3,
"category": "특수문자",
"item":"♤, ♤, ※"
},
"11": {
"path": "//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]/FONTID/@Hangul]/@Name",
"searchValue": "행사안내",
"value": "굴림체",
"points": 1,
"category": "글꼴 속성",
"item":"글씨체 (굴림체)"
},
"12": {
"path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/@ParaShape]/@Align",
"searchValue": "행사안내",
"value": "Center",
"points": 1,
"category": "글꼴 속성",
"item":"정렬 (가운데 정렬)"
},
"13": {
"path": "boolean(//CHARSHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/@CharShape][ITALIC])",
"searchValue": "홈페이지(http://www.ihd.or.kr)를 통해 선착순 접수",
"value": true,
"points": 1,
"category": "글꼴 속성",
"item":"기울임"
},
"14": {
"path": "boolean(//CHARSHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/@CharShape][UNDERLINE])",
"searchValue": "홈페이지(http://www.ihd.or.kr)를 통해 선착순 접수",
"value": true,
"points": 1,
"category": "글꼴 속성",
"item":"밑줄"
},
"15": {
"path": "boolean(//PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/following-sibling::P[1]/@ParaShape]/PARAMARGIN/@Left=3600 and //PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/following-sibling::P[1]/@ParaShape]/PARAMARGIN/@Indent=-2000)",
"searchValue": "※ 기타",
"value": true,
"points": 2,
"category": "문단모양",
"item":"왼쪽여백 (18pt), 내어쓰기 (10pt)"
},
"16": {
"path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]/@Height",
"searchValue": "2024. 1. 27.",
"value": "1100",
"points": 2,
"category": "글꼴 속성",
"item":"크기 (11pt)"
},
"17": {
"path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/@ParaShape]/@Align",
"searchValue": "2024. 1. 27.",
"value": "Center",
"points": 1,
"category": "글꼴 속성",
"item":"정렬 (가운데 정렬)"
},
"18": {
"path": "//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]/FONTID/@Hangul]/@Name",
"searchValue": "용일동보건소",
"value": "한양중고딕",
"points": 2,
"category": "글꼴 속성",
"item":"글씨체 (중고딕)"
},
"19": {
"path": "//CHARSHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/parent::TEXT/@CharShape]/@Height",
"searchValue": "용일동보건소",
"value": "2200",
"points": 2,
"category": "글꼴 속성",
"item":"크기 (22pt)"
},
"20": {
"path": "//PARASHAPE[@Id=//CHAR[contains(text(),'{searchValue}')]/ancestor::P/@ParaShape]/@Align",
"searchValue": "용일동보건소",
"value": "Center",
"points": 2,
"category": "글꼴 속성",
"item":"정렬 (가운데 정렬)"
},
"21": {
"path": "//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/@CharShape]/FONTID/@Hangul]/@Name",
"searchValue": "DIAT",
"value": "돋움체",
"points": 2,
"category": "머리말",
"item":"글꼴 (돋움체)"
},
"22": {
"path": "//CHARSHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/@CharShape]/@Height",
"searchValue": "DIAT",
"value": "900",
"points": 2,
"category": "머리말",
"item":"크기 (9pt)"
},
"23": {
"path": "//PARASHAPE[@Id=//CHAR[text()='{searchValue}']/parent::TEXT/parent::P/@ParaShape]/@Align",
"searchValue": "DIAT",
"value": "Right",
"points": 2,
"category": "머리말",
"item":"정렬 (오른쪽 정렬)"
},
"24": {
"path": "//PAGENUM/@FormatType",
"searchValue": null,
"value": "LatinCapital",
"points": 2,
"category": "쪽번호",
"item":"쪽 번호 매기기 (A,B,C 순으로)"
},
"25": {
"path": "//PAGENUM/@Pos",
"searchValue": null,
"value": "BottomCenter",
"points": 2,
"category": "쪽번호",
"item":"가운데 아래"
} }
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

40
test.py
View File

@@ -22,15 +22,18 @@
import win32com.client import win32com.client
import os import os
import logging import logging
import shutil
from pathlib import Path from pathlib import Path
import win32com.client.gencache
def setup_logging(): def setup_logging():
"""로깅 설정""" """로깅 설정"""
logging.basicConfig( logging.basicConfig(
level = logging.INFO, level = logging.INFO,
format = '%(asctime)s - %(levelname)s - %(message)s', format = '%(asctime)s - %(levelname)s - %(message)s',
handlers = [ handlers = [
logging.FileHandler('hwp_conversion.log'), logging.FileHandler('hwp_conversion.log', encoding='utf-8'),
logging.StreamHandler() logging.StreamHandler()
] ]
) )
@@ -45,32 +48,36 @@ def convert_hwp_to_xml(input_folder, output_folder):
""" """
try: try:
# 한글 애플리케이션 객체 생성 # 한글 애플리케이션 객체 생성
hwp = win32com.client.Dispatch("HWPFrame.HwpObject") # hwp = win32com.client.Dispatch("HWPFrame.HwpObject")
hwp = win32com.client.gencache.EnsureDispatch("HWPFrame.HwpObject")
# 자동화 보안 설정 # 자동화 보안 설정
hwp.XHwpWindows.Item(0).Visible = False
hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule") hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule")
# hwp.XHwpWindows.Item(0).Visible = False
hwp.XHwpWindows.Item(0).Visible = True
# 출력 폴더가 없으면 생성 # 출력 폴더가 없으면 생성
os.makedirs(output_folder, exist_ok=True) os.makedirs(output_folder, exist_ok=True)
# HWP 파일 검색 및 변환 # HWP 파일 검색 및 변환
input_path = Path(input_folder) input_path = Path(input_folder)
for hwp_file in input_path.glob("*.hwp"): for hwp_file in input_path.glob("*.hwp"):
try: try:
# 파일 열기 # 파일 열기
hwp.Open(str(hwp_file)) hwp.Open(str(hwp_file), "HWP")
# XML 파일 경로 설정 # XML 파일 경로 설정
xml_filename = hwp_file.stem + ".xml" xml_filename = hwp_file.stem + ".hml"
xml_path = os.path.join(output_folder, xml_filename) xml_path = os.path.join(output_folder, xml_filename)
# print(f"xml_path:{xml_path} type:{type(xml_path)}")
# XML로 저장 # XML로 저장
hwp.SaveAs(xml_path, "HWPML2X") hwp.SaveAs(xml_path, "HWPML2X", "")
logging.info(f"변환 성공: {hwp_file.name} -> {xml_filename}") logging.info(f"변환 성공: {hwp_file.name} -> {xml_filename}")
except Exception as e: except Exception as e:
logging.error(f"파일 변환 실패: {hwp_file.name} - {str(e)}") logging.error(f"파일 변환 실패: {hwp_file.name} -> {e}")
finally: finally:
# 현재 문서 닫기 # 현재 문서 닫기
@@ -86,13 +93,26 @@ def convert_hwp_to_xml(input_folder, output_folder):
except: except:
pass pass
def delete_gen_py():
# gen_py 디렉토리 경로
gen_py_dir = os.path.join(os.environ['LOCALAPPDATA'], 'Temp', 'gen_py')
# gen_py 디렉토리 삭제
if os.path.exists(gen_py_dir):
shutil.rmtree(gen_py_dir)
print(f'{gen_py_dir} 디렉토리를 삭제했습니다.')
if __name__ == "__main__": if __name__ == "__main__":
# delete_gen_py()
# 로깅 설정 # 로깅 설정
setup_logging() setup_logging()
# 변환할 폴더 경로 설정 # 변환할 폴더 경로 설정
input_folder = r"C:\Users\gzero-ser7-win11\Documents\hwpTest\Input" # HWP 파일이 있는 폴더 input_folder = r"C:\Users\dra\project\HWP-Scoring\input" # HWP 파일이 있는 폴더
output_folder = r"C:\Users\gzero-ser7-win11\Documents\hwpTest\Output" # XML 파일을 저장할 폴더 output_folder = r"C:\Users\dra\project\HWP-Scoring\output" # XML 파일을 저장할 폴더
# output_folder = r"\hwp-output" # HWP 파일이 있는 폴더
# 변환 실행 # 변환 실행
convert_hwp_to_xml(input_folder, output_folder) convert_hwp_to_xml(input_folder, output_folder)

149
xpathSearch.py Normal file
View File

@@ -0,0 +1,149 @@
from lxml import etree
from difflib import SequenceMatcher
import json
class XMLPathHandler:
def __init__(self, xml_file_path):
"""
XML 파일을 로드하고 처리하는 핸들러
:param xml_file_path: XML 파일 경로
"""
self.tree = etree.parse(xml_file_path)
self.root = self.tree.getroot()
def similar(self, a, b):
"""
두 문자열의 유사도를 계산
:return: 유사도 점수 (0~1)
"""
return SequenceMatcher(None, a, b).ratio()
def find_similar_text(self, search_value, element_name, arg_name, threshold=0.8):
"""
XML에서 유사한 텍스트를 찾음
:param search_value: 찾고자 하는 텍스트
:param element_name: 검색할 요소 이름
:param arg_name: 검색할 속성 이름
:param threshold: 유사도 임계값
:return: 가장 유사한 텍스트와 점수
"""
# 특정 요소의 특정 속성을 가진 모든 요소 검색
xpath = f"//{element_name}[@{arg_name}]"
elements = self.root.xpath(xpath)
best_match = None
best_score = 0
for element in elements:
attr_value = element.get(arg_name)
if attr_value is not None:
score = self.similar(search_value, attr_value)
if score > threshold and score > best_score:
best_match = attr_value
best_score = score
return best_match, best_score
def build_xpath(self, item):
"""
설정 항목을 기반으로 XPath 생성
:param item: 설정 항목
:return: 구성된 XPath와 매칭된 텍스트, 유사도 점수
"""
if not all(key in item for key in ['ele', 'arg', 'searchValue']):
return None, None, 0
# 유사 텍스트 검색
matched_text, score = self.find_similar_text(
item['searchValue'],
item['ele'],
item['arg']
)
if matched_text:
# 기본 XPath 템플릿 구성
xpath = f"//{item['ele']}[@{item['arg']}='{matched_text}']"
# path가 제공된 경우, 해당 path를 기반으로 XPath 구성
if 'path' in item and item['path']:
xpath = item['path'].replace(f"[@{item['arg']}='']", f"[@{item['arg']}='{matched_text}']")
xpath = xpath.replace(f"[@{item['arg']}='searchValue']", f"[@{item['arg']}='{matched_text}']")
return xpath, matched_text, score
return None, None, 0
def process_config(self, config):
"""
설정된 JSON 설정을 처리
:param config: JSON 설정
:return: 처리된 XPath 결과들
"""
results = {}
for key, item in config.items():
results[key] = {
'original_config': item,
'processed_results': {}
}
xpath, matched_text, score = self.build_xpath(item)
if xpath:
try:
xpath_results = self.root.xpath(xpath)
results[key]['processed_results'] = {
'original_value': item['searchValue'],
'matched_value': matched_text,
'similarity_score': score,
'xpath': xpath,
'results': xpath_results
}
except etree.XPathEvalError as e:
results[key]['error'] = f"XPath evaluation error: {str(e)}"
else:
results[key]['error'] = "Unable to build XPath: missing required configuration"
return results
# 사용 예시
def main():
config = {
"0": {
"path": "//TEXTART[@Text='']/TEXTARTSHAPE/@FontName",
"ele": "TEXTART",
"arg": "Text",
"searchValue": "즐거운컬러푸드영양교실",
"value": "궁서체",
"points": 10
},
"1": {
"path": "//PARASHAPE[@Id=//TEXTART[@Text='']/ancestor::P/@ParaShape]/@Align",
"ele": "PARASHAPE",
"arg": "Align",
"searchValue": "Center",
"value": "Center",
"points": 2
}
}
xmlPath = r"C:\Users\dra\project\HWP-Scoring\output\1.hml";
handler = XMLPathHandler(xmlPath)
results = handler.process_config(config)
# 결과 출력
for key, result in results.items():
print(f"\nProcessing config item {key}:")
print(f"Original config: {result['original_config']}")
if 'error' in result:
print(f"Error: {result['error']}")
else:
processed = result['processed_results']
print(f"Generated XPath: {processed['xpath']}")
print(f"Matched text: {processed['matched_value']}")
print(f"Similarity score: {processed['similarity_score']}")
print(f"Results found: {processed['results']}")
if __name__ == "__main__":
main()