SpreadSheet-Coding.com

PHPSpreadsheet · Google Sheets API · Excel

Spreadsheets, driven by code.

Hands-on PHP tutorials for working with Excel and Google Sheets — read and write .xlsx, convert files to JSON, stream downloads in the browser, and insert images, formulas, and styling. Every guide ships with code you can copy, run, and adapt.

injection.php View article
<?php

require 'vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Writer\Csv;

$rows = [
    ['Ada Lovelace', 'Great service'],
    ['Grace Hopper', '=2+5'],
    ['Evil User',    '=HYPERLINK("http://attacker.example","Refund")'],
    ['Bjarne S.',    '-7 (owed a credit)'],
];

function looksLikeFormula(string $value): bool
{
    return $value !== '' && in_array($value[0], ['=', '+', '-', '@', "\t", "\r"], true);
}

// 1. Naive export: fromArray auto-detects "=..." as a formula.
$bad = new Spreadsheet();
$badSheet = $bad->getActiveSheet();
$badSheet->fromArray($rows, null, 'A1');
(new Xlsx($bad))->save('export-unsafe.xlsx');

echo "Naive export — what the cell actually became:\n";
echo "  B2 value          : " . $badSheet->getCell('B2')->getValue() . "\n";
echo "  B2 calculated     : " . $badSheet->getCell('B2')->getCalculatedValue() . "\n";
echo "  (the '=2+5' the user typed is now a LIVE formula that evaluates to 7)\n\n";

// 2. XLSX fix: force untrusted cells to explicit strings.
$safe = new Spreadsheet();
$safeSheet = $safe->getActiveSheet();
$r = 1;
foreach ($rows as $line) {
    $col = 'A';
    foreach ($line as $value) {
        $safeSheet->setCellValueExplicit($col . $r, (string) $value, DataType::TYPE_STRING);
        $col++;
    }
    $r++;
}
(new Xlsx($safe))->save('export-safe.xlsx');

echo "Safe XLSX export — same input, forced to text:\n";
echo "  B2 value          : " . $safeSheet->getCell('B2')->getValue() . "\n";
echo "  B2 calculated     : " . $safeSheet->getCell('B2')->getCalculatedValue() . "\n";
echo "  (stored as text, so it is inert and displays exactly as typed)\n\n";

// 3. CSV has no types: neutralise the leading character with an apostrophe.
$csv = new Spreadsheet();
$csvSheet = $csv->getActiveSheet();
$r = 1;
foreach ($rows as $line) {
    $col = 'A';
    foreach ($line as $value) {
        $value = (string) $value;
        if (looksLikeFormula($value)) {
            $value = "'" . $value;
        }
        $csvSheet->setCellValueExplicit($col . $r, $value, DataType::TYPE_STRING);
        $col++;
    }
    $r++;
}
(new Csv($csv))->save('export-safe.csv');

echo "Safe CSV export (export-safe.csv):\n";
echo rtrim(file_get_contents('export-safe.csv')) . "\n";

The full script from Prevent Formula Injection In Excel Exports In PHP Using PHPSpreadSheet — copy, run, adapt.

IOFactory::load() PhpSpreadsheet
Open any spreadsheet file
getActiveSheet() PhpSpreadsheet
Select the worksheet to fill
fromArray() PhpSpreadsheet
Write many rows at once
getCalculatedValue() PhpSpreadsheet
Read a formula result
save('php://output') PhpSpreadsheet
Stream the file as a download
spreadsheets_values->get() Google Sheets
Read a range of cells
spreadsheets_values->update() Google Sheets
Write a range of cells
spreadsheets->create() Google Sheets
Create a new spreadsheet
json_encode() PHP
Serialize rows to JSON
header() PHP
Send the download headers