import json,io,openpyxl from openpyxl.utils import get_column_letter wb=openpyxl.load_workbook('한국지역난방공사.xlsx'); ws=wb.active merges=list(ws.merged_cells.ranges) def eff(r,c): v=ws.cell(r,c).value if v is not None: return v for m in merges: if m.min_row<=r<=m.max_row and m.min_col<=c<=m.max_col: return ws.cell(m.min_row,m.min_col).value return None def leafcol(r): last=None for c in range(4,11): if eff(r,c) not in (None,''): last=c return last groups=json.load(io.open('_tabgroups.json',encoding='utf-8')) bM=json.load(io.open('_newboardM.json',encoding='utf-8')) def host_external(url): return ('/cyb/' in url) or ('kdhc.co.kr/kdhc/' not in url) def classify(t): url=t['url']; mn=t['menuNo'] if mn is None or host_external(url): return ('사이트',None,None) if t['board']: info=bM.get(url) if info: M,tag=info['M'] if M in (0,) or (isinstance(M,str)): return ('게시판',0,'없음') # may override return ('게시판',M,'어문') return ('게시판',0,'없음') return ('페이지',1,'어문') plan=[] for gi,g in enumerate(groups): anchor=[t for t in g if t['active']] note='' if not anchor: # category board (G7 사전정보공표): all same menuNo mns=set(t['menuNo'] for t in g) plan.append({'gi':gi,'type':'categoryboard','mns':list(mns),'tabs':[t['label'] for t in g]}) continue a=anchor[0] if not a['sheet_rows']: plan.append({'gi':gi,'type':'active_not_in_sheet','self':a['label']}); continue r=a['sheet_rows'][0]; lc=leafcol(r); leaf=eff(r,lc) sib = (a['label']==leaf) news=[t for t in g if not t['in_sheet']] # also any OTHER present tabs (already in sheet as own rows) -> note others=[t for t in g if t['in_sheet'] and not t['active']] items=[] for t in news: L,M,N=classify(t) items.append({'label':t['label'],'menuNo':t['menuNo'],'url':t['url'],'L':L,'M':M,'N':N}) plan.append({'gi':gi,'type':'sibling' if sib else 'child', 'anchor_row':r,'leafcol':get_column_letter(lc),'leaf':leaf,'self':a['label'], 'others_in_sheet':[(t['label'],t['sheet_rows']) for t in others], 'new':items}) io.open('_plan.json','w',encoding='utf-8').write(json.dumps(plan,ensure_ascii=False,indent=1)) # readable L=[] for p in plan: if p['type'] in ('categoryboard','active_not_in_sheet'): L.append(f"G{p['gi']} [{p['type']}] {p}"); continue L.append(f"G{p['gi']} [{p['type']}] anchor r{p['anchor_row']} {p['leafcol']}={p['leaf']!r} self={p['self']!r}") if p['others_in_sheet']: L.append(f" others_already_in_sheet={p['others_in_sheet']}") for it in p['new']: L.append(f" + {it['L']:3} M={str(it['M']):>4} N={it['N'] or '':4} | {it['label']} (menuNo={it['menuNo']})") io.open('_plan.txt','w',encoding='utf-8').write('\n'.join(L)) print('groups planned:',len(plan)) print('total new rows:',sum(len(p.get('new',[])) for p in plan))