Skip to content

Data integrity

Data Validation

write_worksheet(
    rows,
    "out.xlsx",
    data_validations={
        "status": {"type": "list", "values": ["open", "closed", "blocked"],
                   "input_message": "Pick one"},
        "qty":    {"type": "whole_number", "criteria": ">=", "value": 0,
                   "error_message": "Quantity cannot be negative"},
        "score":  {"type": "decimal", "criteria": "between", "min": 0, "max": 100},
    },
)

Types: list (the dropdown), whole_number, decimal, text_length, custom, any. Every rule also takes input_title, input_message, error_title, error_message, error_style (stop, warning, information), ignore_blank and show_dropdown.

Rules cover the column's data rows, never the header. Two limits Excel imposes are raised rather than written into a file it would refuse to open: an inline list is capped at 255 characters including separators, and a fraction given to whole_number or text_length is rejected instead of truncated.

Missing values, NaN and infinity

Excel has no cell type for NaN or inf, so both are written as an empty cell. That is the default, and it means a column of missing data is indistinguishable from a column of blanks. Name a representation to keep them apart:

FastExcel("out.xlsx").format(na_rep="N/A", inf_value="INF").sheet("S", df).save()

write_csv(df, "out.csv", na_rep="N/A", inf_value="INF")

na_rep covers None, an Arrow null and a float NaN as one setting, on purpose: pandas turns NaN in a float column into an Arrow null, so a knob that caught only true NaN would do nothing on the most common input there is. inf_value is separate — infinity is a value, not a missing one — and -inf takes the same text with a leading -, matching Excel's own INF/-INF.

CSV carries no formatting, so every Excel-only option is dropped — float_format, column_formats, header_format, freeze panes, merges, banding, row heights and formats, password, dedupe_strings. Only delimiter and sanitize_formulas apply. Switching a target from .xlsx to .csv therefore silently changes the output, so the builder warns and names what it discarded:

FastExcel("out.csv").format(float_format="0.00").sheet("S", rows).save()
# UserWarning: CSV/TSV output ignores Excel-only options: float_format. …

The data is still written correctly — only the styling is gone.