공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
141 lines
5.8 KiB
Python
141 lines
5.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
import openpyxl, re
|
|
from copy import copy
|
|
from openpyxl.styles import PatternFill
|
|
|
|
FN='국민건강보험공단.xlsx'
|
|
BLUE=PatternFill(fill_type='solid', fgColor='FFBDD7EE')
|
|
H='https://www.nhis.or.kr'
|
|
def pg(label, path): return (label, H+path, '페이지', 1, '어문', '미부착')
|
|
def bd(label, path, m, n='어문'): return (label, H+path, '게시판', m, n, '미부착')
|
|
|
|
# (parent_url_substr, level 'G'|'F', tabs[first=self,...])
|
|
GROUPS=[
|
|
('wbhaca04500m01','G',[pg('일반건강검진','/nhis/healthin/wbhaca04500m01.do'),pg('암검진','/nhis/healthin/wbhaca04600m01.do'),
|
|
pg('의료급여생애 전환기검진','/nhis/healthin/wbhaca04700m01.do'),pg('영유아건강검진','/nhis/healthin/wbhaca04800m01.do'),
|
|
pg('학생건강검진','/nhis/healthin/wbhaca04900m01.do'),pg('학교 밖 청소년 건강검진','/nhis/healthin/wbhaca05200m01.do')]),
|
|
('retrieveDiseVltGnlSymp','G',[pg('일반증상','/nhis/healthin/retrieveDiseVltGnlSymp.do'),pg('어린이','/nhis/healthin/retrieveDiseVltChild.do'),
|
|
pg('남성','/nhis/healthin/retrieveDiseVltMan.do'),pg('여성','/nhis/healthin/retrieveDiseVltWoman.do')]),
|
|
('wbhace05600m01','G',[bd('건강검진','/nhis/healthin/wbhace05600m01.do',4,'어문,이미지,영상'),
|
|
bd('만성질환','/nhis/healthin/wbhace05800m01.do',1,'어문,이미지,영상'),
|
|
bd('운동 및 건강강좌','/nhis/healthin/wbhace06800m01.do',8,'어문,이미지,영상')]),
|
|
('wbhaec14100m01','F',[pg('강당','/nhis/together/wbhaec14100m01.do'),pg('회의실','/nhis/together/wbhaec14200m01.do'),
|
|
pg('체육시설','/nhis/together/wbhaec14300m01.do'),pg('주차장','/nhis/together/wbhaec14400m01.do'),
|
|
pg('문화시설','/nhis/together/wbhaec14500m01.do')]),
|
|
('wbhabe08100m01','F',[pg('자세히 알아보기','/nhis/policy/wbhabe08100m01.do'),pg('대상여부 확인','/nhis/policy/wbhabe08200m01.do'),
|
|
pg('적법요건','/nhis/policy/wbhabe08200m03.do')]),
|
|
('wbhaea02200m01','G',[bd('본부','/nhis/together/wbhaea02200m01.do',6648),bd('지역본부·지사','/nhis/together/wbhaea02210m01.do',437)]),
|
|
]
|
|
|
|
wb=openpyxl.load_workbook(FN); ws=wb.active
|
|
MAXC=27
|
|
DATA_END=159 # last possible data row to clear up to (use max_row)
|
|
|
|
# effective D,E,F via merges (F also merged in this sheet? F merges exist per ranges)
|
|
eff={4:{},5:{},6:{}}
|
|
for col in (4,5,6):
|
|
for r in range(3,161): eff[col][r]=ws.cell(r,col).value
|
|
for mr in ws.merged_cells.ranges:
|
|
if mr.min_col<=col<=mr.max_col and mr.min_row>=3:
|
|
top=ws.cell(mr.min_row,col).value
|
|
for r in range(mr.min_row,mr.max_row+1): eff[col][r]=top
|
|
|
|
data_rows=[r for r in range(3,161) if ws.cell(r,2).value is not None]
|
|
recs=[]
|
|
for r in data_rows:
|
|
rec={'src':r,'new':False,'mark':set()}
|
|
rec['D']=eff[4][r]; rec['E']=eff[5][r]; rec['F']=eff[6][r]
|
|
for c in range(7,MAXC+1): rec[c]=ws.cell(r,c).value
|
|
rec['url']=ws.cell(r,11).value
|
|
hl=ws.cell(r,11).hyperlink; rec['hlink']=hl.target if hl else rec['url']
|
|
recs.append(rec)
|
|
|
|
def midx(sub):
|
|
for i,rc in enumerate(recs):
|
|
if rc['url'] and sub in str(rc['url']): return i
|
|
return None
|
|
|
|
# snapshot styles before edit
|
|
stylesnap={}
|
|
for r in range(3,161):
|
|
for c in range(1,MAXC+1): stylesnap[(r,c)]=copy(ws.cell(r,c)._style)
|
|
|
|
out=[]
|
|
applied=[]
|
|
i=0
|
|
# process in original order; build mapping parent substr->group
|
|
gmap={g[0]:g for g in GROUPS}
|
|
for rc in recs:
|
|
g=None
|
|
for sub,grp in gmap.items():
|
|
if rc['url'] and sub in str(rc['url']):
|
|
g=grp; break
|
|
if not g:
|
|
out.append(rc); continue
|
|
sub,level,tabs=g
|
|
first=tabs[0]
|
|
# reuse parent for first tab
|
|
if level=='G':
|
|
rc[7]=first[0]
|
|
else: # F
|
|
rc['F']=first[0]; rc[7]=None
|
|
rc['url']=first[1]; rc['hlink']=first[1]; rc[11]=first[1]
|
|
rc[12]=first[2]; rc[13]=first[3]; rc[14]=first[4]; rc[15]=first[5]
|
|
rc['mark'].update([6,7,11,12,13,14,15])
|
|
out.append(rc)
|
|
for t in tabs[1:]:
|
|
ch={'src':rc['src'],'new':True,'mark':set(range(4,16))}
|
|
ch['D']=rc['D']; ch['E']=rc['E']
|
|
if level=='G':
|
|
ch['F']=rc['F']; ch[7]=t[0]
|
|
else:
|
|
ch['F']=t[0]; ch[7]=None
|
|
for c in range(8,MAXC+1): ch[c]=None
|
|
ch[11]=t[1]; ch['url']=t[1]; ch['hlink']=t[1]
|
|
ch[12]=t[2]; ch[13]=t[3]; ch[14]=t[4]; ch[15]=t[5]
|
|
out.append(ch)
|
|
applied.append((sub,len(tabs)))
|
|
recs=out
|
|
print('applied groups:', applied, 'final rows:', len(recs))
|
|
|
|
# WRITE
|
|
for mr in list(ws.merged_cells.ranges):
|
|
if mr.min_row>=3: ws.unmerge_cells(str(mr))
|
|
SITE='국민건강보험공단'
|
|
n=len(recs)
|
|
for i,rc in enumerate(recs):
|
|
r=3+i; src=rc['src']
|
|
for c in range(1,MAXC+1): ws.cell(r,c)._style=copy(stylesnap[(src,c)])
|
|
ws.cell(r,1).value=None
|
|
ws.cell(r,2).value=i+1
|
|
ws.cell(r,3).value=SITE
|
|
ws.cell(r,4).value=rc['D']; ws.cell(r,5).value=rc['E']; ws.cell(r,6).value=rc['F']
|
|
for c in range(7,MAXC+1): ws.cell(r,c).value=rc.get(c)
|
|
kc=ws.cell(r,11); kc.value=rc['url']; kc.hyperlink=rc['hlink'] if rc['url'] else None
|
|
for c in rc['mark']: ws.cell(r,c).fill=BLUE
|
|
ws.row_dimensions[r].height=15
|
|
for r in range(3+n,161):
|
|
for c in range(1,MAXC+1):
|
|
cell=ws.cell(r,c); cell.value=None; cell.hyperlink=None; cell.fill=PatternFill(fill_type=None)
|
|
|
|
def remerge(col, scope):
|
|
r=3
|
|
while r<3+n:
|
|
v=ws.cell(r,col).value
|
|
if v is None or v=='': r+=1; continue
|
|
r2=r
|
|
while r2+1<3+n:
|
|
if ws.cell(r2+1,col).value!=v: break
|
|
ok=True
|
|
for sc in scope:
|
|
if ws.cell(r2+1,sc).value!=ws.cell(r,sc).value: ok=False;break
|
|
if not ok: break
|
|
r2+=1
|
|
if r2>r:
|
|
for rr in range(r+1,r2+1): ws.cell(rr,col).value=None
|
|
ws.merge_cells(start_row=r,start_column=col,end_row=r2,end_column=col)
|
|
r=r2+1
|
|
remerge(6,[4,5]); remerge(5,[4]); remerge(4,[])
|
|
wb.save(FN)
|
|
print('saved')
|