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

The procedure

  1. Fixed order of checks, geometric check last (earlier steps can create new -SX parts).
  2. Expected totals added part by part.
  3. One check on the raw DXF text, without ezdxf.
  4. The rest of the file unchanged: same count of lines, texts, blocks and inserts.

Do and don't

Do

Don't

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.