공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
128 lines
5.2 KiB
Python
128 lines
5.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""규칙 B 전 사이트 적용: F 하나에 G가 여러 개이고 그 G들이 전부 L=페이지면
|
|
→ 1행으로 합치고(G/H/I/J 비움), K=첫 G URL, 수량(M)=G들의 M 합. (공주시와 동일)
|
|
|
|
안전장치:
|
|
· G 중 하나라도 페이지가 아니면(게시판/사이트) 합치지 않음.
|
|
· 합칠 때 공공누리: O유형=그룹 합집합(숫자 오름차순,콤마,공백없음), Q=하나라도 Y면 Y,
|
|
P=게시판 우선(없으면 게시물). 부착 정보 손실 방지하며 합침.
|
|
· G가 잎일 때만(H/I/J 비어있음). 더 깊은 중첩은 건드리지 않음.
|
|
|
|
공주시(완료)·계룡시(검수완료)는 제외.
|
|
|
|
사용: python -X utf8 _collapse_all.py dry [기관...]
|
|
python -X utf8 _collapse_all.py run [기관...]
|
|
"""
|
|
import os, re, sys, shutil, importlib.util, warnings
|
|
import openpyxl
|
|
warnings.filterwarnings('ignore')
|
|
|
|
TYPE_PAT = re.compile(r'(\d)\s*유형')
|
|
|
|
|
|
def merge_kogl(grp):
|
|
"""그룹 G행들의 O/P/Q 통합. 반환 (O, P, Q)."""
|
|
types = set()
|
|
for g in grp:
|
|
o = g['vals'].get(15)
|
|
if isinstance(o, str):
|
|
for m in TYPE_PAT.finditer(o):
|
|
types.add(int(m.group(1)))
|
|
if types:
|
|
O = ','.join(f'{n}유형' for n in sorted(types))
|
|
else:
|
|
O = '미부착'
|
|
Ps = [g['vals'].get(16) for g in grp]
|
|
P = '게시판' if '게시판' in Ps else ('게시물' if '게시물' in Ps else None)
|
|
Qs = [g['vals'].get(17) for g in grp]
|
|
Q = 'Y' if 'Y' in Qs else ('N' if 'N' in Qs else None)
|
|
return O, (P if O != '미부착' else None), (Q if O != '미부착' else None)
|
|
|
|
spec = importlib.util.spec_from_file_location('dd', __file__.replace('_collapse_all.py', '_dedup_all.py'))
|
|
dd = importlib.util.module_from_spec(spec); spec.loader.exec_module(dd)
|
|
|
|
EXCLUDE = {'공주시', '계룡시'}
|
|
|
|
|
|
def mval(x):
|
|
try:
|
|
return int(x)
|
|
except Exception:
|
|
return 1
|
|
|
|
|
|
def collapse(rows):
|
|
out, groups, held = [], [], []
|
|
i, n = 0, len(rows)
|
|
while i < n:
|
|
v = rows[i]['vals']
|
|
D, E, F, G = v.get(4), v.get(5), v.get(6), v.get(7)
|
|
if F not in (None, '') and G not in (None, ''):
|
|
j = i
|
|
while (j < n and rows[j]['vals'].get(4) == D and rows[j]['vals'].get(5) == E
|
|
and rows[j]['vals'].get(6) == F and rows[j]['vals'].get(7) not in (None, '')):
|
|
j += 1
|
|
grp = rows[i:j]
|
|
all_page = all(g['vals'].get(12) == '페이지' for g in grp)
|
|
leaf = all(all(g['vals'].get(c) in (None, '') for c in (8, 9, 10)) for g in grp)
|
|
has_attach = any(g['vals'].get(15) not in (None, '', '미부착') for g in grp)
|
|
if len(grp) >= 2 and all_page and leaf:
|
|
msum = sum(mval(g['vals'].get(13)) for g in grp)
|
|
O, P, Q = merge_kogl(grp)
|
|
first = dict(grp[0]); nv = dict(first['vals'])
|
|
for c in (7, 8, 9, 10):
|
|
nv[c] = None
|
|
nv[13] = msum
|
|
nv[15] = O; nv[16] = P; nv[17] = Q
|
|
first['vals'] = nv
|
|
out.append(first)
|
|
groups.append({'E': E, 'F': F, 'n': len(grp), 'sum': msum, 'O': O})
|
|
if has_attach:
|
|
held.append({'E': E, 'F': F, 'O': O})
|
|
i = j
|
|
continue
|
|
out.extend(grp); i = j; continue
|
|
out.append(rows[i]); i += 1
|
|
return out, groups, held
|
|
|
|
|
|
def main():
|
|
mode = sys.argv[1] if len(sys.argv) > 1 else 'dry'
|
|
only = set(a for a in sys.argv[2:] if not a.startswith('--'))
|
|
sites = [s for s in dd.SITES if s[2] not in EXCLUDE and (not only or s[2] in only)]
|
|
print(f'대상 기관: {len(sites)}개 (공주·계룡 제외) 모드={mode}\n')
|
|
print(f'{"기관":<8}{"현재":>6}{"합친그룹":>7}{"제거행":>6}{"→남음":>7}{"부착합침":>7}')
|
|
print('-' * 55)
|
|
grand_g = grand_r = grand_h = 0
|
|
attach_detail = []
|
|
for prov, idx, name in sites:
|
|
xp = dd.xpath(prov, idx, name)
|
|
if not os.path.exists(xp):
|
|
print(f'{name:<8} 엑셀 없음'); continue
|
|
wb = openpyxl.load_workbook(xp); ws = wb.active
|
|
rows = dd.load_flat(ws)
|
|
out, groups, held = collapse(rows)
|
|
removed = len(rows) - len(out)
|
|
grand_g += len(groups); grand_r += removed; grand_h += len(held)
|
|
print(f'{name:<8}{len(rows):>6}{len(groups):>7}{removed:>6}{len(out):>7}{len(held):>7}')
|
|
for h in held:
|
|
attach_detail.append((name, h['E'], h['F'], h['O']))
|
|
if mode == 'run' and groups:
|
|
bak = xp.replace('.xlsx', '_backup_collapse전.xlsx')
|
|
shutil.copy(xp, bak)
|
|
dd.write_back(ws, out)
|
|
try:
|
|
wb.save(xp)
|
|
except PermissionError:
|
|
wb.save(xp.replace('.xlsx', '_LP.xlsx')); print(f' !! {name} 잠김→_LP')
|
|
print('-' * 55)
|
|
print(f'합계: 합친그룹 {grand_g} / 제거행 {grand_r} / 부착합침 {grand_h} ({mode})')
|
|
if attach_detail:
|
|
print(f'\n=== 부착 유형 합쳐진 그룹 {len(attach_detail)}개 (O 결과 확인용) ===')
|
|
for nm, E, F, O in attach_detail:
|
|
print(f' [{nm}] {E} > {F} → O={O}')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|