공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
109 lines
4.5 KiB
Python
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))
|