Three Bugs That Would Have Stayed Hidden in Excel

When you convert an optimization model from Excel to standalone Python, you expect to do some work. You expect to rewrite the data loading, restructure the variable definitions, test the output. What you don’t expect is for the model to fail in three distinct ways, each one caused by something the Excel version was handling silently without you knowing it.

That’s what happened here. Three bugs. All real. All the kind that would have stayed invisible forever if the model had stayed in the spreadsheet.

Bug 1: The client who wasn’t there

The scheduling model has a simultaneous sessions constraint — certain courses have to happen at the same time slot for multiple clients. One of those constraints required a course called Demo A to be scheduled simultaneously for Client A, Client B, and Client C.

The problem: Client C had no data in the workbook. No availability. No requirements. No slot entries. Nothing.

In the original Excel model, this wasn’t an issue. SolverStudio builds the schedule index from whatever data actually exists in the sheets. If Client C has no slots, there are simply no decision variables for Client C — so the simultaneous constraint has nothing to enforce on that side, and the model solves fine. The sparsity of the data structure handled it automatically.

In the standalone Python version, we built the constraint explicitly: for every client in the simultaneous group, enforce that the course happens at the same time. With Client C having no schedule entries, the constraint was trying to reference variables that didn’t exist. Infeasible model. No solution.

The fix was to filter the active pairs before building simultaneous constraints — only enforce them between clients that actually have schedule entries for the relevant course. One line of filtering. Easy fix once you understand what’s happening. The lesson, though, is worth noting: Excel models can be implicitly correct because sparse data is just absent. Standalone code has to be explicit about what exists and what doesn’t.

Bug 2: The comment in the workbook

The second bug was subtler. Q&A and Discussions are two separate courses, both assigned to Client A, and they’re in the same simultaneous group — meaning they must happen at the same time slot. That’s intentional. They’re run together.

But the client capacity constraint says a client can only have one session at a time. Q&A is one session. Discussions is another. If they’re both scheduled at 10am Tuesday, the constraint fires and says: Client A has two sessions at once. Infeasible.

The model was blocking the very thing it was supposed to allow.

What saved us was a comment in the Excel workbook. Right there in the requirements sheet: “Q&A and Discussions will be held simultaneously, so effective slots needed is 44.” The person who built the original data understood that these two courses share a slot — they’re not competing for it. That note had been sitting in the spreadsheet for years, invisible in the original model because SolverStudio understood the context from the data structure.

The fix: identify courses that are in the same simultaneous group for the same client, and exempt all but one from the client capacity constraint. The representative course still counts against the slot. The others ride along for free. It matches the intent exactly.

Comments in workbooks are documentation. Read them before you decide they’re clutter.

Bug 3: Mike can’t be in two places at once

The third bug was a data issue masquerading as a model issue. In the sample workbook, a staff member called Mike is assigned to teach Demo A for both Client A and Client B. The simultaneous constraint requires Demo A for Client A and Demo A for Client B to happen at the same time slot — they’re in the same simultaneous group.

But if both assignments have to happen simultaneously, and the same person is teaching both of them, Mike has to be in two classrooms at once. That’s not a scheduling challenge. That’s physics. The model correctly identified this as infeasible.

Here’s the thing: in a real, complete dataset, this wouldn’t happen. Different staff members would teach Demo A for different clients, and the simultaneous constraint would synchronize their separate schedules. The sample data just happened to assign the same instructor to both — an artifact of it being sample data, not a real deployment.

The fix: skip simultaneous enforcement when both sides of the constraint involve the same staff member. If Mike is the assigned instructor for Demo A for Client A and Demo A for Client B, we can’t make those simultaneous without splitting Mike in half, so we don’t try. In real data this edge case doesn’t arise, but sample data will find your edge cases every time.

The result

After all three fixes: 86 assignments. Status: Optimal. The standalone Python model produces exactly the same result as the original Excel model. That match matters — it means the conversion is faithful, not just approximately correct.

None of these bugs were in the math. The objective function, the constraints, the solver — all of that was right from the start. The bugs were in the assumptions the code made about the data: that all referenced clients exist, that simultaneous courses can share a slot without violating capacity, that same-staff assignments won’t create simultaneous contradictions. The original Excel model made those same assumptions, but the data structure enforced them invisibly.

Making those assumptions explicit is most of what “converting a model from Excel to Python” actually means.

The next post covers the web application itself — three files, how they fit together, and why the structure made the debugging session that produced these fixes significantly less painful than it could have been. You can try the finished app here: Staff Scheduler.

If the solver names are new to you, I untangled PuLP, MILP, and CBC in a separate post.

Tradeline Supply
Things that I use, like, and am affiliated with:
Mint Mobile offers great cell phone service for $15 flat, get $15 off using the link. Get discounted phones with service activation and no contract.
I never spend money before I check Mr Rebates or Rakuten to get cashbacks, rebates, discounts, coupons or cheaper gift cards.

Leave a Reply