Tutorial: Importing Ports from Excel#
For assemblies with many connection points it is more convenient to define ports in a
spreadsheet than to hard-code them in Python. Port includes
a class method that reads an Excel file and returns a list of Port objects.
Excel Format#
The Excel file must have the following columns (in order) in the first worksheet. The first row is treated as a header and is automatically skipped:
Column |
Header name |
Description |
|---|---|---|
A |
|
Port identifier string (e.g. |
B |
|
X coordinate in metres |
C |
|
Y coordinate in metres |
D |
|
Z coordinate in metres |
E |
|
X component of the pipe exit direction |
F |
|
Y component |
G |
|
Z component |
H |
|
Minimum straight length at the port before the first turn (metres) |
Direction vectors do not need to be unit vectors — they are normalized automatically.
Example spreadsheet:
name | coord_x | coord_y | coord_z | dir_x | dir_y | dir_z | length
inlet_port | 0.05 | -0.4 | 0.1 | 0 | 1 | 0 | 0.1
outlet_port | 0.05 | 0.8 | 0.1 | 0 | -1 | 0 | 0.1
branch_port_A | 0.37 | -0.4 | 0.3 | 0 | 1 | 0 | 0.08
branch_port_B | 0.45 | 0.8 | 0.18 | 0 | -1 | 0 | 0.04
Reading Ports from a File#
from routing.core.core import Port
with open("ports.xlsx", "rb") as f:
ports = Port.from_xlsx_stream(f)
# ports is a list of Port objects
for port in ports:
print(port.name, port.coordinates, port.direction)
The method returns a flat list[Port]. If your spreadsheet defines port pairs
(start + end for each pipe), you will need to pair them manually.
Pairing Ports into Specifications#
A common pattern is to store ports in consecutive pairs (start, end) and pair them in a loop:
from routing.core.core import Port, PipeType, Specification
from piping_3d import piping
with open("ports.xlsx", "rb") as f:
ports = Port.from_xlsx_stream(f)
# Pair consecutive ports as (start, end)
port_pairs = [(ports[i], ports[i + 1]) for i in range(0, len(ports), 2)]
# One pipe type for all
pipe_type = PipeType(
section=piping.Section(radius_equivalent=0.015),
name="HydraulicLine",
radius_of_curvature_ratio_min=1.5,
color=(0, 100, 200),
type_="Hydraulic",
)
specifications = [
Specification(start, end, pipe_type, name=f"route_{i}")
for i, (start, end) in enumerate(port_pairs)
]
Alternatively, use naming conventions to match starts and ends:
# Ports named "inlet_<id>" pair with "outlet_<id>"
port_dict = {p.name: p for p in ports}
specifications = [
Specification(
port_dict[f"inlet_{i}"],
port_dict[f"outlet_{i}"],
pipe_type,
name=f"route_{i}",
)
for i in range(n_pipes)
]
Next Steps#
Core Concepts — complete Port and Specification reference
Tutorial: Routing Pipes Through a CAD Assembly — full routing tutorial