# -*- coding: utf-8 -*- """금산군 ui-nav_tabs 재검토 + 군민복지 cross-product 정리 (2026-05-31) - PHASE1: ui-nav_tabs 인페이지 탭 페이지 → 1행 유지, M=라이브 탭 개수 여성가족 05030301=3, 어르신 05030401=3, 사회복지 05030601=5(무변경), 읍·면 행정복지센터 06X0101 ×10 =2 - PHASE2: 군민복지(05030701) tab-ul type1 4탭 cross-product(147~159, 13행) → 4행으로 축소(공지사항/금산군자원봉사센터/복지시설/관련사이트). 151~159 삭제. """ import sys, openpyxl from copy import copy from openpyxl.utils import range_boundaries PATH = r'D:\01.프로젝트\DB수집\작업파일\광역_사이트맵\충청남도\3.금산군\충청남도_금산군.xlsx' WRITE = '--write' in sys.argv wb = openpyxl.load_workbook(PATH) ws = wb.active MAXC = ws.max_column # ---------- PHASE 1: M 정규화 (URL 매칭) ---------- MTARGETS = { '05030301': 3, '05030401': 3, '05030601': 5, '06010101': 2, '06020101': 2, '06030101': 2, '06040101': 2, '06050101': 2, '06060101': 2, '06070101': 2, '06080101': 2, '06090101': 2, '06100101': 2, } print('=== PHASE1: M 정규화 ===') for r in range(3, ws.max_row + 1): k = ws.cell(r, 11).value if not k: continue ks = str(k) for code, mval in MTARGETS.items(): if code + '.html' in ks: old_m = ws.cell(r, 13).value old_l = ws.cell(r, 12).value ws.cell(r, 13).value = mval print(f' row{r} {code} L={old_l} M:{old_m}->{mval}') break # ---------- PHASE 2: 군민복지 restructure ---------- print('=== PHASE2: 군민복지 정리 ===') # Step A: 147~150 G<-H, clear H for r in range(147, 151): g_old = ws.cell(r, 7).value h = ws.cell(r, 8).value ws.cell(r, 7).value = h ws.cell(r, 8).value = None print(f' row{r} G:{g_old}->{h} (H clear)') DEL_START, DEL_COUNT = 151, 9 # Step B: capture & clear merges merges = [str(mc) for mc in ws.merged_cells.ranges] for mc in list(ws.merged_cells.ranges): ws.unmerge_cells(str(mc)) # Step C: manual shift up (delete 151~159) max_row = ws.max_row for r in range(DEL_START, max_row - DEL_COUNT + 1): src = r + DEL_COUNT for c in range(1, MAXC + 1): s = ws.cell(src, c); d = ws.cell(r, c) d.value = s.value if s.has_style: d._style = copy(s._style) d.number_format = s.number_format d.hyperlink = None if s.hyperlink: d.hyperlink = copy(s.hyperlink) d.hyperlink.ref = d.coordinate for r in range(max_row - DEL_COUNT + 1, max_row + 1): for c in range(1, MAXC + 1): d = ws.cell(r, c); d.value = None; d.hyperlink = None # Step D: rebuild merges with row mapping def surv(x): return x < DEL_START or x >= DEL_START + DEL_COUNT def mp(x): return x if x < DEL_START else x - DEL_COUNT for mc in merges: c1, r1, c2, r2 = range_boundaries(mc) s = [x for x in range(r1, r2 + 1) if surv(x)] if not s: continue nr1, nr2 = mp(min(s)), mp(max(s)) if nr1 == nr2 and c1 == c2: continue # collapsed to single cell, no merge ws.merge_cells(start_row=nr1, start_column=c1, end_row=nr2, end_column=c2) # Step E: 순번 재번호 (151행 이후 -9 → 연속성 유지) for r in range(DEL_START, ws.max_row + 1): v = ws.cell(r, 2).value if isinstance(v, int): ws.cell(r, 2).value = v - DEL_COUNT print(f' deleted rows {DEL_START}~{DEL_START+DEL_COUNT-1} (9 rows)') if WRITE: wb.save(PATH) print('SAVED', PATH) else: print('DRY-RUN (use --write to save)')