공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
102 lines
3.4 KiB
Python
102 lines
3.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
import openpyxl, json
|
|
from openpyxl.worksheet.hyperlink import Hyperlink
|
|
|
|
F='충청남도_천안시.xlsx'
|
|
wb=openpyxl.load_workbook(F); ws=wb.active
|
|
counts={o['row']:o for o in json.load(open('counts.json',encoding='utf-8'))}
|
|
|
|
DELROWS=[68,112,126,151,156,248,330,584]
|
|
SITES=[329,337,363,551]
|
|
PAGES=[12,71,148,192,409]
|
|
delset=set(DELROWS)
|
|
|
|
log=[]
|
|
# ---- Phase A: board M/N recollect (skip delrows; skip reclassify rows) ----
|
|
chgM=chgN=0
|
|
for r,o in counts.items():
|
|
if r in delset: continue
|
|
if r in SITES or r in PAGES: continue
|
|
t=o.get('total')
|
|
if t is None: continue
|
|
if ws.cell(r,13).value != t:
|
|
ws.cell(r,13).value=t; chgM+=1
|
|
Nv=ws.cell(r,14).value
|
|
if t==0:
|
|
if Nv!='없음': ws.cell(r,14).value='없음'; chgN+=1
|
|
else:
|
|
if Nv in (None,'','없음'): ws.cell(r,14).value='어문'; chgN+=1
|
|
log.append('PhaseA: M changed %d, N changed %d'%(chgM,chgN))
|
|
|
|
# ---- Phase A2: reclassify non-board rows ----
|
|
for r in SITES:
|
|
ws.cell(r,12).value='사이트'; ws.cell(r,13).value=None; ws.cell(r,14).value=None
|
|
for r in PAGES:
|
|
ws.cell(r,12).value='페이지'; ws.cell(r,13).value=1
|
|
if ws.cell(r,14).value in (None,'','없음'): ws.cell(r,14).value='어문'
|
|
log.append('PhaseA2: %d sites, %d pages reclassified'%(len(SITES),len(PAGES)))
|
|
|
|
# ---- Phase B: delete landing-shell rows ----
|
|
# capture data merges for col D(4),E(5),F(6)
|
|
data_merges=[] # (col,minr,maxr)
|
|
header_merges=[]
|
|
for mr in list(ws.merged_cells.ranges):
|
|
if mr.min_row<3:
|
|
header_merges.append(str(mr)); continue
|
|
if mr.min_col==mr.max_col and mr.min_col in (4,5,6):
|
|
data_merges.append((mr.min_col,mr.min_row,mr.max_row))
|
|
else:
|
|
log.append('UNEXPECTED data merge kept as-is: %s'%mr)
|
|
|
|
# carry E label to next surviving row for each E-collapse group
|
|
for r in DELROWS:
|
|
label=ws.cell(r,5).value
|
|
# next surviving row is r+1 (not a delrow)
|
|
assert (r+1) not in delset
|
|
# will set after unmerge
|
|
# unmerge all captured data merges
|
|
for col,a,b in data_merges:
|
|
ws.unmerge_cells(start_row=a,start_column=col,end_row=b,end_column=col)
|
|
# now set E labels on r+1 (writable after unmerge)
|
|
for r in DELROWS:
|
|
label=ws.cell(r,5).value
|
|
ws.cell(r+1,5).value=label
|
|
|
|
# delete rows bottom-up
|
|
for r in sorted(DELROWS,reverse=True):
|
|
ws.delete_rows(r,1)
|
|
|
|
# build oldrow->newrow map
|
|
def newrow(old):
|
|
return old - sum(1 for d in DELROWS if d<old)
|
|
|
|
# re-add merges remapped (drop deleted rows inside ranges)
|
|
remerged=0
|
|
for col,a,b in data_merges:
|
|
rows=[x for x in range(a,b+1) if x not in delset]
|
|
if not rows: continue
|
|
na=newrow(rows[0]); nb=newrow(rows[-1])
|
|
if nb>na:
|
|
ws.merge_cells(start_row=na,start_column=col,end_row=nb,end_column=col)
|
|
remerged+=1
|
|
log.append('PhaseB: deleted %d rows, re-merged %d data merges'%(len(DELROWS),remerged))
|
|
|
|
# rebuild K hyperlinks from value + renumber B
|
|
maxr=ws.max_row
|
|
bnum=0; hl=0
|
|
for r in range(3,maxr+1):
|
|
# B renumber only for content rows (B had a value)
|
|
if ws.cell(r,2).value is not None:
|
|
bnum+=1; ws.cell(r,2).value=bnum
|
|
k=ws.cell(r,11)
|
|
v=k.value
|
|
if v and isinstance(v,str) and v.startswith('http'):
|
|
k.hyperlink=Hyperlink(ref=k.coordinate,target=v); k.style='Hyperlink'; hl+=1
|
|
else:
|
|
if k.hyperlink: k.hyperlink=None
|
|
log.append('Post: maxrow=%d, B renumbered to %d, K hyperlinks=%d'%(maxr,bnum,hl))
|
|
|
|
wb.save(F)
|
|
print('\n'.join(log))
|
|
print('SAVED',F)
|