DB_JOB/작업파일/완료/광역_사이트맵/충청북도/_cy3_build2.py
hehihoho3 df16c98366 백업: DB수집 전체 스냅샷 (공공기관2 정리 전)
공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:15:40 +09:00

109 lines
4.5 KiB
Python

# -*- coding: utf-8 -*-
# 청양 본문탭 +29 전개 + 고아5삭제. fill-down 방식(전행 풀path→consecutive-equal 병합). 1~122 불변.
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_본문탭전개2전.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
last=ws.max_row
# 1) 병합맵 → filled[(r,c)]
filled={}
mranges=list(ws.merged_cells.ranges)
def anchor_val(r,c):
for m in mranges:
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 ws.cell(r,c).value
for r in range(123,last+1):
for c in range(4,9):
filled[(r,c)]=anchor_val(r,c)
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 cstyle(st): return {k:(copy(v) if k!='number_format' else v) for k,v in st.items()}
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']
ORPHAN=set(range(386,391))
# 부모 행(B순번)별 자식
PLAN={ # anchor B순번 -> (childcol, parent_set{col:val}, parent_Lfix, miss_key)
135:(7,{7:'청양사랑기부제 안내'},'페이지','133'),
248:(7,{},None,'243'),
250:(7,{7:'인구증가 시책'},None,'246'),
296:(8,{8:'고추'},None,'291'),
297:(8,{8:'전통주(구기주/생막걸리)'},'페이지','292'),
}
rowh=ws.row_dimensions[200].height or 15
# 2) 기존행 캡처(filled D-H + 기타 그대로)
def cap_row(r):
vals={c:ws.cell(r,c).value for c in range(2,NCOL+1)}
for c in range(4,9): vals[c]=filled[(r,c)] # D-H를 filled로
hl=ws.cell(r,11).hyperlink
return {'b':vals[2],'vals':vals,'st':{c:style_of(r,c) for c in range(2,NCOL+1)},'hyper':(hl.target if hl else None)}
old=[]
for r in range(123,last+1):
if r in ORPHAN: continue
rec=cap_row(r)
b=rec['b']
if b in PLAN:
col,pset,Lfix,_=PLAN[b]
for c,v in pset.items(): rec['vals'][c]=v
if Lfix: rec['vals'][12]=Lfix
old.append(rec)
# 3) 새 리스트 + 자식 삽입(filled path = 부모 filled 기반)
def make_child(parentrec,col,lab,url,blank):
vals={c:None for c in range(2,NCOL+1)}
vals[3]='충청남도 청양군'
# filled D-H 상속: 부모의 filled D..(col-1) 복사, col=lab, 더깊은=None
for c in range(4,col): vals[c]=parentrec['vals'][c]
vals[col]=lab
vals[11]=url
if blank: vals[12]='사이트'
else: vals[12]='페이지'; vals[13]=1; vals[14]='어문'
st={c:cstyle(parentrec['st'][c]) for c in range(2,NCOL+1)}
return {'b':None,'vals':vals,'st':st,'hyper':url if url and str(url).startswith('http') else None}
newlist=[]; added=0
for rec in old:
newlist.append(rec)
b=rec['b']
if b in PLAN:
col,_,_,mk=PLAN[b]
for x in miss[mk]['miss']:
newlist.append(make_child(rec,col,x['lab'],x['absu'],x['blank'])); added+=1
print('기존',len(old),'신규',added,'',len(newlist))
# 4) 123+ 언머지 + 삭제
for m in list(ws.merged_cells.ranges):
if m.min_row>=123: ws.unmerge_cells(str(m))
ws.delete_rows(123,last-123+1)
# 5) 쓰기(filled 전값)
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
if rec['hyper']: ws.cell(r,11).hyperlink=rec['hyper']
newlast=122+len(newlist)
# 6) 병합 재계산: consecutive-equal per col 4-8
def val(r,c):
v=ws.cell(r,c).value
return v if (v is not None and str(v).strip()!='') else None
for c in range(4,9):
r=123
while r<=newlast:
v=val(r,c)
if v is None: r+=1; continue
r2=r
while r2+1<=newlast and val(r2+1,c)==v: r2+=1
if r2>r: ws.merge_cells(start_row=r,start_column=c,end_row=r2,end_column=c)
r=r2+1
wb.save(F)
print('저장 newlast',newlast,'max_row',ws.max_row)
d=Counter(ws.cell(r,12).value for r in range(123,newlast+1))
print('123+ L',dict(d))