DB_JOB/작업파일/_dupname_sweep.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

77 lines
2.7 KiB
Python

# -*- coding: utf-8 -*-
import openpyxl, io, os, glob
from collections import defaultdict
ROOT=r"D:\01.프로젝트\DB수집"
out=io.open(r"D:\01.프로젝트\DB수집\작업파일\_dupname_sweep_out.txt","w",encoding="utf-8")
def w(*a): out.write(" ".join(str(x) for x in a)+"\n")
SKIP_DIR=("_backup","backup","_temp","제출폴더","_스크립트","_nshots","_naudit","_shots",".git")
SKIP_NAME=("backup","conflicted","_작업현황","작업현황","_취합_예시","자료_취합","예시","~$")
def is_target(p):
pl=p.replace("/","\\")
for s in SKIP_DIR:
if "\\"+s in pl or "\\"+s+"\\" in pl: return False
base=os.path.basename(p)
for s in SKIP_NAME:
if s in base: return False
return base.endswith(".xlsx")
files=[]
for dp,dn,fn in os.walk(ROOT):
# prune skip dirs
dn[:]=[d for d in dn if d not in SKIP_DIR and "backup" not in d.lower()]
for f in fn:
p=os.path.join(dp,f)
if is_target(p): files.append(p)
w("scanned candidate files:",len(files));w("")
def eff_leaf_dups(ws):
eff={}
for r in range(3,ws.max_row+1):
for c in range(4,11):
eff[(r,c)]=ws.cell(r,c).value
for mr in ws.merged_cells.ranges:
if mr.min_col>=4 and mr.max_col<=10:
v=ws.cell(mr.min_row,mr.min_col).value
for r in range(mr.min_row,mr.max_row+1):
for c in range(mr.min_col,mr.max_col+1):
eff[(r,c)]=v
byleaf=defaultdict(list)
for r in range(3,ws.max_row+1):
# skip empty rows
path=[str(eff[(r,c)]).strip() for c in range(4,11) if eff[(r,c)] not in (None,"")]
if not path: continue
byleaf[path[-1]].append(r)
return {k:v for k,v in byleaf.items() if len(v)>1}
summary=[]
for p in sorted(files):
try:
wb=openpyxl.load_workbook(p,read_only=False,data_only=True)
except Exception as e:
w("LOADERR",p,e); continue
ws=wb.active
if ws.max_row<3:
wb.close(); continue
dups=eff_leaf_dups(ws)
rel=os.path.relpath(p,ROOT)
ngroups=len(dups); nduprows=sum(len(v) for v in dups.values())
summary.append((ngroups,nduprows,rel,dups,ws.max_row))
wb.close()
summary.sort(reverse=True)
w("=== FILES WITH DUPLICATE MENU NAMES (sorted by #groups) ===")
for ng,nr,rel,dups,mx in summary:
if ng==0: continue
w(f"\n[{ng} groups / {nr} rows] {rel} (max_row={mx})")
for nm,rs in sorted(dups.items(), key=lambda x:-len(x[1])):
w(f" '{nm}' x{len(rs)} rows={rs}")
clean=[s for s in summary if s[0]==0]
w("\n=== FILES WITH NO DUPLICATE MENU NAMES ===",len(clean))
for ng,nr,rel,dups,mx in clean:
w(" OK",rel)
out.close()
print("done; files:",len(files),"with dups:",sum(1 for s in summary if s[0]>0))