Cut List Macro in FreeCAD: Difference between revisions
Jump to navigation
Jump to search
"""
if measure_count > 0:
html += """
"""
# If nothing found, show a friendly message in the HTML instead of crashing
if part_count == 0 and measure_count == 0:
html += """
(Created page with "import FreeCAD import FreeCADGui import tempfile import webbrowser import os def print_master_checklist(): doc = FreeCAD.ActiveDocument if not doc: FreeCAD.Console.PrintError("No active document found.\n") return selection = FreeCADGui.Selection.getSelection() # Even if nothing is selected, we will try to generate the page # so you can see that the script is working. # --- HTML Header --- html = """...") |
(No difference)
|
Latest revision as of 15:24, 18 November 2025
import FreeCAD
import FreeCADGui
import tempfile
import webbrowser
import os
def print_master_checklist():
doc = FreeCAD.ActiveDocument
if not doc:
FreeCAD.Console.PrintError("No active document found.\n")
return
selection = FreeCADGui.Selection.getSelection()
# Even if nothing is selected, we will try to generate the page
# so you can see that the script is working.
# --- HTML Header ---
html = """
<!DOCTYPE html>
Shop Master List
Shop Master List
Project: """ + doc.Label + """
Date:
"""
# Lists to hold our data
part_rows = ""
measure_rows = ""
part_count = 0
measure_count = 0
# --- Helper to process objects ---
if selection:
items_to_process = list(selection)
processed_ids = set()
while items_to_process:
obj = items_to_process.pop(0)
# Avoid infinite loops or duplicates
if obj.Name in processed_ids:
continue
processed_ids.add(obj.Name)
# 1. If it's a Folder/Group, add its contents to the queue
if hasattr(obj, "Group") and obj.Group:
items_to_process.extend(obj.Group)
# We don't 'continue' here because a group might ALSO have a shape (rare but possible)
# 2. Check for Measurement (Distance)
is_measurement = False
# Check for standard Measure tool or Draft Dimensions
if hasattr(obj, "Distance") or hasattr(obj, "Length"):
# Distinguish between a Part that happens to have a Length (like a Cube)
# and a Measurement object.
# Measurement objects usually don't have a "Shape" that is a solid.
if not hasattr(obj, "Shape") or obj.Shape.Volume < 1e-6:
val = 0.0
try:
if hasattr(obj, "Distance"):
# Handle wrapped values vs direct floats
val = obj.Distance.Value if hasattr(obj.Distance, "Value") else obj.Distance
elif hasattr(obj, "Length"):
val = obj.Length.Value if hasattr(obj.Length, "Value") else obj.Length
# Only add if we got a valid number
if isinstance(val, (int, float)):
val_str = FreeCAD.Units.Quantity(val, 'mm').UserString
measure_rows += f"""
{obj.Label}
{val_str}
☐
"""
measure_count += 1
is_measurement = True
except:
pass # Skip if calculation fails
# 3. Check for 3D Part (Cutlist) - Only if it wasn't a measurement
if not is_measurement and hasattr(obj, 'Shape') and not obj.Shape.isNull():
# We filter out things with 0 volume (like lines or planes) for the Cutlist
if obj.Shape.Volume > 0:
bbox = obj.Shape.BoundBox
raw_dims = sorted([bbox.XLength, bbox.YLength, bbox.ZLength], reverse=True)
L_str = FreeCAD.Units.Quantity(raw_dims[0], 'mm').UserString
W_str = FreeCAD.Units.Quantity(raw_dims[1], 'mm').UserString
T_str = FreeCAD.Units.Quantity(raw_dims[2], 'mm').UserString
part_rows += f"""
{obj.Label}
{L_str}
{W_str}
{T_str}
☐
"""
part_count += 1
# --- Build the HTML Tables ---
if part_count > 0:
html += """
Material Cut List
""" + part_rows + """
| Part Name | Length | Width | Thickness | Cut |
|---|
Critical Measurements
""" + measure_rows + """| Measurement Name | Value | Check |
|---|
No Parts Selected
Please select your 3D Parts or Measurement Objects in the FreeCAD tree before running this macro.
""" html += """"""
# --- Launch Browser ---
try:
fd, path = tempfile.mkstemp(suffix=".html")
with os.fdopen(fd, 'w') as tmp:
tmp.write(html)
webbrowser.open('file://' + path)
print("HTML Page generated.")
except Exception as e:
FreeCAD.Console.PrintError(f"Error creating print file: {e}\n")
if __name__ == "__main__":
print_master_checklist()