seems ezdxf has this feature, so we can just use it.
import wx
from ezdxf.addons import acadctb
from pyrx import Ap, Db, Ed
def browse_for_ctb():
"""Opens a native wxPython file dialog to browse for a CTB file."""
parent = wx.GetApp().GetTopWindow()
with wx.FileDialog(
parent,
"Select AutoCAD CTB File",
wildcard="CTB files (*.ctb)|*.ctb",
style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST,
) as fileDialog:
if fileDialog.ShowModal() == wx.ID_CANCEL:
return None
return fileDialog.GetPath()
@Ap.Command()
def doit() -> None:
ctb_path = browse_for_ctb()
if not ctb_path:
print("\nCommand cancelled.")
return
try:
# 2. Parse the CTB using ezdxf
ctb_data = acadctb.load(ctb_path)
except Exception as e:
print(f"\nFailed to parse CTB file: {str(e)}")
return
active_colors = []
for idx in range(1, 256):
style = ctb_data[idx]
# Keep the entry if it overrides lineweight or screening
if style.lineweight >= 0 or style.screen < 100:
# Store the index along with the full style object to access all 10 properties
active_colors.append((idx, style))
if not active_colors:
print("\nNo explicit pen styles overrides found in this CTB. Table skipped.")
return
db = Db.curDb()
ps, insert_pt = Ed.Editor.getPoint("\nSpecify insertion point for the CTB table: ")
if ps != Ed.PromptStatus.kNormal:
return
table = Db.Table()
table.setDatabaseDefaults(db)
# 10 headers corresponding to all the available style properties
headers = [
"ACI Index", "Lineweight", "Screening", "Dither",
"Phys Pen", "Virt Pen", "Linetype", "Adaptive LT",
"Fill Style", "Style Index"
]
total_rows = len(active_colors) + 2 # Title row + Header row + Data rows
table.setSize(total_rows, len(headers))
table.setPosition(insert_pt)
table.generateLayout()
# Title Row Configurations
table.setTextString(0, 0, f"Complete CTB Profile: {ctb_path.split('\\')[-1]}")
# Header Row Configurations
for col_idx, header_text in enumerate(headers):
table.setTextString(1, col_idx, header_text)
# Populate Data rows
for row_idx, (idx, style) in enumerate(active_colors, start=2):
lweight_str = f"{style.lineweight:.2f} mm" if style.lineweight >= 0 else "Use Object Value"
table.setBackgroundColor(row_idx, 0, Db.Color(style.aci))
table.setContentColor(row_idx, 0, Db.Color(7))
table.setTextString(row_idx, 0, str(style.aci))
table.setTextString(row_idx, 1, lweight_str)
table.setTextString(row_idx, 2, f"{style.screen}%")
table.setTextString(row_idx, 3, "On" if style.dithering == 1 else "Off")
table.setTextString(row_idx, 4, str(style.physical_pen_number))
table.setTextString(row_idx, 5, str(style.virtual_pen_number))
table.setTextString(row_idx, 6, str(style.linetype))
table.setTextString(row_idx, 7, "Yes" if style.adaptive_linetype == 1 else "No")
table.setTextString(row_idx, 8, str(style.fill_style))
table.setTextString(row_idx, 9, str(style.index))
db.addToCurrentspace(table)
print(f"\nSuccessfully generated a 10-column table with {len(active_colors)} CTB overrides.")