공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
67 lines
2.7 KiB
Python
67 lines
2.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
# 괴산 _gs_nodes.json → 엑셀 재구성 (전주 빌더 패턴: 템플릿스타일 보존 + prefix-run 병합)
|
|
import openpyxl, json, sys, copy, datetime, io
|
|
sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
|
|
DIR=r'1.괴산군'
|
|
F=DIR+r'\충청북도_괴산군.xlsx'
|
|
SITE='충청북도 괴산군'
|
|
import shutil
|
|
shutil.copyfile(F, F.replace('.xlsx','_backup_재구축전.xlsx'))
|
|
|
|
nodes=json.load(open('_gs_nodes.json',encoding='utf-8'))
|
|
# rows: path + L/M/N/O
|
|
rows=[]
|
|
for n in nodes:
|
|
path=[x for x in n['d'] if x]
|
|
if not path: continue
|
|
L=n['kind']
|
|
M=n['M'] if L=='게시판' else (1 if L=='페이지' else None)
|
|
O=''
|
|
if n.get('O'): O=','.join('%d유형'%t for t in n['O'])
|
|
else: O='미부착' if L in ('페이지','게시판') else None
|
|
rows.append({'path':path,'url':n['url'],'L':L,'M':M,'N':('어문' if L in('페이지','게시판') else None),'O':O})
|
|
print('빌드행',len(rows))
|
|
|
|
wb=openpyxl.load_workbook(F); ws=wb.active
|
|
TPL={}
|
|
for c in range(1,28):
|
|
s=ws.cell(3,c)
|
|
TPL[c]=dict(font=copy.copy(s.font),fill=copy.copy(s.fill),border=copy.copy(s.border),
|
|
align=copy.copy(s.alignment),numfmt=s.number_format)
|
|
keep={'B1:R1','Y1:AA1','S1:W1'}
|
|
for rng in list(ws.merged_cells.ranges):
|
|
if str(rng) not in keep: ws.unmerge_cells(str(rng))
|
|
for r in range(3,ws.max_row+1):
|
|
for c in range(1,28): ws.cell(r,c).value=None
|
|
def setcell(r,c,val):
|
|
cell=ws.cell(r,c); cell.value=val; t=TPL[c]
|
|
cell.font=copy.copy(t['font']); cell.fill=copy.copy(t['fill'])
|
|
cell.border=copy.copy(t['border']); cell.alignment=copy.copy(t['align']); cell.number_format=t['numfmt']
|
|
TODAY=datetime.date(2026,6,6)
|
|
LEVELCOL={0:4,1:5,2:6,3:7,4:8}
|
|
r0=3
|
|
for i,rec in enumerate(rows):
|
|
r=r0+i
|
|
setcell(r,2,i+1); setcell(r,3,SITE)
|
|
for idx in range(5): setcell(r,LEVELCOL[idx],None)
|
|
setcell(r,9,None); setcell(r,10,None)
|
|
setcell(r,11,rec['url']); setcell(r,12,rec['L'])
|
|
setcell(r,13,rec['M'] if rec['M'] not in('',None) else None)
|
|
setcell(r,14,rec['N']); setcell(r,15,rec['O'])
|
|
for c in (16,17,18,19,20,21,22,23,24): setcell(r,c,None)
|
|
setcell(r,25,None); setcell(r,26,None); setcell(r,27,None)
|
|
ws.row_dimensions[r].height=15
|
|
N=len(rows)
|
|
for idx in range(5):
|
|
col=LEVELCOL[idx]; i=0
|
|
while i<N:
|
|
if len(rows[i]['path'])<=idx: i+=1; continue
|
|
pref=tuple(rows[i]['path'][:idx+1]); j=i
|
|
while j+1<N and len(rows[j+1]['path'])>idx and tuple(rows[j+1]['path'][:idx+1])==pref: j+=1
|
|
ws.cell(r0+i,col).value=rows[i]['path'][idx]
|
|
if j>i: ws.merge_cells(start_row=r0+i,start_column=col,end_row=r0+j,end_column=col)
|
|
i=j+1
|
|
wb.save(F)
|
|
from collections import Counter
|
|
print('저장:',F,'| 행',N,'| L',dict(Counter(x['L'] for x in rows)))
|