# -*- coding: utf-8 -*- # 청양 본문탭 누락전개(+29) + 고아행386~390 삭제. 123+ 재구축, 1~122 불변, D/E/F/G 병합재계산. import openpyxl, json, io, sys, shutil from copy import copy from collections import Counter sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8') F=r'D:\01.프로젝트\DB수집\작업파일\광역_사이트맵\충청남도\13.청양군\충청남도_청양군.xlsx' BK=r'D:\01.프로젝트\DB수집\작업파일\광역_사이트맵\충청남도\13.청양군\충청남도_청양군_backup_본문탭전개전.xlsx' shutil.copyfile(F,BK); print('백업',BK) miss=json.load(open('_cy3_missing.json',encoding='utf-8')) wb=openpyxl.load_workbook(F); ws=wb.active NCOL=17; CCOL=3 def style_of(r,c): cell=ws.cell(r,c) return dict(font=copy(cell.font),border=copy(cell.border),fill=copy(cell.fill), alignment=copy(cell.alignment),number_format=cell.number_format,protection=copy(cell.protection)) def apply_style(cell,st): cell.font=st['font']; cell.border=st['border']; cell.fill=st['fill'] cell.alignment=st['alignment']; cell.number_format=st['number_format']; cell.protection=st['protection'] last=ws.max_row # 1) 123+ 캡처 ORPHAN=set(range(386,391)) PARENT_B={135:'r133',248:'r243',250:'r246',296:'r291',297:'r292'} # anchor B순번 # anchor별 자식 children(label,url,blank), child col def childcol(b): return 8 if b in (296,297) else 7 def childlist(b): key={135:'133',248:'243',250:'246',296:'291',297:'292'}[b] return miss[key]['miss'] # 부모 값 세팅 PARENT_SET={ 135:{'set':{7:'청양사랑기부제 안내'},'L':'페이지'}, 250:{'set':{7:'인구증가 시책'}}, 296:{'set':{8:'고추'}}, 297:{'set':{8:'전통주(구기주/생막걸리)'},'L':'페이지'}, } rowh=ws.row_dimensions[200].height or 15 old=[] for r in range(123,last+1): if r in ORPHAN: continue b=ws.cell(r,2).value hl=ws.cell(r,11).hyperlink rec={'b':b,'vals':{c:ws.cell(r,c).value for c in range(2,NCOL+1)}, 'st':{c:style_of(r,c) for c in range(2,NCOL+1)}, 'hyper':(hl.target if hl else None)} # 부모 값/ L 수정 if b in PARENT_SET: ps=PARENT_SET[b] for c,v in ps.get('set',{}).items(): rec['vals'][c]=v if 'L' in ps: rec['vals'][12]=ps['L'] old.append(rec) # 2) 새 리스트 구성(부모 뒤 자식 삽입) def copy_st(st): return dict(font=copy(st['font']),border=copy(st['border']),fill=copy(st['fill']), alignment=copy(st['alignment']),number_format=st['number_format'],protection=copy(st['protection'])) def make_child(lab,url,blank,col,style_src): vals={c:None for c in range(2,NCOL+1)} vals[3]='충청남도 청양군' vals[col]=lab vals[11]=url if blank: vals[12]='사이트' else: vals[12]='페이지'; vals[13]=1; vals[14]='어문' return {'b':None,'vals':vals,'st':style_src,'hyper':url if url and url.startswith('http') else None,'new':True} newlist=[] added=0 for rec in old: newlist.append(rec) b=rec['b'] if b in PARENT_B: col=childcol(b) # 스타일은 부모행 각 컬럼 스타일 복사 src={c:rec['st'][c] for c in range(2,NCOL+1)} for x in childlist(b): newlist.append(make_child(x['lab'],x['absu'],x['blank'],col,{c:copy_st(src[c]) for c in range(2,NCOL+1)})) added+=1 print('기존123+',len(old),'신규',added,'→ 합',len(newlist)) # 3) 123+ 전체 삭제 ws.delete_rows(123, last-123+1) # 4) 새 행 쓰기 for i,rec in enumerate(newlist): r=123+i for c in range(2,NCOL+1): cell=ws.cell(r,c); cell.value=rec['vals'][c]; apply_style(cell,rec['st'][c]) ws.row_dimensions[r].height=rowh u=rec['hyper'] if u: ws.cell(r,11).hyperlink=u newlast=122+len(newlist) print('새 max data row',newlast) # 5) 병합 재계산 D/E/F/G (4~7), 123+만 keep=[m for m in ws.merged_cells.ranges if not (m.min_row>=123 and m.min_col in (4,5,6,7))] # delete_rows가 123+ D/E/F 병합 제거했지만 잔여 가능 → 명시적 정리 for m in list(ws.merged_cells.ranges): if m.min_row>=123 and m.min_col in (4,5,6,7): ws.unmerge_cells(str(m)) def has_val(r,c): v=ws.cell(r,c).value return v is not None and str(v).strip()!='' for c in range(4,8): # D,E,F,G r=123 while r<=newlast: if has_val(r,c): end=newlast for r2 in range(r+1,newlast+1): if any(has_val(r2,cc) for cc in range(4,c+1)): end=r2-1; break if end>r: ws.merge_cells(start_row=r,start_column=c,end_row=end,end_column=c) r=end+1 else: r+=1 wb.save(F) print('저장 완료') d=Counter(ws.cell(r,12).value for r in range(123,newlast+1)) print('123+ L분포',dict(d))