Blog · Lessons · 1 Oct 2026 · 3 min read
How to check part quantities in a cutting DXF against the bill of materials
Quantities written in the notes of a delivery DXF must match the parts list, times the number of assemblies, with left-hand parts counted once. The rule that decides it, the error that put twenty extra plates in a delivery, and the parser traps an AI agent must handle.
Short answer: count geometrically, not from the register. A symmetric part is needed quantity × number of assemblies. A part that needs a left-hand version (-SX) and its -SX are each needed quantity × 1. Double both and you count them four times. Add up the expected totals one by one, never with a global formula, and check the result on the raw text of the file as well.
The counting rule
| Part | Assemblies | Quantity in the notes |
|---|---|---|
| Symmetric (turned over is the same part) | 2 | qty × 2 |
| Chiral part with its own -SX | 2 | qty × 1 |
| Its -SX | 2 | qty × 1 |
Why: the second assembly is the mirror of the first. A symmetric part serves both by turning over. A chiral part serves one side, its -SX the other. More on deciding which is which: when a mirrored part needs its own drawing.
The error that added twenty plates
The rule had been inferred from the fact that -SX parts get their own rows in the register. Result: 10 base codes and their 10 -SX at quantity 2 instead of 1. Total 418 instead of 398. Twenty extra plates.
It passed because the test re-read the file with the same formula that had written it. A test that re-reads with the measure that wrote the values is not a test. What caught it was a different check: "is the rest of the file unchanged?", which found 1,038 extra lines and 822 extra texts.
Parser traps
| Trap | Effect | Fix |
|---|---|---|
Lowercase codes (-sx) and colour codes inside MTEXT ({\C4;-SX}) |
4 notes out of 150 missed | Case-insensitive regex that allows a colour block |
The degree sign corrupted (n°4 becomes n?4) |
Quantity not found | Accept any 0 to 4 non-word characters after n |
CSV with ; read as comma-separated |
Empty dictionary, read downstream as "no discrepancies" | Detect the delimiter from the first line |
| Replacing the first match | The right number in the wrong place | Edit by match position |
| Work material parked far away in the modelspace | 11 codes counted twice | Limit the count to the delivery area |
RE_QTY = re.compile(r'(n\W{0,4})(\d+)', re.I) # n°4, n.4, n 4, n?4
RE_SX = re.compile(r'CODE\s*-?\s*(\{[^}]*;)?\s*SX', re.I) # -SX or {\C4;SX}
with open(path, encoding="utf-8-sig", newline="") as f:
first = f.readline()
delim = ";" if first.count(";") > first.count(",") else ","
new_raw = raw[:m.start(2)] + str(new_qty) + raw[m.end(2):] # edit by position
A false OK is worse than an error. An empty dictionary that means "nothing to compare" must stop the run.
Reading a discrepancy report
- Every code off by the same factor: the measure is wrong, usually the assembly multiplier is missing.
- Right = 2 and left = 2 with BOM = 1 and 2 assemblies: the twenty-plates defect.
- The same code twice: almost always a part that appears in both the cutting area and the machining column. Add up the notes before calling it a defect.
The procedure
- Fixed order of checks, geometric check last (earlier steps can create new -SX parts).
- Expected totals added part by part.
- One check on the raw DXF text, without ezdxf.
- The rest of the file unchanged: same count of lines, texts, blocks and inserts.
Do and don't
Do
- Decide the multiplier per part, from the geometry.
- Detect CSV delimiters; stop on empty results.
- Verify with a method different from the one that wrote.
Don't
- Don't multiply both a part and its -SX by the assemblies.
- Don't trust a "no discrepancies" built on an empty table.
- Don't edit the first match of a number.
Questions people ask
Can an AI agent do this check? Yes, and it is fast. The danger is that it checks with its own formula. Make it check against the geometry and against the raw file.
Where do the quantities come from? From the register, which is the single source. The DXF notes are a copy, and copies drift.