From 14a4c25e4f1742e92991c69dad53e04215e6b1e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EA=B2=BD=EB=AF=BC?= Date: Thu, 19 Mar 2026 14:02:58 +0900 Subject: [PATCH] =?UTF-8?q?Cleanup:=20Deleting=2003.Code/=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=EC=9A=A9/converters/html=5Fto=5Fhwp=5Fbriefi?= =?UTF-8?q?ng.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../converters/html_to_hwp_briefing.py | 605 ------------------ 1 file changed, 605 deletions(-) delete mode 100644 03.Code/업로드용/converters/html_to_hwp_briefing.py diff --git a/03.Code/업로드용/converters/html_to_hwp_briefing.py b/03.Code/업로드용/converters/html_to_hwp_briefing.py deleted file mode 100644 index 308da52..0000000 --- a/03.Code/업로드용/converters/html_to_hwp_briefing.py +++ /dev/null @@ -1,605 +0,0 @@ -# -*- coding: utf-8 -*- -""" -HTML HWP 蹂 (湲고 - - ) - 癒몃━留щ━留닿 - 諛⑹ ( 踰 ы ) - - lead-box, section, data-table, strategy-grid, qa-grid, bottom-box 吏 - process-container ( ④ -pip install pyhwpx beautifulsoup4 -""" - 濡 -from pyhwpx import Hwp 몄) 吏 -from bs4 import BeautifulSoup -import os - Navy -留 -class Config: - """ ㅼ """ - PAGE_WIDTH = 210 - PAGE_HEIGHT = 297 - MARGIN_LEFT = 20 - MARGIN_RIGHT = 20 - MARGIN_TOP = 20 - MARGIN_BOTTOM = 15 - HEADER_LEN = 10 - FOOTER_LEN = 10 - CONTENT_WIDTH = 170 - -class HtmlToHwpConverter: - """HTML HWP 蹂 (湲고 - - )""" - - def __init__(self, visible=True): - self.hwp = Hwp(visible=visible) - self.cfg = Config() - self.colors = {} - self.is_first_h1 = True - - # - # 珥湲고 諛 대━ - # - - def _init_colors(self): - """ 珥湲고 (Navy 怨 - )""" - self.colors = { - 'primary-navy': self.hwp.RGBColor(26, 54, 93), # #1a365d - 'secondary-navy': self.hwp.RGBColor(44, 82, 130), # #2c5282 - 'accent-navy': self.hwp.RGBColor(49, 130, 206), # #3182ce - 'dark-gray': self.hwp.RGBColor(45, 55, 72), # #2d3748 - 'medium-gray': self.hwp.RGBColor(74, 85, 104), # #4a5568 - 'light-gray': self.hwp.RGBColor(226, 232, 240), # #e2e8f0 - 'bg-light': self.hwp.RGBColor(247, 250, 252), # #f7fafc - 'border-color': self.hwp.RGBColor(203, 213, 224), # #cbd5e0 - 'badge-safe': self.hwp.RGBColor(30, 111, 63), # #1e6f3f - 'badge-caution': self.hwp.RGBColor(154, 91, 19), # #9a5b13 - 'badge-risk': self.hwp.RGBColor(161, 43, 43), # #a12b2b - 'white': self.hwp.RGBColor(255, 255, 255), - 'black': self.hwp.RGBColor(0, 0, 0), - } - - def _mm(self, mm): - """諛由щ - HWP 濡 蹂몄 HWP 濡 蹂 - RGB濡 蹂고 ㅼ ( ъ )""" - self.hwp.set_font( - FaceName='留 怨', - Height=size, - Bold=bold, - TextColor=self.colors.get(color, self.colors['black']) - ) - - def _set_font(self, size=11, bold=False, hex_color='#000000'): - """고 ㅼ (HEX ъ )""" - self.hwp.set_font( - FaceName='留 怨', - Height=size, - Bold=bold, - TextColor=self._rgb(hex_color) - ) - - def _align(self, align): - """ ㅼ """ - actions = { - 'left': 'ParagraphShapeAlignLeft', - 'center': 'ParagraphShapeAlignCenter', - 'right': 'ParagraphShapeAlignRight', - 'justify': 'ParagraphShapeAlignJustify', - } - if align in actions: - self.hwp.HAction.Run(actions[align]) - - def _para(self, text='', size=10, color='black', bold=False, align='left'): - """臾몃 쎌 -""" - self._align(align) - self._font(size, color, bold) - if text: - self.hwp.insert_text(text) - self.hwp.BreakPara() - - def _exit_table(self): - """ 몄 紐⑤ 醫 -猷""" - self.hwp.HAction.Run("Cancel") - self.hwp.HAction.Run("CloseEx") - self.hwp.HAction.Run("MoveDocEnd") - self.hwp.BreakPara() - - def _setup_page(self): - """ ㅼ """ - try: - self.hwp.HAction.GetDefault("PageSetup", self.hwp.HParameterSet.HSecDef.HSet) - s = self.hwp.HParameterSet.HSecDef - s.PageDef.LeftMargin = self._mm(self.cfg.MARGIN_LEFT) - s.PageDef.RightMargin = self._mm(self.cfg.MARGIN_RIGHT) - s.PageDef.TopMargin = self._mm(self.cfg.MARGIN_TOP) - s.PageDef.BottomMargin = self._mm(self.cfg.MARGIN_BOTTOM) - s.PageDef.HeaderLen = self._mm(self.cfg.HEADER_LEN) - s.PageDef.FooterLen = self._mm(self.cfg.FOOTER_LEN) - self.hwp.HAction.Execute("PageSetup", s.HSet) - print(f"[ ㅼ ] щ갚: 醫 {self.cfg.MARGIN_LEFT}mm, {self.cfg.MARGIN_TOP}mm, 깆 ] ㅼ ㅽ : {e}") - - # - # 癒몃━留щ━留닿 - 諛⑹ - - def _create_header(self, right_text=""): - """癒몃━留 - (곗륫 )""" - print(f" 癒몃━留 - : {right_text if right_text else '(珥湲고)'}") - try: - self.hwp.HAction.GetDefault("HeaderFooter", self.hwp.HParameterSet.HHeaderFooter.HSet) - self.hwp.HParameterSet.HHeaderFooter.HSet.SetItem("HeaderFooterStyle", 0) - self.hwp.HParameterSet.HHeaderFooter.HSet.SetItem("HeaderFooterCtrlType", 0) - self.hwp.HAction.Execute("HeaderFooter", self.hwp.HParameterSet.HHeaderFooter.HSet) - - self.hwp.HAction.Run("ParagraphShapeAlignRight") - self._set_font(9, False, '#4a5568') - if right_text: - self.hwp.insert_text(right_text) - - self.hwp.HAction.Run("CloseEx") - except Exception as e: - print(f" [寃쎄 ] 癒몃━留 - (醫痢 ㅽ + 곗륫 踰 )") - print(f" 瑗щ━留닿린 - self.hwp.HAction.GetDefault("HeaderFooter", self.hwp.HParameterSet.HHeaderFooter.HSet) - self.hwp.HParameterSet.HHeaderFooter.HSet.SetItem("HeaderFooterStyle", 0) - self.hwp.HParameterSet.HHeaderFooter.HSet.SetItem("HeaderFooterCtrlType", 1) - self.hwp.HAction.Execute("HeaderFooter", self.hwp.HParameterSet.HHeaderFooter.HSet) - - # 2. 醫痢 + 紐 8pt - self.hwp.HAction.Run("ParagraphShapeAlignLeft") - self._set_font(8, False, '#4a5568') - self.hwp.insert_text(left_text) - - # 3. 瑗щ━留リ린 - self.hwp.HAction.Run("CloseEx") - - # 4. 履쎈 (곗륫 ) - self.hwp.HAction.GetDefault("PageNumPos", self.hwp.HParameterSet.HPageNumPos.HSet) - self.hwp.HParameterSet.HPageNumPos.DrawPos = self.hwp.PageNumPosition("BottomRight") - self.hwp.HAction.Execute("PageNumPos", self.hwp.HParameterSet.HPageNumPos.HSet) - - def _new_section_with_header(self, header_text): - """ 援ъ 癒몃━留 ㅼ """ - print(f" 援ъ 癒몃━留 癒몃━留 - # 諛곌꼍 ㅼ - # - - def _set_cell_bg(self, color_name): - """諛곌꼍 ㅼ ( )""" - self.hwp.HAction.GetDefault("CellBorderFill", self.hwp.HParameterSet.HCellBorderFill.HSet) - pset = self.hwp.HParameterSet.HCellBorderFill - pset.FillAttr.type = self.hwp.BrushType("NullBrush|WinBrush") - pset.FillAttr.WinBrushFaceStyle = self.hwp.HatchStyle("None") - pset.FillAttr.WinBrushHatchColor = self.hwp.RGBColor(0, 0, 0) - pset.FillAttr.WinBrushFaceColor = self.colors.get(color_name, self.colors['white']) - pset.FillAttr.WindowsBrush = 1 - self.hwp.HAction.Execute("CellBorderFill", pset.HSet) - - # - # HTML 蹂고 - - # - - def _convert_lead_box(self, elem): - """lead-box 蹂듭 湲곗“ 諛 )""" - content = elem.find("div") - if not content: - return - - text = content.get_text(strip=True) - text = ' '.join(text.split()) - print(f" lead-box") - - self.hwp.create_table(1, 1, treat_as_char=True) - self._set_cell_bg('bg-light') - self._font(11.5, 'dark-gray', False) - self.hwp.insert_text(text) - self._exit_table() - - def _convert_strategy_grid(self, elem): - """strategy-grid 蹂 - 諛 )""" - items = elem.find_all(class_="strategy-item") - if not items: - return - - print(f" strategy-grid: {len(items)} items") - - self.hwp.create_table(2, 2, treat_as_char=True) - - for i, item in enumerate(items[:4]): - if i > 0: - self.hwp.HAction.Run("MoveRight") - - self._set_cell_bg('bg-light') - - title = item.find(class_="strategy-title") - if title: - self._font(10, 'primary-navy', True) - self.hwp.insert_text(title.get_text(strip=True)) - self.hwp.BreakPara() - - p = item.find("p") - if p: - self._font(9.5, 'dark-gray', False) - self.hwp.insert_text(p.get_text(strip=True)) - - self._exit_table() - - def _convert_process_container(self, elem): - """process-container 蹂④ - 蹂 - 濡 - 몄)""" - steps = elem.find_all(class_="process-step") - if not steps: - return - - print(f" process-container: {len(steps)} steps") - - rows = len(steps) - self.hwp.create_table(rows, 2, treat_as_char=True) - - for i, step in enumerate(steps): - if i > 0: - self.hwp.HAction.Run("MoveRight") - - # 踰 - - num = step.find(class_="step-num") - self._set_cell_bg('primary-navy') - self._font(10, 'white', True) - self._align('center') - if num: - self.hwp.insert_text(num.get_text(strip=True)) - - self.hwp.HAction.Run("MoveRight") - - # 댁 - - content = step.find(class_="step-content") - self._set_cell_bg('bg-light') - self._font(10.5, 'dark-gray', False) - self._align('left') - if content: - self.hwp.insert_text(content.get_text(strip=True)) - - self._exit_table() - - def _convert_data_table(self, table): - """data-table 蹂ы )""" - data = [] - - thead = table.find("thead") - if thead: - ths = thead.find_all("th") - data.append([th.get_text(strip=True) for th in ths]) - - tbody = table.find("tbody") - if tbody: - for tr in tbody.find_all("tr"): - row = [] - for td in tr.find_all("td"): - badge = td.find(class_="badge") - if badge: - badge_class = ' '.join(badge.get('class', [])) - badge_text = badge.get_text(strip=True) - if 'badge-safe' in badge_class: - row.append(f"[ {badge_text}]") - elif 'badge-caution' in badge_class: - row.append(f"[ {badge_text}]") - elif 'badge-risk' in badge_class: - row.append(f"[ {badge_text}]") - else: - row.append(f"[{badge_text}]") - else: - row.append(td.get_text(strip=True)) - data.append(row) - - if not data: - return - - rows = len(data) - cols = len(data[0]) if data else 0 - print(f" data-table: {rows} {cols}") - - self.hwp.create_table(rows, cols, treat_as_char=True) - - for row_idx, row in enumerate(data): - for col_idx, cell_text in enumerate(row): - is_header = (row_idx == 0) - is_first_col = (col_idx == 0 and not is_header) - - is_safe = '[ ' in str(cell_text) - is_caution = '[ ' in str(cell_text) - is_risk = '[ ' in str(cell_text) - - if is_header: - self._set_cell_bg('primary-navy') - self._font(9, 'white', True) - elif is_first_col: - self._set_cell_bg('bg-light') - self._font(9.5, 'primary-navy', True) - elif is_safe: - self._font(9.5, 'badge-safe', True) - elif is_caution: - self._font(9.5, 'badge-caution', True) - elif is_risk: - self._font(9.5, 'badge-risk', True) - else: - self._font(9.5, 'dark-gray', False) - - self._align('center') - self.hwp.insert_text(str(cell_text)) - - if not (row_idx == rows - 1 and col_idx == cols - 1): - self.hwp.HAction.Run("MoveRight") - - self._exit_table() - - def _convert_qa_grid(self, elem): - """qa-grid 蹂 諛 )""" - items = elem.find_all(class_="qa-item") - if not items: - return - - print(f" qa-grid: {len(items)} items") - - self.hwp.create_table(1, 2, treat_as_char=True) - - for i, item in enumerate(items[:2]): - if i > 0: - self.hwp.HAction.Run("MoveRight") - - self._set_cell_bg('bg-light') - - text = item.get_text(strip=True) - strong = item.find("strong") - if strong: - q_text = strong.get_text(strip=True) - a_text = text.replace(q_text, '').strip() - - self._font(9.5, 'primary-navy', True) - self.hwp.insert_text(q_text) - self.hwp.BreakPara() - self._font(9.5, 'dark-gray', False) - self.hwp.insert_text(a_text) - else: - self._font(9.5, 'dark-gray', False) - self.hwp.insert_text(text) - - self._exit_table() - - def _convert_bottom_box(self, elem): - """bottom-box 蹂듭 寃곕 諛 )""" - left = elem.find(class_="bottom-left") - right = elem.find(class_="bottom-right") - - if not left or not right: - return - - left_text = ' '.join(left.get_text().split()) - right_text = right.get_text(strip=True) - print(f" bottom-box") - - self.hwp.create_table(1, 2, treat_as_char=True) - - # 醫痢 (Navy 諛곌꼍) - self._set_cell_bg('primary-navy') - self._font(10.5, 'white', True) - self._align('center') - self.hwp.insert_text(left_text) - - self.hwp.HAction.Run("MoveRight") - - # 곗륫 ( 고 諛곌꼍) - self._set_cell_bg('bg-light') - self._font(10.5, 'primary-navy', True) - self._align('center') - self.hwp.insert_text(right_text) - - self._exit_table() - - def _convert_section(self, section): - """section 蹂 " + title.get_text(strip=True), 12, 'primary-navy', True) - - strategy_grid = section.find(class_="strategy-grid") - if strategy_grid: - self._convert_strategy_grid(strategy_grid) - - process = section.find(class_="process-container") - if process: - self._convert_process_container(process) - - table = section.find("table", class_="data-table") - if table: - self._convert_data_table(table) - - ul = section.find("ul") - if ul: - for li in ul.find_all("li", recursive=False): - keyword = li.find(class_="keyword") - if keyword: - kw_text = keyword.get_text(strip=True) - full = li.get_text(strip=True) - rest = full.replace(kw_text, '', 1).strip() - - self._font(10.5, 'primary-navy', True) - self.hwp.insert_text(" " + kw_text + " ") - self._font(10.5, 'dark-gray', False) - self.hwp.insert_text(rest) - self.hwp.BreakPara() - else: - self._para(" " + li.get_text(strip=True), 10.5, 'dark-gray') - - qa_grid = section.find(class_="qa-grid") - if qa_grid: - self._convert_qa_grid(qa_grid) - - self._para() - - def _convert_sheet(self, sheet, is_first_page=False, footer_title=""): - """ (sheet) 蹂 - 留 癒몃━留щ━留 - ㅼ - if is_first_page: - # 癒몃━留 - - ㅽ 異異 - header = sheet.find(class_="page-header") - if header: - left = header.find(class_="header-left") - right = header.find(class_="header-right") - # 곗륫 - ㅽ ъ (遺 - 紐 - ) - header_text = right.get_text(strip=True) if right else "" - if header_text: - self._create_header(header_text) - - # 瑗щ━留紐 + 踰 - self._create_footer(footer_title) - - # 紐 - title = sheet.find(class_="header-title") - if title: - title_text = title.get_text(strip=True) - if '[泥⑤ ]' in title_text: - self._para(title_text, 15, 'primary-navy', True, 'left') - self._font(10, 'secondary-navy', False) - self._align('left') - self.hwp.insert_text("" * 60) - self.hwp.BreakPara() - else: - self._para(title_text, 23, 'primary-navy', True, 'center') - self._font(10, 'secondary-navy', False) - self._align('center') - self.hwp.insert_text("" * 45) - self.hwp.BreakPara() - - self._para() - - # 由щ 諛 - lead_box = sheet.find(class_="lead-box") - if lead_box: - self._convert_lead_box(lead_box) - self._para() - - # - 뱀 - - for section in sheet.find_all(class_="section"): - self._convert_section(section) - - # 諛 - bottom_box = sheet.find(class_="bottom-box") - if bottom_box: - self._para() - self._convert_bottom_box(bottom_box) - - # - # 硫⑥ - - def convert(self, html_path, output_path): - """HTML HWP 蹂ㅽ""" - - print("=" * 60) - print("HTML HWP 蹂 (湲고 - - ) ") - print(" 癒몃━留щ━留닿 - 諛 Navy -留, 湲고 - ") - print("=" * 60) - - print(f"\n[ ] {html_path}") - - with open(html_path, 'r', encoding='utf-8') as f: - soup = BeautifulSoup(f.read(), 'html.parser') - - # 紐 異異 (瑗щ━留) - title_tag = soup.find('title') - if title_tag: - full_title = title_tag.get_text(strip=True) - footer_title = full_title.split(':')[0].strip() - else: - footer_title = "" - - self.hwp.FileNew() - self._init_colors() - self._setup_page() - - # 蹂 - 蹂\n") - - for i, sheet in enumerate(sheets, 1): - print(f"[{i}/{total}] 泥 怨...") - self._convert_sheet(sheet, is_first_page=(i == 1), footer_title=footer_title) - - if i < total: - self.hwp.HAction.Run("BreakPage") - - # - self.hwp.SaveAs(output_path) - print(f"\n - 猷: {output_path}") - - def close(self): - """HWP 醫 -猷""" - try: - self.hwp.Quit() - except: - pass - - -def main(): - """ ㅽ""" - - html_path = r"D:\for python\geulbeot-light\geulbeot-light\output\briefing.html" - output_path = r"D:\for python\geulbeot-light\geulbeot-light\output\briefing.hwp" - - print("=" * 60) - print("HTML HWP 蹂 (湲고 - )") - print("=" * 60) - print() - - try: - converter = HtmlToHwpConverter(visible=True) - converter.convert(html_path, output_path) - - print("\n" + "=" * 60) - print(" 蹂 - 猷!") - print("=" * 60) - - input("\nEnter瑜 - 대㈃ HWP媛 ロ...") - converter.close() - - except FileNotFoundError: - print(f"\n[ ] - 李얠 - 듬: {html_path}") - print("寃쎈瑜 댁< - 몄.") - except Exception as e: - print(f"\n[ ] {e}") - import traceback - traceback.print_exc() - - -if __name__ == "__main__": - main()