Skip to the content.

8. Recipes

Complete scripts for common jobs, written with the raw API so you can see what happens underneath; Building models shows shorter versions of several of them. They build on each other in order (the first one creates and saves plate.SLDPRT, later ones work on the active document), and each can be adapted on its own. Files go to %TEMP%\swpy-recipes.

Create a part from scratch

Sketch a rectangle on the Front plane, extrude it and save. model.planes makes it work with any part template, also ones that rename the default planes.

```python live import os, tempfile folder = os.path.join(tempfile.gettempdir(), “swpy-recipes”) os.makedirs(folder, exist_ok=True)

tpl = sw.GetUserPreferenceStringValue(swconst.swUserPreferenceStringValue_e.swDefaultTemplatePart) part = sw.NewDocument(tpl, 0, 0, 0) plate = Model(part)

def extrude(doc, depth): “"”Close the open sketch and extrude it (blind).””” doc.SketchManager.InsertSketch(True) doc.FeatureByPositionReverse(0).Select2(False, 0) # closing a sketch can leave nothing selected feat = doc.FeatureManager.FeatureExtrusion2( True, False, False, 0, 0, depth, 0, False, False, False, False, 0, 0, False, False, False, False, True, True, True, 0, 0, False) if feat is None: raise RuntimeError(“extrusion failed”) # the API fails silently - check results return feat

plate.planes.front.Select2(False, 0) part.SketchManager.InsertSketch(True) part.SketchManager.CreateCenterRectangle(0, 0, 0, 40 * mm, 25 * mm, 0) # 80 x 50 mm extrude(part, 15 * mm)

ok, errors, warnings = part.Extension.SaveAs(os.path.join(folder, “plate.SLDPRT”), 0, 1, None, 0, 0) print(“saved” if ok else f”save failed ({errors})”, part.GetPathName())


## Parameter study to CSV

Vary a dimension, record the mass, restore the original value.

```python live
import csv, os, tempfile
path = os.path.join(tempfile.gettempdir(), "swpy-recipes", "study.csv")

original = model.dims["D1@Boss-Extrude1"]
rows = []
for t in [5, 10, 15, 20]:
    model.dims["D1@Boss-Extrude1"] = t * mm
    rows.append((t, round(model.mass["mass"], 6)))
model.dims["D1@Boss-Extrude1"] = original

with open(path, "w", newline="") as f:
    csv.writer(f).writerows([("thickness_mm", "mass_kg"), *rows])
rows

Export to STEP, Parasolid and STL

```python live import os base = os.path.splitext(doc.GetPathName())[0] # the document must be saved once for ext in (“.step”, “.x_t”, “.stl”): ok, errors, warnings = doc.Extension.SaveAs( base + ext, swconst.swSaveAsVersion_e.swSaveAsCurrentVersion, swconst.swSaveAsOptions_e.swSaveAsOptions_Silent, None, 0, 0) print(f”{ext:6} {‘ok’ if ok else f’failed (error {errors})’}”)


## Custom properties

```python live
props = doc.Extension.get_CustomPropertyManager("")    # "" = file properties; or a configuration name
TEXT = swconst.swCustomInfoType_e.swCustomInfoText
REPLACE = swconst.swCustomPropertyAddOption_e.swCustomPropertyReplaceValue

props.Add3("PartNo", TEXT, "P-1001", REPLACE)
props.Add3("Description", TEXT, "Base plate", REPLACE)

for name in props.GetNames() or []:
    status, value, resolved, was_resolved, linked = props.Get6(name, False)
    print(f"{name:12} {resolved}")

ok, errors, warnings = doc.Save3(swconst.swSaveAsOptions_e.swSaveAsOptions_Silent, 0, 0)

Features by type, rename

```python live from collections import Counter print(Counter(f.GetTypeName2() for f in model.features()))

extrusions = [f for f in model.features() if f.GetTypeName2() == “Extrusion”] first = extrusions[0] first.Name = “Plate body” # property assignment works like in VBA print([f.Name for f in extrusions]) first.Name = “Boss-Extrude1”


## Bounding box and largest face

```python live
x1, y1, z1, x2, y2, z2 = doc.GetPartBox(True)
size = [round(to(b - a, mm), 3) for a, b in ((x1, x2), (y1, y2), (z1, z2))]
print("bounding box (mm):", size)

face = model.faces.planar().largest()
face.Select4(False, None)                  # highlight it in the viewport
print("largest face:", round(to(face.GetArea(), mm**2)), "mm^2, normal", Vec(face.Normal))

Sketch from a list of points

```python live points = [(0, 0), (60, 0), (60, 20), (30, 35), (0, 20)] # mm, closed outline

tpl = sw.GetUserPreferenceStringValue(swconst.swUserPreferenceStringValue_e.swDefaultTemplatePart) profile = sw.NewDocument(tpl, 0, 0, 0) Model(profile).planes.front.Select2(False, 0) sketch = profile.SketchManager sketch.InsertSketch(True) sketch.AddToDB = True # draw directly: no snapping, much faster for (xa, ya), (xb, yb) in zip(points, points[1:] + points[:1]): sketch.CreateLine(xa * mm, ya * mm, 0, xb * mm, yb * mm, 0) sketch.AddToDB = False

profile.SketchManager.InsertSketch(True) profile.FeatureByPositionReverse(0).Select2(False, 0) feat = profile.FeatureManager.FeatureExtrusion2( True, False, False, 0, 0, 10 * mm, 0, False, False, False, False, 0, 0, False, False, False, False, True, True, True, 0, 0, False) print(feat.Name, round(to(Model(profile).mass[“volume”], mm**3)), “mm^3”) sw.CloseDoc(profile.GetTitle()) # closes without saving


## Build an assembly and count components

```python live
import os, tempfile
from collections import Counter

plate_path = os.path.join(tempfile.gettempdir(), "swpy-recipes", "plate.SLDPRT")   # saved above
tpl = sw.GetUserPreferenceStringValue(swconst.swUserPreferenceStringValue_e.swDefaultTemplateAssembly)
asm = sw.NewDocument(tpl, 0, 0, 0)
for i in range(3):
    asm.AddComponent5(plate_path, 0, "", False, "", i * 100 * mm, 0, 0)

components = asm.GetComponents(True)      # True = top level only
for path, n in Counter(c.GetPathName() for c in components).items():
    print(n, "x", os.path.basename(path))
for c in components:
    x, y, z = c.Transform2.ArrayData[9:12]   # translation part of the 4x4 transform
    print(f"{c.Name2:10} at {to(x, mm):6.1f} {to(y, mm):6.1f} {to(z, mm):6.1f} mm")
print("total mass:", round(Model(asm).mass["mass"], 3), "kg")
sw.CloseDoc(asm.GetTitle())

Process every part in a folder

Open each file silently, read something, close the ones that were not open before.

```python live import glob, os, tempfile folder = os.path.join(tempfile.gettempdir(), “swpy-recipes”)

for path in sorted(glob.glob(os.path.join(folder, “*.SLDPRT”))): was_open = sw.GetOpenDocumentByName(path) is not None part, errors, warnings = sw.OpenDoc6( path, swconst.swDocumentTypes_e.swDocPART, swconst.swOpenDocOptions_e.swOpenDocOptions_Silent, “”, 0, 0) if part is None: print(“cannot open”, path, “error”, errors) continue print(f”{os.path.basename(path):20} {Model(part).mass[‘mass’]:.3f} kg”) if not was_open: sw.CloseDoc(part.GetTitle())


## Clean up

```python live
import os, tempfile
plate = sw.GetOpenDocumentByName(os.path.join(tempfile.gettempdir(), "swpy-recipes", "plate.SLDPRT"))
if plate is not None:
    sw.CloseDoc(plate.GetTitle())