import FreeCADGui as Gui import FreeCAD as App import ahb_utils from ahb_material import Material class PartInfo: def __init__(self, workbench, document, obj): self.document = document self.reference = obj.Label if len(self.reference) == 3 and self.reference[0:1] in ['L', 'M', 'T', 'R', 'E']: self.reference = 'TB_' + self.reference workbench.techDrawExtensions.initPartMetadata(obj) self.material = 'Unknown' try: self.material = obj.Assembly_handbook_Material except: pass self.size = [obj.Shape.BoundBox.XLength, obj.Shape.BoundBox.YLength, obj.Shape.BoundBox.ZLength] # in mm self.volume = obj.Shape.Volume # in mm3 self.mass = -1 # in g (negative means unknown mass) density = -1 # in g/cm3 material = Material.Get(self.material) if material is not None: density = material.density if density >= 0: self.mass = density * (self.volume / 1000) try: part_mass = obj.Assembly_handbook_Weight if part_mass >= 0: self.mass = part_mass except: pass self.count = 0 class AHB_ExportPartsList: def GetResources(self): return {"MenuText": "Export parts list (CSV)", "ToolTip": "Exports all parts of the selected assembly in CSV format", "Pixmap": "" } def IsActive(self): obj = Gui.Selection.getSelection() if len(obj) == 1: obj = obj[0] return obj.TypeId == 'App::Part' and 'AssemblyType' in obj.PropertiesList return False def Activated(self): all_parts = {} rootAssembly = Gui.Selection.getSelection()[0] workbench = Gui.getWorkbench("AssemblyHandbookWorkbench") #: :type workbench: AssemblyHandbookWorkbench def add_part(part): #print(part.Label + " (" + part.LinkedObject.Label + ")") try: info = all_parts[part.LinkedObject] except: info = PartInfo(workbench, part.LinkedObject.Document.Name, part.LinkedObject) all_parts[part.LinkedObject] = info info.count += 1 def process_group(group): for part in group.Group: if not part.Visibility: continue isPartLink = part.TypeId == 'App::Link' or (part.TypeId == 'Part::FeaturePython' and hasattr(part, 'LinkedObject')) partType = None isSinglePart = None try: partType = part.Type isSinglePart = part.Assembly_handbook_IsSinglePart except: pass if isPartLink: if isSinglePart != True and (partType == 'Assembly' or (part.Group[1].Label == 'Constraints' and part.Group[2].Label == 'Variables' and part.Group[3].Label == 'Configurations')): process_group(part.LinkedObject) else: add_part(part) else: if part.TypeId != 'App::DocumentObjectGroup' and part.TypeId != 'Spreadsheet::Sheet' and partType != 'App::PropertyContainer': print("??? " + part.Label) pass print("Exporting all parts contained in assembly: " + rootAssembly.Label + "...") process_group(rootAssembly) file_name = rootAssembly.Document.FileName.replace('.FCStd', '') + '_list.csv' with open(file_name, "w") as f: f.write("Document, Reference, Material, SizeX (mm), SizeY (mm), SizeZ (mm), Volume (cm3), Mass (g), Count\n") for part in all_parts.values(): mass_str = '' if part.mass >= 10: mass_str = str(int(part.mass + 0.5)) elif part.mass >= 0: mass_str = str(int(part.mass*10 + 0.5) / 10.0) f.write(part.document + "," + part.reference + "," + part.material + "," + str(int(part.size[0]+0.5)) + "," + str(int(part.size[1]+0.5)) + "," + str(int(part.size[2]+0.5)) + "," + str(int(part.volume/100+0.5)/10.0) + "," + mass_str + ", " + str(part.count) + "\n") print("Part list exported to " + file_name) from ahb_command import AHB_CommandWrapper AHB_CommandWrapper.addGuiCommand('AHB_export_parts_list', AHB_ExportPartsList())