How I finally stopped copy-pasting modules for every nut size

Nov 08, 2026 Last reply: 2 days ago 4 Replies

First reply

CrestRusty

I hit the same wall last year with a set of hex standoffs, M3 through M6, and my module was a mess of nested conditionals that I was scared to touch. Rebuilding it around a data table like you describe cut the file down by half and I stopped making copy-paste errors where I'd…

Read the full reply

For ages I did the same thing you're describing, one module per size, all near identical apart from which row of the table they pulled from. The fix turned out to be much simpler than I expected. Put all your data in one big list, one row per nut, and let OpenSCAD find the right row for you before any branching happens. Something like: nut_data = [ [3, 5.5, 2.4], [4, 7, 3.2], [5, 8, 4] ]; then row = search([nut_size], nut_data)[0]; and from there h = nut_data[row][1]; and so on. search() returns the position of the matching row, so you grab your height, radius and clearance straight out of it. One module, one block of geometry code, no if/else chain at all. The reason the if statement felt broken is that OpenSCAD variables only get set once when the file compiles, so reassigning them inside a branch never does what you hope. Selecting the data first sidesteps the whole problem. Same trick works for any parameter table, pipe fittings, bolt sizes, whatever you're stacking up.


I hit the same wall last year with a set of hex standoffs, M3 through M6, and my module was a mess of nested conditionals that I was scared to touch. Rebuilding it around a data table like you describe cut the file down by half and I stopped making copy-paste errors where I'd update a hole size in one branch but forget the other three. One thing that tripped me up with search(): it does exact matching, so if your nut_size comes in as a string from a customizer dropdown while your table uses numbers, it silently returns an empty list and you get an undefined index error that's painful to trace. I fixed it by making sure the customizer options and the table keys were the same type. Also, if two rows ever share the same first value, search returns a vector of matches instead of a single index, which bit me once when I had a leftover duplicate row.

For debugging I'd echo(row) right after the lookup and just render a flat plate until the numbers coming out looked right. Took ten minutes and saved me a wasted print. I've since reused the pattern for a drill guide jig with different bushing sizes and it held up fine.

One addition that's saved me some grief: check the result before you index into it, since len(search([nut_size], nut_data)) > 0 is a cheap guard against a typo in the table or a customizer value that doesn't exist yet. I also got into the habit of adding a clearance column as a fourth entry in each row rather than computing it inline later, which sounds overly fussy til you want to tweak the fit for a sloppy printer and realize it's buried in three places. Does anyone else keep the units in a comment above the table, becasue I've definatly mixed mm and fractions of an inch on a bolt chart before.

Reminds me of how we used to handle this back before search() even existed in OpenSCAD. I kept a seperate include file per size and swapped them in and out, which worked but was a pain to maintain. These days I do the same table trick for my drawer pull templates, and one habit I picked up is keeping the table sorted by size so it reads like the old paper reference charts I still have kicking around the shop. Makes spotting a typo at a glance much easier.

Update: The suggestion to check the result count before indexing was super helpful for catching input typos. I've got that guard in place now, but I'm still running into trouble with ambiguity. When a parameter value matches more than one row in the list, which result should my script pick up?

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required