← All writing

Keep CSV exports from turning user text into spreadsheet formulas

PHP 8.3+Sources checked 2026-09-13

A customer name beginning with = is ordinary text in your database but may be interpreted as a formula when opened in spreadsheet software. CSV quoting protects field boundaries; it does not necessarily force a spreadsheet to treat the field as text.

Separate CSV syntax from spreadsheet behavior

<?php
function spreadsheetText(string $value): string {
    return preg_match('/^[=+@\-\t\r\n]/', $value) ? "'".$value : $value;
}
assert(spreadsheetText('=1+1') === "'=1+1");
assert(spreadsheetText('Acme') === 'Acme');

This illustrates one text-prefix policy. It changes the exported representation and must be tested in the spreadsheet applications you support. It is not a universal guarantee for every parser, whitespace normalization, or import setting.

Preserve typed columns

A negative numeric amount may legitimately begin with a minus sign. Decide column types before applying a text safeguard to everything. A typed spreadsheet format with cells explicitly written as text can be a better contract for untrusted names and descriptions, while numeric columns remain numeric.

Use fputcsv for quoting and separators even after applying your chosen text policy. Hand-built comma concatenation adds a separate problem when a value contains a comma, quote, or newline.

Test hostile-looking prefixes, leading whitespace, embedded delimiters, and multiline values in the actual target application. Keep the original database data unchanged. Label a spreadsheet-oriented export separately from a machine-to-machine CSV if consumers require exact original values. A security transformation that silently changes identifiers can break downstream imports even when it improves spreadsheet handling.

Reference

Official documentation. The examples here illustrate the stated boundary; adapt them to your application and test its failure paths.