I Tried Server-Side Excel Formula Evaluation in Python: Here's What Actually Works
I spent three days trying to evaluate an Excel formula in Python on a Linux server. Three days. The formula was simple - =PMT(A2/12, A3, -A1) for a loan payment calculation. What I learned is that the Python ecosystem has a gaping hole when it comes to server-side Excel formula evaluation.
Let me save you those three days.
The Problem That Breaks Most Projects
You’re building a Python backend. Maybe it’s a REST API that needs to calculate loan payments. Maybe it’s a data pipeline that processes Excel files uploaded by users. Maybe it’s a financial reporting service.
It doesn’t matter. The scenario is always the same:
User uploads Excel file with formulas | vYour Python backend reads the file | vYou need the CALCULATED values | vEverything breaksI tried the obvious approaches first.
Approach 1: openpyxl - The False Hope
openpyxl is the standard for reading Excel files in Python. It’s mature, well-documented, and everyone uses it. I installed it, loaded my workbook, and grabbed the cell value:
from openpyxl import load_workbook
wb = load_workbook('loan_calc.xlsx')ws = wb['Sheet1']
print(ws['B10'].value) # I expected: 299.71 # I got: =PMT(A2/12, A3, -A1)That’s a string. Not the calculated value - just the formula text. openpyxl can read and write Excel files, but it has no formula evaluation engine. It reads what’s in the file, and if Excel hasn’t calculated the value and saved it, you’re stuck.
I could open the file in Excel first and save it - but this is a server. There’s no Excel on this server.
Approach 2: pandas - The Wrong Tool Altogether
Maybe I thought, pandas reads Excel files all the time:
import pandas as pd
df = pd.read_excel('loan_calc.xlsx')print(df.iloc[9, 1]) # Returns cached value or NaNThis “works” only if Excel has previously calculated and saved the values. If you’re generating files programmatically or processing data from external sources, there’s no cached value. pandas also doesn’t implement Excel’s calculation logic - df.sum() is not the same as Excel SUM(). Different error handling, different blank handling, different type coercion.
Approach 3: xlwings - The Platform Trap
xlwings is brilliant for desktop automation. It connects Python to Excel and can evaluate formulas:
import xlwings as xw
wb = xw.Book('loan_calc.xlsx')result = wb.sheets[0].range('B10').value # Works!The problem? xlwings requires Excel to be installed. On my Linux server? No Excel. In my Docker container? No Excel. On AWS Lambda? No Excel.
xlwings works on: Windows, macOS (with Excel)xlwings fails on: Linux, Docker, Cloud Functions, CI/CD pipelinesEvery server environment I’ve worked with runs Linux. xlwings was never an option.
The Solution: Formualizer
I found Formualizer while searching for “Python Excel calculation engine without Excel.” It’s a Rust-powered spreadsheet engine with Python bindings that evaluates Excel formulas without requiring Excel installation.
Here’s what makes it different:
| Feature | openpyxl | pandas | xlwings | Formualizer |
|---|---|---|---|---|
| Read XLSX | Yes | Yes | Yes | Yes |
| Write XLSX | Yes | Yes | Yes | Yes |
| Evaluate Formulas | No | No | Yes* | Yes |
| Linux Support | Yes | Yes | No | Yes |
| Docker Ready | Yes | Yes | No | Yes |
| Excel Required | No | No | Yes | No |
| Functions | N/A | N/A | Excel’s | 320+ |
*xlwings requires Excel installed on Windows/macOS only
The key advantage: Formularizer is pure Python with a Rust engine under the hood. It works anywhere Python runs, and it’s MIT/Apache-2.0 licensed for commercial use.
My First Working Example
I installed it and ran the same loan calculation:
pip install formualizerimport formualizer as fz
# Create workbookwb = fz.Workbook()s = wb.sheet("LoanCalc")
# Set input valuess.set_value(1, 1, fz.LiteralValue.number(10000.0)) # A1: Principals.set_value(2, 1, fz.LiteralValue.number(0.05)) # A2: Annual rate (5%)s.set_value(3, 1, fz.LiteralValue.number(36.0)) # A3: Months
# Set formula: PMT(rate/12, periods, -principal)s.set_formula(1, 2, "=PMT(A2/12, A3, -A1)")
# Evaluateresult = wb.evaluate_cell("LoanCalc", 1, 2)print(f"Monthly payment: ${result:.2f}")# Output: Monthly payment: $299.71That $299.71 matches what Excel returns. On my Linux server. Without Excel installed.
Why This Matters
Here’s where it clicked for me. I was building a loan comparison API:
User: "I need to compare loan options" | vMy API: Receives principal, rate, months for 3 different lenders | vFormualizer: Calculates PMT for each, computes total interest | vAPI returns: Sorted list of best options with monthly paymentsThis works in:
- Docker containers
- AWS Lambda
- Google Cloud Functions
- Kubernetes pods
- Any Linux environment
No COM automation. No Windows server. No licensing headaches.
Real-World Patterns I’ve Used
REST API with FastAPI
from fastapi import FastAPIfrom pydantic import BaseModelimport formualizer as fz
app = FastAPI()
class LoanRequest(BaseModel): principal: float annual_rate: float months: int
@app.post("/calculate-loan")async def calculate_loan(request: LoanRequest): wb = fz.Workbook() s = wb.sheet("Calc")
s.set_value(1, 1, fz.LiteralValue.number(request.principal)) s.set_value(2, 1, fz.LiteralValue.number(request.annual_rate)) s.set_value(3, 1, fz.LiteralValue.number(request.months))
s.set_formula(1, 2, "=PMT(A2/12, A3, -A1)") monthly_payment = wb.evaluate_cell("Calc", 1, 2)
return {"monthly_payment": round(monthly_payment, 2)}Background Task with Celery
Financial calculations often take time. Offload to a Celery worker:
from celery import Celeryimport formualizer as fz
app = Celery('tasks', broker='redis://localhost:6379/0')
@app.taskdef generate_report(data: dict) -> dict: wb = fz.Workbook() s = wb.sheet("Report")
s.set_value(1, 1, fz.LiteralValue.number(data['revenue'])) s.set_value(2, 1, fz.LiteralValue.number(data['costs'])) s.set_value(3, 1, fz.LiteralValue.number(data['tax_rate']))
s.set_formula(1, 2, "=A1-A2") # Gross profit s.set_formula(2, 2, "=(A1-A2)/A1") # Margin s.set_formula(3, 2, "=B1*(1-A3)") # Net profit
return { "gross_profit": wb.evaluate_cell("Report", 1, 2), "margin": wb.evaluate_cell("Report", 2, 2), "net_profit": wb.evaluate_cell("Report", 3, 2), }Batch Processing
For large datasets, use batch operations:
# Slower: individual operationsfor i in range(1000): s.set_value(i, 1, fz.LiteralValue.number(i * 1.0))
# Faster: batch operationdata = [[fz.LiteralValue.number(i * 1.0)] for i in range(1000)]s.set_values_batch(1, 1, data)What I Wish I Knew Earlier
Function Coverage
Formualizer supports 320+ Excel functions. The ones I’ve used most:
- Financial: PMT, PV, FV, NPV, IRR, RATE, NPER
- Math: SUM, AVERAGE, ROUND, CEILING, FLOOR
- Logical: IF, AND, OR, IFERROR, IFS
- Text: CONCATENATE, LEFT, RIGHT, MID, TRIM
If you need a specific function, check the GitHub repo - coverage is solid for typical financial/logical use cases.
Error Handling
Excel errors propagate as values:
s.set_value(1, 1, fz.LiteralValue.number(100.0))s.set_value(2, 1, fz.LiteralValue.number(0.0))s.set_formula(1, 2, "=A1/A2") # Returns #DIV/0! error
# Use IFERROR for safe fallbackss.set_formula(2, 2, "=IFERROR(A1/A2, 0)")Docker Deployment
This is the game-changer:
FROM python:3.11-slimRUN pip install formualizer fastapi uvicornCOPY app.py .CMD ["uvicorn", "app:app", "--host", "0.0.0.0"]No Excel. No external dependencies. Just Python.
When NOT to Use Formualizer
Be honest about your use case:
- Reading existing Excel files: openpyxl is fine (just read values)
- Data analysis: pandas is your tool
- Windows desktop automation: xlwings works beautifully
- Need 100% Excel compatibility: No pure-Python solution is perfect; consider Microsoft Graph API if you need Excel online
The Bottom Line
The Python ecosystem lacks a good answer for server-side Excel formula evaluation. For years, the only real options were:
- Install Excel on Windows servers (expensive, fragile)
- Use xlwings locally only (not server-compatible)
- Pre-calculate in Excel (no dynamic calculations)
Formularizer fills this gap. It’s not perfect - function coverage is ~320 vs Excel’s 500+, and some edge cases differ. But for typical financial calculations, reporting, and data processing, it works.
I now use Formularizer in every Python project that needs Excel-compatible calculations. No more “open in Excel first” workarounds. No more Windows-only servers. Just calculations that work.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 Formualizer GitHub Repository
- 👨💻 Formualizer PyPI Package
- 👨💻 openpyxl Documentation
- 👨💻 xlwings Documentation
- 👨💻 pandas Excel Documentation
- 👨💻 Excel PMT Function Reference
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments