# -*- coding: utf-8 -*- import openpyxl, sys from openpyxl.utils import get_column_letter sys.stdout.reconfigure(encoding='utf-8') new=openpyxl.load_workbook('_충청남도_서천군_NEW.xlsx').active old=openpyxl.load_workbook('충청남도_서천군_backup_탭전개전.xlsx').active print('=== hyperlink mismatches ===') for r in range(3,new.max_row+1): c=new.cell(r,11); L=new.cell(r,12).value if L in ('페이지','게시판','사이트') and c.hyperlink: if isinstance(c.value,str) and c.value.strip()!=c.hyperlink.target.strip(): print(f' R{r} L={L} val={c.value[:45]} tgt={c.hyperlink.target[:45]}') # L type counts old vs new from collections import Counter def lc(ws): return Counter(ws.cell(r,12).value for r in range(3,ws.max_row+1) if ws.cell(r,12).value) print('OLD L counts:', dict(lc(old))) print('NEW L counts:', dict(lc(new))) # 분야별이행기준 group size for r in range(3,new.max_row+1): if new.cell(r,6).value=='분야별이행기준': cnt=0 for k in range(r, r+40): if new.cell(k,6).value and k>r and new.cell(k,6).value!='분야별이행기준': break if new.cell(k,7).value or new.cell(k,6).value=='분야별이행기준': cnt+=1 print(f'분야별이행기준 @R{r}, first G={new.cell(r,7).value}, last few:') for k in range(r, r+28): g=new.cell(k,7).value; f=new.cell(k,6).value if f and f!='분야별이행기준' and k>r: break # show merge fm=[str(m) for m in new.merged_cells.ranges if m.min_col==6 and m.min_row==r] print(' F-merge:', fm) break # site row preserved? print('=== site rows sample (new) ===') sc=0 for r in range(3,new.max_row+1): if new.cell(r,12).value=='사이트': sc+=1 if sc<=3: print(f' R{r} F={new.cell(r,6).value} M={new.cell(r,13).value} N={new.cell(r,14).value} link={new.cell(r,11).hyperlink.target[:40] if new.cell(r,11).hyperlink else None}') print('site count new:', sc) # verify total D/E merge integrity: every data row covered by a D value (merge-top or own) missingD=0 dranges=[m for m in new.merged_cells.ranges if m.min_col==4] covered=set() for m in dranges: for rr in range(m.min_row,m.max_row+1): covered.add(rr) for r in range(3,new.max_row+1): if new.cell(r,4).value is None and r not in covered: missingD+=1 print('rows with no D coverage:', missingD)