DB_JOB/작업파일/공공기관2/12.한국철도공사/_rebuild.py
hehihoho3 b0acd1e705 백업: 셀병합 정상화(D~J)+KDHC 옵션2/행높이17, 오늘(06-21) 제출 17곳 검수·압축
- 공공기관2/3 작업본 + 오늘 제출 17곳 D~J 카테고리 셀병합 정상화
- 한국지역난방공사 옵션2(고아셀 F98 수정)+전행 높이17
- 제출_프리랜서2_2026-06-21.zip 생성(17개 xlsx, 2,468행)

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

143 lines
4.9 KiB
Python

import openpyxl, json, sys, os, shutil, time
from copy import copy
from openpyxl.styles import PatternFill
from openpyxl.utils import get_column_letter
sys.stdout.reconfigure(encoding='utf-8')
P=r'작업파일/공공기관2/12.한국철도공사/한국철도공사.xlsx'
BASE='https://info.korail.com'
BLUE=PatternFill(fill_type='solid', fgColor='FFBDD7EE', bgColor='FFBDD7EE')
ts=json.load(open(r'작업파일/공공기관2/12.한국철도공사/_tabscan.json',encoding='utf-8'))
EXPAND=[6,8,15,30,33,34,37,38,39,40,45,46,47,74,78,79,80,82,86,92,93,94,102,104,105,106]
IMG=set('719 720 730 769 781 783 785 799 871 872 894 899 900 901 902 906 907 908 970 2950 2951 2952 2977 1461 1462 1463 1464 1641 1303 1541 1503 1504 2730 1505 2731 1507 1508 2732 1510 1511'.split())
def nfor(key):
return '어문,이미지' if str(key) in IMG else '어문'
mt0=os.path.getmtime(P)
shutil.copy2(P, P.replace('.xlsx', f'_backup_{int(mt0)}.xlsx'))
wb=openpyxl.load_workbook(P)
ws=wb.active
# merge-fill map cols 4-10
fill={}
for m in list(ws.merged_cells.ranges):
v=ws.cell(m.min_row,m.min_col).value
for rr in range(m.min_row,m.max_row+1):
for cc in range(m.min_col,m.max_col+1):
fill[(rr,cc)]=v
def eff(r,c):
return fill.get((r,c), ws.cell(r,c).value)
# capture template styles per column from a clean data row (row 4)
TPL={}
for c in range(2,28):
cell=ws.cell(4,c)
TPL[c]=(copy(cell.font),copy(cell.border),copy(cell.fill),copy(cell.alignment),copy(cell.number_format))
# K hyperlink template style (font/color)
KSTYLE=(copy(ws.cell(3,11).font),copy(ws.cell(3,11).border),copy(ws.cell(3,11).fill),copy(ws.cell(3,11).alignment))
Cval=ws.cell(3,3).value # 사이트명
# Build records: list of dicts col->value, plus 'blue' set of cols, plus 'hl' url
records=[]
for r in range(3, ws.max_row+1):
base={}
for c in range(3,28): # C..AA (B renumbered later)
if 4<=c<=10:
base[c]=eff(r,c)
else:
base[c]=ws.cell(r,c).value
hl=ws.cell(r,11).hyperlink.target if ws.cell(r,11).hyperlink else (base[11] if base[11] else None)
if r in EXPAND:
leafcol=6 # F
tabs=ts[str(r)]['tabs']
# self tab = active (first); reuse this row but add G label + url stays
for i,t in enumerate(tabs):
rec=dict(base)
key=t['href'].split('key=')[-1]
url=BASE+t['href']
rec[7]=t['label'] # G
rec[11]=url # K value
rec['_hl']=url
rec[12]='페이지' # L
rec[13]=1 # M
rec[14]=nfor(key) # N
rec[15]='미부착' # O
rec['_blue']={7,11,12,13,14,15}
if i>0:
# new row: clear D,E,F values (merge covers) - keep for run-length; keep eff values
rec[16]=None; rec[17]=None # P,Q clear for new
for cc in range(18,28): rec[cc]=None # R-AA clear
records.append(rec)
else:
rec=dict(base); rec['_hl']=hl; rec['_blue']=set()
records.append(rec)
# Now rewrite sheet: clear merges + data region
for m in list(ws.merged_cells.ranges):
ws.unmerge_cells(str(m))
maxr=ws.max_row
for r in range(3, maxr+1):
for c in range(1,28):
cell=ws.cell(r,c); cell.value=None; cell.hyperlink=None
# write records
import re
for idx,rec in enumerate(records):
r=3+idx
ws.cell(r,2).value=idx+1 # B renumber
# apply template style to all cols
for c in range(2,28):
f,b,fl,al,nf=TPL[c]
cell=ws.cell(r,c)
cell.font=copy(f); cell.border=copy(b); cell.fill=copy(fl); cell.alignment=copy(al); cell.number_format=nf
for c in range(3,28):
ws.cell(r,c).value=rec.get(c)
# K hyperlink
url=rec.get('_hl')
if url and isinstance(url,str) and url.startswith('http'):
kc=ws.cell(r,11)
kc.hyperlink=url
kf,kb,kfl,kal=KSTYLE
kc.font=copy(kf)
# blue highlights
for c in rec.get('_blue',()):
ws.cell(r,c).fill=copy(BLUE)
nrows=len(records)
last=3+nrows-1
# snapshot of effective values BEFORE merging (merged cells read back as None)
SNAP={}
for idx,rec in enumerate(records):
rr=3+idx
for c in range(4,11):
SNAP[(rr,c)]=rec.get(c)
# run-length merges for cols D(4)..J(10)
def val(r,c): return SNAP.get((r,c))
for c in range(4,11):
r=3
while r<=last:
v=val(r,c)
if v is None:
r+=1; continue
# ancestor tuple
def anctup(rr):
return tuple(val(rr,cc) for cc in range(4,c))
a0=anctup(r)
r2=r
while r2+1<=last and val(r2+1,c)==v and anctup(r2+1)==a0:
r2+=1
if r2>r:
ws.merge_cells(start_row=r,start_column=c,end_row=r2,end_column=c)
r=r2+1
# mtime guard + save
if os.path.getmtime(P)!=mt0:
print('ABORT mtime moved'); sys.exit(2)
try:
wb.save(P)
except PermissionError as e:
print('ABORT-PERM (close Excel)', e); sys.exit(3)
print('OK rows', nrows, '(was', maxr-2, ') new', nrows-(maxr-2))