import clr
import sys
import re
import os
clr.AddReference("System")
clr.AddReference("Microsoft.Office.Interop.Excel")
from Microsoft.Office.Interop import Excel
class MsoTriState:
msoFalse = 0
msoTrue = -1
Win = Windows()
Option = [
['Thumbnail Size', WindowsInputTypes.Real, 100],
['Save Folder', WindowsInputTypes.Folder, None],
]
Values = Win.OptionsDialog("Image from Assembly", Option, 100)
if Values is None:
sys.exit()
dimension_thumb = Values[0]
save_path = Values[1]
def detect_type():
try:
if hasattr(CurrentAssembly(), 'Parts'):
obj = CurrentAssembly()
obj_type = 'Assembly'
else:
raise Exception("Invalid assembly")
except:
if hasattr(CurrentPart(), 'Name'):
obj = CurrentPart()
obj_type = 'Part'
else:
raise Exception("Invalid part")
return obj, obj_type
def normalize_part_name(part_name):
return re.sub(r"<\d+>", "", part_name)
def clean_file_name(name):
invalid_chars = r'<>:"/\\|?*'
cleaned_name = re.sub('[{}]'.format(re.escape(invalid_chars)), '_', name)
return cleaned_name
def get_part_location(part):
"""Extract the file location using the FileName property from Alibre API"""
try:
if hasattr(part, 'FileName'):
return part.FileName
else:
return "N/A"
except:
return "N/A"
def get_part_properties(part):
"""Extract specific properties from a part using Alibre API"""
properties = {}
property_names = [
'Comment',
'CostCenter',
'CreatedBy',
'CreatedDate',
'CreatingApplication',
'DocumentNumber',
'EngineeringApprovedBy',
'Keywords',
'Material'
]
for prop_name in property_names:
try:
if hasattr(part, prop_name):
prop_value = getattr(part, prop_name)
if prop_value is not None:
properties[prop_name] = str(prop_value)
else:
properties[prop_name] = ""
else:
properties[prop_name] = ""
except:
properties[prop_name] = ""
return properties
def collect_all_instances(assembly):
"""Collect all part instances (each occurrence gets its own entry)"""
all_instances = []
def process_assembly(asm):
for part in asm.Parts:
part_name = part.Name if hasattr(part, 'Name') else str(part)
normalized_name = normalize_part_name(part_name)
instance_data = {
'name': normalized_name,
'full_name': part_name,
'location': get_part_location(part),
'properties': get_part_properties(part),
'thumbnail_name': clean_file_name(normalized_name) + '.jpg'
}
all_instances.append(instance_data)
for sub_asm in asm.SubAssemblies:
sub_asm_name = sub_asm.Name if hasattr(sub_asm, 'Name') else str(sub_asm)
normalized_name = normalize_part_name(sub_asm_name)
instance_data = {
'name': normalized_name,
'full_name': sub_asm_name,
'location': get_part_location(sub_asm),
'properties': get_part_properties(sub_asm),
'thumbnail_name': clean_file_name(normalized_name) + '.jpg'
}
all_instances.append(instance_data)
process_assembly(sub_asm)
process_assembly(assembly)
return all_instances
def generate_thumbnails(assembly, save_path):
saved_thumbnails = set()
def process_assembly(asm):
for part in asm.Parts:
part_name = part.Name if hasattr(part, 'Name') else str(part)
normalized_name = normalize_part_name(part_name)
cleaned_name = clean_file_name(normalized_name)
if cleaned_name not in saved_thumbnails:
thumbnail_path = os.path.join(save_path, cleaned_name + '.jpg')
part.SaveThumbnail(thumbnail_path, dimension_thumb, dimension_thumb)
saved_thumbnails.add(cleaned_name)
for sub_asm in asm.SubAssemblies:
sub_asm_name = sub_asm.Name if hasattr(sub_asm, 'Name') else str(sub_asm)
normalized_name = normalize_part_name(sub_asm_name)
cleaned_name = clean_file_name(normalized_name)
if cleaned_name not in saved_thumbnails:
thumbnail_path = os.path.join(save_path, cleaned_name + '.jpg')
sub_asm.SaveThumbnail(thumbnail_path, dimension_thumb, dimension_thumb)
saved_thumbnails.add(cleaned_name)
process_assembly(sub_asm)
process_assembly(assembly)
def GenerateExcelWithImagesNET(image_directory, all_instances):
excel = Excel.ApplicationClass()
excel.Visible = False
workbook = excel.Workbooks.Add()
sheet = workbook.Worksheets[1]
property_columns = [
'Comment',
'CostCenter',
'CreatedBy',
'CreatedDate',
'CreatingApplication',
'DocumentNumber',
'EngineeringApprovedBy',
'Keywords',
'Material'
]
sheet.Cells[1, 1].Value2 = "Part Name"
sheet.Cells[1, 2].Value2 = "Image"
sheet.Cells[1, 3].Value2 = "File Location"
for idx, prop_name in enumerate(property_columns):
sheet.Cells[1, 4 + idx].Value2 = prop_name
header_range = sheet.Range[sheet.Cells[1, 1], sheet.Cells[1, 3 + len(property_columns)]]
header_range.Font.Bold = True
header_range.Interior.Color = 0xD3D3D3
header_range.WrapText = False
cell_size_points = 75
sheet.Columns("B").ColumnWidth = 15
row = 2
for instance in all_instances:
sheet.Cells[row, 1].Value2 = instance['name']
sheet.Cells[row, 3].Value2 = instance['location'] if instance['location'] else "N/A"
properties = instance['properties']
for idx, prop_name in enumerate(property_columns):
prop_value = properties.get(prop_name, "")
sheet.Cells[row, 4 + idx].Value2 = prop_value
sheet.Rows[row].RowHeight = cell_size_points
thumbnail_path = os.path.join(image_directory, instance['thumbnail_name'])
if os.path.exists(thumbnail_path):
left = sheet.Cells[row, 2].Left
top = sheet.Cells[row, 2].Top
picture = sheet.Shapes.AddPicture(
Filename=thumbnail_path,
LinkToFile=MsoTriState.msoFalse,
SaveWithDocument=MsoTriState.msoTrue,
Left=left,
Top=top,
Width=cell_size_points,
Height=cell_size_points
)
row += 1
sheet.Columns("A").AutoFit()
sheet.Columns("C").AutoFit()
for idx in range(len(property_columns)):
sheet.Columns[4 + idx].AutoFit()
excel_file_path = os.path.join(image_directory, "Images_NET.xlsx")
workbook.SaveAs(excel_file_path)
workbook.Close(False)
excel.Quit()
print("\nExcel file with images created at: {}".format(excel_file_path))
def Main():
obj, obj_type = detect_type()
if obj_type == 'Part':
print("Current document is a Part; generating thumbnail.")
cleaned_name = clean_file_name(obj.Name)
obj.SaveThumbnail(os.path.join(save_path, cleaned_name + '.jpg'), dimension_thumb, dimension_thumb)
all_instances = [{
'name': obj.Name,
'full_name': obj.Name,
'location': get_part_location(obj),
'properties': get_part_properties(obj),
'thumbnail_name': cleaned_name + '.jpg'
}]
GenerateExcelWithImagesNET(save_path, all_instances)
else:
print("Current document is an Assembly; collecting all instances.")
all_instances = collect_all_instances(obj)
print("Generating thumbnails.")
generate_thumbnails(obj, save_path)
print("Creating Excel with {} instances.".format(len(all_instances)))
GenerateExcelWithImagesNET(save_path, all_instances)
Main()