Examples

This page contains practical examples of using SerializableExcel in various scenarios.

Example 1: Import Configuration Data

Import application settings from an Excel spreadsheet:

from serializable_excel import ExcelModel, Column

class ConfigModel(ExcelModel):
    key: str = Column(header="Config Key")
    value: str = Column(header="Value")
    environment: str = Column(header="Environment")

# Read configuration from Excel
configs = ConfigModel.from_excel("config.xlsx")

# Use the configuration
for config in configs:
    print(f"{config.key} = {config.value} ({config.environment})")

Example 2: Export Report Data

Export application data to Excel for reporting:

from serializable_excel import ExcelModel, Column

class ReportModel(ExcelModel):
    date: str = Column(header="Date")
    revenue: float = Column(header="Revenue")
    expenses: float = Column(header="Expenses")

    @property
    def profit(self):
        return self.revenue - self.expenses

# Create report data
reports = [
    ReportModel(date="2024-01", revenue=10000, expenses=5000),
    ReportModel(date="2024-02", revenue=12000, expenses=6000),
]

# Export to Excel
ReportModel.to_excel(reports, "report.xlsx")

Example 3: Forecast with Dynamic Characteristics

Work with dynamic columns that administrators can configure:

import enum
from serializable_excel import ExcelModel, Column, DynamicColumn

class ForecastValueTypeEnum(enum.Enum):
    """Value types for forecast characteristics"""
    INTEGER = 'Integer'
    STRING = 'String'

class ForecastModel(ExcelModel):
    # Static fields - always present in Excel
    month: str = Column(header="Month")
    curator: str = Column(header="Curator")
    manager: str = Column(header="Manager")
    object_title: str = Column(header="Object")

    # Dynamic characteristics - detected from Excel headers at runtime
    characteristics: dict = DynamicColumn()

# Excel file with additional columns:
# Month | Curator | Manager | Object | Sales Volume | Priority | Region
forecasts = ForecastModel.from_excel("forecasts.xlsx", dynamic_columns=True)

# Each forecast contains:
# - Static fields: month, curator, manager, object_title
# - characteristics dict: {"Sales Volume": "1000", "Priority": "High", "Region": "North"}
for forecast in forecasts:
    print(f"Forecast for {forecast.month}: {forecast.characteristics}")

Example 4: Data Validation Pipeline

Build a validation pipeline with custom business rules:

from serializable_excel import ExcelModel, Column

def validate_email(value: str) -> str:
    """Validate and normalize email"""
    if value and '@' not in value:
        raise ValueError(f"Invalid email: {value}")
    return value.strip().lower()

def validate_age(value: int) -> int:
    """Validate age range"""
    if not (0 <= value <= 150):
        raise ValueError(f"Age must be 0-150, got: {value}")
    return value

class UserModel(ExcelModel):
    name: str = Column(header="Name", required=True)
    age: int = Column(header="Age", validator=validate_age)
    email: str = Column(header="Email", validator=validate_email)

# Read and validate data
try:
    users = UserModel.from_excel("users.xlsx")
    print(f"Successfully imported {len(users)} users")
except ValueError as e:
    print(f"Validation error: {e}")

Example 5: Export Database Models

Export SQLAlchemy models to Excel with relationship handling:

from serializable_excel import ExcelModel, Column

def get_curator_name(model) -> str:
    """Extract curator name from relationship"""
    return model.curator.full_name if model.curator else ""

def get_object_title(model) -> str:
    """Get object title with fallback"""
    return model.object.title if model.object else model.object_title or ""

class ForecastExportModel(ExcelModel):
    month: str = Column(header="Month")
    curator: str = Column(header="Curator", getter=get_curator_name)
    manager: str = Column(header="Manager", getter=lambda m: m.manager.full_name)
    object_title: str = Column(header="Object", getter=get_object_title)

# Export SQLAlchemy models
from sqlalchemy.orm import Session
forecasts = db.query(Forecast).all()
ForecastExportModel.to_excel(forecasts, "export.xlsx")

Example 6: Cell Styling and Highlighting

Export data with conditional cell styling to highlight important information:

from serializable_excel import ExcelModel, Column, CellStyle, Colors

def highlight_age(cell_value, row_data, column_name, row_index):
    """Highlight age based on value"""
    if cell_value and cell_value > 30:
        return CellStyle(fill_color=Colors.WARNING, font_bold=True)
    return CellStyle(fill_color=Colors.UNCHANGED)

def highlight_email(cell_value, row_data, column_name, row_index):
    """Highlight email if contains 'example'"""
    if cell_value and "example" in cell_value:
        return CellStyle(fill_color=Colors.INFO, font_italic=True)
    return None

class UserModel(ExcelModel):
    name: str = Column(header="Name")
    age: int = Column(header="Age", getter_cell_color=highlight_age)
    email: str = Column(header="Email", getter_cell_color=highlight_email)

users = [
    UserModel(name="Alice", age=25, email="alice@example.com"),
    UserModel(name="Bob", age=35, email="bob@example.com"),
]

UserModel.to_excel(users, "highlighted_users.xlsx")
# Age > 30 will be orange and bold
# Emails with 'example' will be light blue and italic

Example 7: Web API Integration

Use SerializableExcel with FastAPI or other web frameworks to handle Excel uploads and downloads:

from io import BytesIO
from fastapi import FastAPI, UploadFile, File
from fastapi.responses import StreamingResponse
from serializable_excel import ExcelModel, Column

app = FastAPI()

class UserModel(ExcelModel):
    name: str = Column(header="Name")
    email: str = Column(header="Email")
    age: int = Column(header="Age")

@app.post("/upload")
async def upload_excel(file: UploadFile = File(...)):
    """Import users from uploaded Excel file"""
    # Read bytes from uploaded file
    file_bytes = await file.read()

    # Parse Excel directly from bytes
    users = UserModel.from_excel(file_bytes)

    return {"imported": len(users), "users": [u.model_dump() for u in users]}

@app.get("/download")
async def download_excel():
    """Export users to Excel and return as download"""
    # Get users from database
    users = [
        UserModel(name="Alice", email="alice@example.com", age=30),
        UserModel(name="Bob", email="bob@example.com", age=25),
    ]

    # Generate Excel as bytes
    excel_bytes = UserModel.to_excel(users, return_bytes=True)

    # Return as streaming response
    return StreamingResponse(
        BytesIO(excel_bytes),
        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        headers={"Content-Disposition": "attachment; filename=users.xlsx"}
    )

@app.post("/transform")
async def transform_excel(file: UploadFile = File(...)):
    """Process Excel file and return modified version"""
    file_bytes = await file.read()

    # Parse and modify data
    users = UserModel.from_excel(file_bytes)
    for user in users:
        user.email = user.email.lower()

    # Return transformed Excel
    result_bytes = UserModel.to_excel(users, return_bytes=True)
    return StreamingResponse(
        BytesIO(result_bytes),
        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        headers={"Content-Disposition": "attachment; filename=transformed.xlsx"}
    )

Example 8: Flask Integration

Using SerializableExcel with Flask:

from io import BytesIO
from flask import Flask, request, send_file
from serializable_excel import ExcelModel, Column

app = Flask(__name__)

class ProductModel(ExcelModel):
    sku: str = Column(header="SKU")
    name: str = Column(header="Product Name")
    price: float = Column(header="Price")

@app.route("/upload", methods=["POST"])
def upload():
    """Upload and parse Excel file"""
    file = request.files["file"]
    products = ProductModel.from_excel(file.read())
    return {"count": len(products)}

@app.route("/download")
def download():
    """Generate and download Excel file"""
    products = [
        ProductModel(sku="A001", name="Widget", price=9.99),
        ProductModel(sku="A002", name="Gadget", price=19.99),
    ]

    excel_bytes = ProductModel.to_excel(products, return_bytes=True)

    return send_file(
        BytesIO(excel_bytes),
        mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        as_attachment=True,
        download_name="products.xlsx"
    )

Example 9: Custom Column Ordering

Control the order of columns in exported Excel files:

from typing import Optional, Dict
from serializable_excel import ExcelModel, Column, DynamicColumn

class ForecastModel(ExcelModel):
    month: str = Column(header="Month")
    manager: str = Column(header="Manager")
    characteristics: dict = DynamicColumn()

# Order static columns using a function
def static_order(header: str) -> Optional[int]:
    """Manager first, then Month"""
    order_map = {"Manager": 1, "Month": 2}
    return order_map.get(header)

# Order dynamic columns using order_layer from database
def dynamic_order(orders: Dict[str, int]) -> Dict[str, int]:
    """
    Normalize dynamic column orders based on order_layer.
    Columns with same order are sorted alphabetically.
    """
    # Simulate fetching order_layer from database
    initial_orders = {"Sales": 1, "Priority": 5, "Status": 10}

    # Update with database values
    for key in orders:
        if key in initial_orders:
            orders[key] = initial_orders[key]

    # Normalize: sort by order and create sequential numbers (1, 5, 10 -> 1, 2, 3)
    sorted_items = sorted(orders.items(), key=lambda x: x[1])
    return {title: idx + 1 for idx, (title, _) in enumerate(sorted_items)}

forecasts = [
    ForecastModel(
        month="2024-01",
        manager="Alice",
        characteristics={"Sales": 150, "Priority": "High", "Status": "Active"}
    )
]

# Export with custom column order
ForecastModel.to_excel(
    forecasts,
    "forecasts.xlsx",
    column_order=static_order,
    dynamic_column_order=dynamic_order
)
# Result: Manager, Month, Sales, Priority, Status
# (Dynamic columns can appear before static if they have lower order numbers)

# Or use a dictionary for static columns
column_order_dict = {"Email": 1, "Name": 2, "Age": 3}
UserModel.to_excel(users, "users.xlsx", column_order=column_order_dict)

Next Steps

  • Advanced Usage - Learn about advanced features like dynamic columns, validators, cell styling, and column ordering

  • API Reference - Full API reference