I Replaced Our Quote Spreadsheet With a Real Pricing Engine
How I turned a fragile comlicated multi-dimensional Excel ritual into a 3-step app that generates accurate branded pricing quotes in minutes.
Our sales team used a shared Excel file for customer quotes.
Realistically, two people fully understood how it worked.
I am a DevRel engineer. Pricing tools are not in my job description.
I built one anyway.
The Spreadsheet Ritual
Quoting pain can look like a small nuisance from the outside. It is not small. It quietly burns hours every week, and everyone tolerates it because the sheet “works.”
This is what quote creation actually looked like:
Open the file. Find the right version, hopefully.
Enter asset counts into a formula chain nobody has audited in months.
Wait for a number.
Copy that number into a Word template.
Export to PDF.
Double-check the final amount because we had already seen dropped digits.
Send it.
That took 30 to 45 minutes per quote. And that was the happy path.
Then came the hidden failures. A VLOOKUP pulled the wrong tier because one row got drag-filled too far. Three file copies floated in Slack, all slightly different. A rep sent USD pricing to an India-based customer because the currency column was far off-screen.
None of this is theoretical. I watched all of it happen.
Version sprawl alone was enough reason to replace the process. Files named Pricing_v3_FINAL.xlsx, Pricing_v3_FINAL_USE_THIS.xlsx, and Pricing_v3_clientname_v2.xlsx lived across Slack and inboxes. Two reps quoting the same prospect from two versions was normal.
At that point, you do not “improve the sheet.” You replace the workflow.
Why This Was Not “Just Build a Calculator”
On paper, this sounds easy. Build a calculator and move on.
In practice, pricing for a multi-module B2B security platform is not seat count times price.
The calculation had at least eight dependent steps, and each one affected the others.
Modules: About a dozen products, including cloud posture, workload protection, API security, multiple appsec modules, AI model security, prompt firewall, vulnerability scanning, and log analytics. Customers rarely bought one.
Billable unit per module: There was no universal seat model. Billing could be assets, nodes, endpoints, repos, apps, AI models, prompts per month, container images scanned, or GB ingested per day.
Per-module divisors: Raw counts had to be normalized first. 1,500 API endpoints was not 1,500 units. Divisors varied heavily by module.
Volume tiers: Normalized units across all selected modules rolled up to one total. That total set the tier, and the tier set per-unit rate across the whole quote. One extra module could shift pricing for everything.
Discount: Applied to the post-tier subtotal.
Support tier: Silver, Gold, or Platinum, each with its own multiplier.
Subscription term: One, two, or three years.
Currency and billing entity: USD or INR. INR also needed lakh-crore formatting.
10,000,000should render as1,00,00,000. Locale differences between machines made outputs inconsistent. Billing entity also controlled address, footer text, and legal language.
That is eight to ten linked pricing steps per quote.
A spreadsheet hides those links. One wrong cell reference gives the customer a wrong price, and nothing warns you.
What I Built
A passcode-gated web app with a three-step wizard that outputs a branded PDF quote.
The interesting part is not the UI. It is the design choices behind it.
Why Passcode-Gated Instead of Full Auth
A full login system would have delayed launch and added onboarding friction that this workflow did not need. Reps and select partners needed instant access from any device, including right before calls. A rotatable shared passcode fit the threat model and shipped fast.
OAuth could wait.
The entry point. One URL. No file attachments. No version confusion.
That URL became the distribution model. No files to send. No version confusion. When pricing changed, I updated the tool once and everyone got the latest values immediately.
Why a Three-Step Wizard Instead of One Long Form
I had seen the same failure pattern repeatedly. People skipped fields they found annoying and promised to fill them later. Sometimes they forgot.
The wizard enforces sequence. No pricing step until quote details are complete. No PDF until required fields are filled.
Step one captures everything that goes on the cover page:
Required fields with live validation. Nothing gets sent without a customer name, a preparer, a billing entity, and a logo.
Customer name, prepared-by, quote date, valid-until, billing entity, and customer logo are all required. The form blocks progression until they are filled. The valid-until date defaults to 30 days out so nobody sends an expired quote from an old template.
Here is what the same form looks like when it is done:
The Billing Entity Selector Was the Highest Leverage Dropdown
Switching entities updates the registered address, currency defaults, number format, and legal footer simultaneously.
This took the most thought because it controlled a full downstream chain: currency symbol, number format, legal address block, footer text, and entity name. In the spreadsheet, these were manual and separate. People got one part right and missed another.
I collapsed it into one choice. Select AccuKnox India Pvt. Ltd., and currency, formatting, address, and legal text all switch automatically.
One rep decision. Multiple guaranteed updates. People could now also see billable assets per module, rather than switching spreadsheet tabs they just had to click the i button next to the module they wanted to inspect the billable assets for and boom!
The Pricing Engine
This replaced the old formula chain:
Eleven modules, live unit calculations, real-time tier tracking, and one very useful nudge.
The layout is intentional: inputs on the left, pricing impact on the right, both visible at once. No “fill then calculate” flow. Reps type values and see outcomes live.
Each module row has three fields that matter:
Count: Raw numbers from the customer.
Divisor: Converts raw counts to billable units. I made this editable on purpose. Most reps should keep defaults, but some deals require negotiated normalization factors. If the tool could not handle exceptions, reps would return to spreadsheets. Defaults are prefilled, overrides are visible.
Units:
ceil(Count / Divisor). Simple, visible, auditable.
The right panel handles everything else:
Total units are summed across selected modules. That single total sets the tier. The tier is quote-wide, not per module.
Price per unit, monthly list, annual list, discount, support multiplier, term modifier, and grand total update in real time.
The detail I cared about most was this message:
In the old spreadsheet, tier thresholds were buried in formulas. Most reps never surfaced them during calls. That meant missed opportunities when a customer was already close to the next discount tier.
Now the threshold distance is explicit and live. Reps can test scenarios in front of the customer and immediately show tier effects.
That changes the conversation from “let me check and reply later” to “here is what happens if we include this module.”
What Changed
Quote time dropped from 30-45 minutes to 3-5 minutes. This is how the quote is generated right from the app, so clean, modular and dynamic and always free of human errors.
That gap matters. Sending a quote during the meeting hits differently than sending it the next day.
Currency errors since launch: zero.
Wrong legal entity on quote cover pages: zero.
“Excel says one number, PDF says another” incidents: zero.
New sales engineers can now produce correct branded quotes on day one. The spreadsheet used to require a one-hour walkthrough plus validation from a senior rep.
Each quote is now a generated artifact tied to exact inputs. We can reconstruct what was quoted months later, including module mix, rate card, and discount.
Take Ownership of the Problem, Not Just the Title
I am a DevRel engineer and a Technical Content Lead and yet I shipped a sales ops tool. That is unusual, but it was the right call.
The pain was obvious from outside the team. Quote cycles turned into long Slack threads. Rate card updates meant inbox blasts. New rep onboarding included spreadsheet survival training.
When a problem is this visible and this solvable, title boundaries should not block execution.
The spreadsheet was not failing because people were careless. It was the wrong tool. Spreadsheets can handle straightforward math. They struggle when eight linked variables drive legal, currency, formatting, and governance-sensitive output that must be auditable later.
At that point, you do not “improve the sheet.” You replace the workflow.















