Create DPM compare script and updated DPM Netwrok table script

This commit is contained in:
gigi.mamaladze 2025-12-12 19:44:06 +04:00
parent 7a8cd2a763
commit 3582a67422
12 changed files with 554 additions and 6 deletions

Binary file not shown.

View File

@ -0,0 +1,225 @@
#!/usr/bin/env python3
"""
Script to compare device lists from two Excel files.
- File 1: Extract all values from P_TAG1 column
- File 2: Extract all devices, ignoring those containing "SPARE"
- Output: Excel file with all devices and a YES/NO column indicating if device is in both files
"""
import argparse
import sys
import pandas as pd
from pathlib import Path
def extract_from_p_tag1_file(file_path, sheet_name=0):
"""
Extract all device values from the P_TAG1 column.
Args:
file_path: Path to Excel file with P_TAG1 column
sheet_name: Sheet name or index to read
Returns:
List of device names (preserving original case)
"""
try:
df = pd.read_excel(file_path, sheet_name=sheet_name)
# Find P_TAG1 column
if 'P_TAG1' not in df.columns:
print(f"Error: Column 'P_TAG1' not found in '{file_path}'")
print(f"Available columns: {list(df.columns)}")
sys.exit(1)
# Extract all values from P_TAG1 column, preserving original case
devices = df['P_TAG1'].dropna().astype(str).str.strip()
devices = devices[devices != ''].tolist()
return devices
except FileNotFoundError:
print(f"Error: File '{file_path}' not found.")
sys.exit(1)
except Exception as e:
print(f"Error reading '{file_path}': {e}")
sys.exit(1)
def extract_from_devices_file(file_path, sheet_name=0):
"""
Extract all devices from file, ignoring those containing "SPARE".
Args:
file_path: Path to Excel file with device list
sheet_name: Sheet name or index to read
Returns:
List of device names (preserving original case)
"""
try:
df = pd.read_excel(file_path, sheet_name=sheet_name)
# Get all values from first column (assuming devices are in first column)
devices = df.iloc[:, 0].dropna().astype(str).str.strip()
devices = devices[devices != ''].tolist()
# Also check if column name itself is a device (if it looks like a device name)
column_name = str(df.columns[0]).strip()
column_lower = column_name.lower()
# If column name looks like a device (contains underscore, not "P_TAG1"), add it
if '_' in column_name and len(column_name) > 3 and column_lower != 'p_tag1':
if column_name not in devices:
devices.append(column_name)
# Filter out devices containing "SPARE" (case-insensitive)
filtered_devices = []
for device in devices:
device_lower = device.lower()
if 'spare' not in device_lower:
filtered_devices.append(device)
return filtered_devices
except FileNotFoundError:
print(f"Error: File '{file_path}' not found.")
sys.exit(1)
except Exception as e:
print(f"Error reading '{file_path}': {e}")
sys.exit(1)
def compare_and_create_output(file1_path, file2_path, output_path, sheet1=0, sheet2=0):
"""
Compare device lists and create Excel output file.
Args:
file1_path: Path to file with P_TAG1 column
file2_path: Path to file with device list
output_path: Path to output Excel file
sheet1: Sheet name or index for first file
sheet2: Sheet name or index for second file
"""
# Get file names (without path) for column headers
file1_name = Path(file1_path).name
file2_name = Path(file2_path).name
print(f"Reading '{file1_path}' (looking for P_TAG1 column)...")
devices1 = extract_from_p_tag1_file(file1_path, sheet_name=sheet1)
print(f" Found {len(devices1)} devices in P_TAG1 column")
print(f"Reading '{file2_path}' (extracting all devices, ignoring SPARE)...")
devices2 = extract_from_devices_file(file2_path, sheet_name=sheet2)
print(f" Found {len(devices2)} devices (after filtering SPARE)")
# Create sets for case-insensitive comparison
devices1_lower = {d.lower(): d for d in devices1}
devices2_lower = {d.lower(): d for d in devices2}
# Get all unique devices (combining both lists, preserving original case)
all_devices_lower = set(devices1_lower.keys()) | set(devices2_lower.keys())
# Create result list with original case
result_data = []
for device_lower in sorted(all_devices_lower):
# Get original case (prefer from file1, then file2)
if device_lower in devices1_lower:
device_original = devices1_lower[device_lower]
else:
device_original = devices2_lower[device_lower]
# Check if device is in each file (case-insensitive)
in_file1 = device_lower in devices1_lower
in_file2 = device_lower in devices2_lower
in_both = in_file1 and in_file2
result_data.append({
'Device': device_original,
file1_name: "YES" if in_file1 else "NO",
file2_name: "YES" if in_file2 else "NO",
'In Both Files': "YES" if in_both else "NO"
})
# Create DataFrame
result_df = pd.DataFrame(result_data)
# Validate output file extension
output_path_obj = Path(output_path)
if output_path_obj.suffix.lower() not in ['.xlsx', '.xls']:
# If no extension or wrong extension, add .xlsx
if not output_path_obj.suffix:
output_path = str(output_path_obj) + '.xlsx'
print(f"Note: Output file extension added: {output_path}")
else:
print(f"Warning: Output file should be .xlsx format. Converting to .xlsx")
output_path = str(output_path_obj.with_suffix('.xlsx'))
# Write to Excel
try:
# Ensure openpyxl is available
try:
import openpyxl
except ImportError:
print("Error: openpyxl library is required. Install it with: pip install openpyxl")
sys.exit(1)
result_df.to_excel(output_path, index=False, engine='openpyxl')
print(f"\nOutput saved to: {output_path}")
print(f"Total devices: {len(result_df)}")
print(f"Devices in both files: {len(result_df[result_df['In Both Files'] == 'YES'])}")
print(f"Devices only in one file: {len(result_df[result_df['In Both Files'] == 'NO'])}")
print(f"\nColumns in output file:")
print(f" - Device: Device name")
print(f" - {file1_name}: YES if device is in this file")
print(f" - {file2_name}: YES if device is in this file")
print(f" - In Both Files: YES if device is in both files")
except Exception as e:
print(f"Error writing to Excel file: {e}")
print(f"Make sure the output path is valid and you have write permissions.")
sys.exit(1)
def main():
parser = argparse.ArgumentParser(
description='Compare device lists from two Excel files and create Excel output',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python check_dpm_devices.py file1.xlsx file2.xlsx output.xlsx
python check_dpm_devices.py file1.xlsx file2.xlsx output.xlsx --sheet1 "Sheet1" --sheet2 "Sheet2"
"""
)
parser.add_argument('file1', type=str,
help='Path to first Excel file (must have P_TAG1 column)')
parser.add_argument('file2', type=str,
help='Path to second Excel file (device list, SPARE devices will be ignored)')
parser.add_argument('output', type=str,
help='Path to output Excel file (must be .xlsx format)')
parser.add_argument('--sheet1', type=str, default=0,
help='Sheet name or index for first file (default: 0)')
parser.add_argument('--sheet2', type=str, default=0,
help='Sheet name or index for second file (default: 0)')
args = parser.parse_args()
# Validate files exist
if not Path(args.file1).exists():
print(f"Error: File '{args.file1}' does not exist.")
sys.exit(1)
if not Path(args.file2).exists():
print(f"Error: File '{args.file2}' does not exist.")
sys.exit(1)
# Compare and create output
compare_and_create_output(
args.file1,
args.file2,
args.output,
sheet1=args.sheet1,
sheet2=args.sheet2
)
if __name__ == '__main__':
main()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -162,9 +162,12 @@ def generate_rows(unique_dpms, assign, rating_map, net2_dpms):
for dpm in unique_dpms:
ring_ip = ring_ip_map[dpm]
tags = assign.get(dpm, [])
tags = tags[:24] + ["SPARE"] * (24 - len(tags[:24]))
for idx, port in enumerate(range(5, 29)):
# Generate ports starting from 5, continuing beyond 28 if needed
num_devices = len(tags)
ports = list(range(5, 5 + num_devices))
for idx, port in enumerate(ports):
dev = tags[idx]
pn = part_number_for(dev, rating_map)
@ -201,6 +204,7 @@ def write_sheet(ws, rows, title):
)
yellow = PatternFill("solid", fgColor="FFC000")
red = PatternFill("solid", fgColor="FF0000")
thin = Side(style="thin", color="000000")
border = Border(left=thin, right=thin, top=thin, bottom=thin)
center = Alignment(horizontal="center", vertical="center")
@ -218,11 +222,10 @@ def write_sheet(ws, rows, title):
for dpm, group in groupby(rows, key=lambda x: x[0]):
g = list(group)
# should already be 24 rows per DPM
g = g[:24]
num_rows = len(g)
start = row_idx
end = row_idx + 24 - 1
end = row_idx + num_rows - 1
ws.merge_cells(start_row=start, start_column=4, end_row=end, end_column=4)
ws.merge_cells(start_row=start, start_column=5, end_row=end, end_column=5)
@ -235,17 +238,23 @@ def write_sheet(ws, rows, title):
cell.border = border
cell.font = Font(bold=False)
for i in range(24):
for i in range(num_rows):
row_vals = {
6: g[i][2], # Assigned Device
7: g[i][3], # Part Number
8: g[i][4], # IP
9: g[i][5], # DPM PORT
}
# Highlight rows beyond 24th device in red
is_overflow = i >= 24
fill_color = red if is_overflow else None
for col, val in row_vals.items():
c = ws.cell(row=start + i, column=col, value=val)
c.alignment = left if col in (6, 7, 9) else center
c.border = border
if fill_color:
c.fill = fill_color
for r in range(start + 1, end + 1):
for col in (4, 5):

314
AutoCAD/RenAttrib.LSP Normal file
View File

@ -0,0 +1,314 @@
;;; Rename Attributes by Irné Barnard
;;; Version 3
(vl-load-com)
(defun RenAtt:LoadSettings (filename / f s lst)
(if (and (or (setq f (findfile (cond (filename)
("RenAttrib.DAT"))))
(setq f (findfile (strcat (getvar "RoamableRootPrefix") "RenAttrib.DAT"))))
(setq f (open f "r")))
(progn
(setq lst "")
(while (setq s (read-line f)) (setq lst (strcat lst "\n" s)))
(setq lst (read lst))
(close f)))
(setq *RenAtt:Settings* lst))
(RenAtt:LoadSettings nil)
(defun RenAtt:SaveSettings (filename / f)
(setq f (cond (filename)
((findfile "RenAttrib.DAT"))
((strcat (getvar "RoamableRootPrefix") "RenAttrib.DAT"))))
(if (setq f (open f "w"))
(progn
(prin1 *RenAtt:Settings* f)
(close f))))
;; Get ALL (even duplicate) attributes from a block reference
(defun RenAtt:GetAttributes (obj / an ao lst)
(setq an (vlax-vla-object->ename obj))
(while (and (setq an (entnext an))
(setq ao (vlax-ename->vla-object an))
(eq (vla-get-ObjectName ao) "AcDbAttribute"))
(setq lst (cons ao lst)))
lst)
(defun RenAtt:GetBlocks (/ lst item name attList attTest attName changed)
(or *AcadApp* (setq *AcadApp* (vlax-get-acad-object)))
(or *ActiveDocument* (setq *ActiveDocument* (vla-get-ActiveDocument *AcadApp*)))
(or *BlocksCollection* (setq *BlocksCollection* (vla-get-Blocks *ActiveDocument*)))
;; Get attributes from block definitions
(vlax-for blk *BlocksCollection*
(if (wcmatch (setq name (vla-get-Name blk)) "~`**")
(progn
(setq item nil)
(vlax-for obj blk
(if (eq (vla-get-ObjectName obj) "AcDbAttributeDefinition")
(if (setq attTest (assoc (setq attName (strcase (vla-get-TagString obj))) item))
(setq item (subst (cons attName (1+ (cdr attTest))) attTest item))
(setq item (cons (cons attName 1) item)))))
(if item
(setq lst (cons (cons (strcase name) (reverse item)) lst))))))
;; Get attributes from block references
(vlax-for blk *BlocksCollection*
(vlax-for obj blk
(if (and (eq (vla-get-ObjectName obj) "AcDbBlockReference") (eq (vla-get-HasAttributes obj) :vlax-true))
(progn
(setq attList nil)
(foreach att (vlax-invoke obj "GetAttributes")
(if (and (setq attName (strcase (vla-get-TagString att))) (setq attTest (assoc attName attList)))
(setq attList (subst (cons attName (1+ (cdr attTest))) attTest attList))
(setq attList (cons (cons attName 1) attList))))
(setq name (strcase (vla-get-EffectiveName obj))
item (reverse (cdr (assoc name lst)))
attName nil)
(foreach att (reverse attList)
(if (setq attTest (assoc (setq attName (car att)) item))
(if (> (cdr att) (cdr attTest))
(setq changed t
item (subst att attTest item)))
(setq changed t
item (cons att item))))
;; Merge into block definition list
(if changed
(setq lst (subst (cons name (reverse item)) (assoc name lst) lst)))))))
(reverse lst))
(defun RenAtt:MergeData (Settings NewData / old old2 attOld len)
(foreach item NewData
(if (setq old2 (setq old (assoc (car item) Settings)))
(foreach att (cdr item)
(if (setq attOld (assoc (car att) (cdr old)))
(if (> (cdr att) (setq len (1- (length attOld))))
(setq Settings
(subst
(setq old (subst (append attOld (_MakeList (car att) (- (cdr att) len))) attOld old))
old2
Settings)
old2 old))
;;Some error here
(setq Settings (subst (append old (list (cons (car att) (_MakeList (car att) (cdr att))))) old Settings))))
(setq Settings
(append
Settings
(list
(cons (car item)
(mapcar (function (lambda (attName) (list attName attName)))
(apply 'append (mapcar (function (lambda (a) (_MakeList (car a) (cdr a)))) (cdr item))))))))))
Settings)
(defun _MakeList (val count / lst) (repeat count (setq lst (cons val lst))))
(defun _FirstN (lst num / res)
(if (< num (length lst))
(progn
(repeat num
(setq res (cons (car lst) res)
lst (cdr lst)))
(reverse res))
lst))
(defun _CdrN (lst num /) (repeat num (setq lst (cdr lst))))
(defun _ReplaceN (val idx lst /)
(if (< idx 0)
(cons val lst)
(append (_FirstN lst idx) (list val) (_CdrN lst (1+ idx)))))
(defun _RemoveN (lst idx /)
(if (< idx 0)
(cons val lst)
(append (_FirstN lst idx) (_CdrN lst (1+ idx)))))
(defun RenAttr (obj / setting found)
(cond
((and (eq (vla-get-ObjectName obj) "AcDbBlockReference")
(eq (vla-get-HasAttributes obj) :vlax-true)
(setq setting (assoc (strcase (vla-get-EffectiveName obj)) *RenAtt:Settings*)))
(setq setting (cdr setting))
(foreach att (vlax-invoke obj "GetAttributes")
(if (setq found (assoc (strcase (vla-get-TagString att)) setting))
(progn
(setq setting (_RemoveN setting (vl-position found setting)))
(if (not (eq (car found) (cadr found)))
(vla-put-TagString att (cadr found)))))))
((and (eq (vla-get-ObjectName obj) "AcDbBlockTableRecord")
(setq setting (assoc (strcase (vla-get-Name obj)) *RenAtt:Settings*)))
(setq setting (cdr setting))
(vlax-for att obj
(if (and (eq (vla-get-ObjectName att) "AcDbAttributeDefinition")
(setq found (assoc (strcase (vla-get-TagString att)) setting)))
(progn
(setq setting (_RemoveN setting (vl-position found setting)))
(if (not (eq (car found) (cadr found)))
(vla-put-TagString att (cadr found)))))))))
(defun c:RenAttr (/)
(or *AcadApp* (setq *AcadApp* (vlax-get-acad-object)))
(or *ActiveDocument* (setq *ActiveDocument* (vla-get-ActiveDocument *AcadApp*)))
(or *BlocksCollection* (setq *BlocksCollection* (vla-get-Blocks *ActiveDocument*)))
;; Get attributes from block definitions
(vlax-for blk *BlocksCollection*
(if (wcmatch (vla-get-Name blk) "~`**")
(RenAttr blk))
(vlax-for obj blk (RenAttr obj)))
(princ))
(defun c:RenAttrSet (/ dcl s Blocks Settings ~btnCurrentAdd ~btnCurrentRem ~lstBlocks ~lstAttribs ~btnSave)
(if
(and (setq dcl (open (setq s (strcat (getvar "TempPrefix") "RenAttrib.DCL")) "w"))
(princ
(strcat
"RenAttrSet : dialog {\n"
" label = \"Rename Attributes - Settings\";\n"
" : row {\n"
" : boxed_column {\n"
" label = \"Blocks in current Drawing\";\n"
" : list_box { height = 20; key = \"lstCurrent\"; width = 30; multiple_select = true; }\n"
" : column {\n"
" : button { label = \"Add to Settings\"; key = \"btnCurrentAdd\"; }\n"
" : button { label = \"Remove from Settings\"; key = \"btnCurrentRem\"; }\n"
" }\n"
" }\n"
" : boxed_column {\n"
" label = \"Settings\";\n"
" :row { : column {\n"
" : list_box { label = \"Block Names\"; key = \"lstBlocks\"; width = 30; height = 20; }\n"
" : edit_box { label = \"New Name\"; key = \"edtName\"; edit_width = 25; }\n"
" }\n"
" : column {\n"
" : list_box { label = \"Old Attribute Names\"; key = \"lstAttribs\"; width = 30; height = 20; }\n"
" : retirement_button { key = \"btnSave\"; label = \" Save \"; }\n"
" }}\n"
" : row {\n"
" fixed_width = true;\n"
" alignment = centered;\n"
" : button { label = \"Clear\"; key = \"clear\"; action = \"(done_dialog 2)\"; }\n"
" : spacer { width = 2; }\n"
" ok_button;\n"
" : spacer { width = 2; }\n"
" cancel_button;\n"
" }\n"
" }\n"
" }\n"
"}")
dcl)
(not (close dcl))
(setq dcl (load_dialog s))
(new_dialog "RenAttrSet" dcl))
(progn
;; Action on button "Add to Settings" clicked
(defun ~btnCurrentAdd (/ idx)
(if (not (eq (setq idx (get_tile "lstCurrent")) ""))
(progn
(setq idx (mapcar (function (lambda (n) (nth n Blocks))) (read (strcat "(" idx ")")))
Settings (RenAtt:MergeData Settings idx))
(start_list "lstBlocks")
(mapcar 'add_list (mapcar 'car Settings))
(end_list)
(set_tile "lstBlocks" "")
(~lstBlocks))))
;; Action on button "Add to Settings" clicked
(defun ~btnCurrentRem (/ idx)
(if (not (eq (setq idx (get_tile "lstCurrent")) ""))
(progn
(setq idx (mapcar (function (lambda (n) (nth n Blocks))) (read (strcat "(" idx ")"))))
(foreach i idx
(setq i (assoc (car i) Settings)
Settings (vl-remove i Settings)))
(start_list "lstBlocks")
(mapcar 'add_list (mapcar 'car Settings))
(end_list)
(set_tile "lstBlocks" "")
(~lstBlocks))))
;; Action on selection "Block Names" changed
(defun ~lstBlocks (/ idx)
(if (not (eq (setq idx (get_tile "lstBlocks")) ""))
(progn
(start_list "lstAttribs")
(mapcar 'add_list
(mapcar
(function
(lambda (att)
(if (eq (car att) (cadr att))
(car att)
(strcat (car att) " <" (cadr att) ">"))))
(cdr (nth (atoi idx) Settings))))
(end_list)
(mode_tile "lstAttribs" 0)
(set_tile "lstAttribs" ""))
(progn
(start_list "lstAttribs")
(setq idxLst nil)
(end_list)
(mode_tile "lstAttribs" 1)
(set_tile "lstAttribs" "")))
(~lstAttribs))
;; Action on selection "Old Attribute Names" changed
(defun ~lstAttribs (/ idx1 idx2 blk att)
(if (and (not (eq (setq idx1 (get_tile "lstBlocks")) ""))
(not (eq (setq idx2 (get_tile "lstAttribs")) ""))
(setq blk (nth (atoi idx1) Settings))
(setq att (nth (atoi idx2) (cdr blk))))
(progn
(set_tile "edtName" (cadr att))
(mode_tile "edtName" 0)
(mode_tile "btnSave" 0))
(progn
(set_tile "edtName" "")
(mode_tile "edtName" 1)
(mode_tile "btnSave" 1))))
;; Action on button "Save" clicked
(defun ~btnSave (/ idx1 idx2 blk att)
(if (and (not (eq (setq idx1 (get_tile "lstBlocks")) ""))
(not (eq (setq idx2 (get_tile "lstAttribs")) ""))
(setq idx1 (atoi idx1)
idx2 (atoi idx2))
(setq blk (nth idx1 Settings))
(setq att (nth idx2 (cdr blk))))
(progn
(setq Settings
(subst (cons (car blk)
(_ReplaceN (list (car att) (strcase (get_tile "edtName"))) idx2 (cdr blk)))
blk
Settings))
(~lstBlocks)
(set_tile "lstAttribs" (itoa idx2))
(~lstAttribs))))
(start_list "lstCurrent")
(mapcar 'add_list (mapcar 'car (setq Blocks (RenAtt:GetBlocks))))
(end_list)
(setq Settings *RenAtt:Settings*)
(start_list "lstBlocks")
(mapcar 'add_list (mapcar 'car Settings))
(end_list)
(action_tile "btnCurrentAdd" "(~btnCurrentAdd)")
(action_tile "btnCurrentRem" "(~btnCurrentRem)")
(action_tile "lstBlocks" "(~lstBlocks)")
(action_tile "lstBlocks" "(~lstBlocks)")
(action_tile "lstAttribs" "(~lstAttribs)")
(action_tile "btnSave" "(~btnSave)")
(cond
((= (setq s (start_dialog)) 1)
(setq *RenAtt:Settings* Settings)
(RenAtt:SaveSettings nil)
(unload_dialog dcl))
((= s 2)
(if (eq (progn (initget "Yes No")
(getkword "Are you sure you want to clear all block settings? [Yes/No] <No>: "))
"Yes")
(while (setq s (cond ((findfile "RenAttrib.DAT"))
((findfile (strcat (getvar "RoamableRootPrefix") "RenAttrib.DAT")))))
(vl-file-delete s)))
(unload_dialog dcl)
(c:RenAttrSet))
(t (unload_dialog dcl)))
))
(princ))
;|«Visual LISP© Format Options»
(120 2 1 0 nil "end of " 100 9 0 0 0 nil T nil T)
;*** DO NOT add text below the comment! ***|;