High‑Performance Excel Export in PHP Using the php‑ext‑xlswriter Extension
This article introduces the php‑ext‑xlswriter C extension for PHP, outlines its features, shows how to install it (including Docker commands), compares its speed with PHPSpreadsheet and PHP_XLSXWriter, and provides complete sample code for generating large Excel files efficiently.
The php‑ext‑xlswriter extension is a PHP C‑extension designed to improve performance when exporting large datasets to Excel 2007+ XLSX files, supporting Windows and Linux, and offering features such as full Excel format compatibility, merged cells, charts, data validation, images, and memory‑optimized writing.
Key Features – Writing:
100% compatible Excel XLSX file
完整的 Excel 格式
合并单元格
定义工作表名称
过滤器
图表
数据验证和下拉列表
工作表 PNG/JPEG 图像
用于写入大文件的内存优化模式
适用于 Linux,FreeBSD,OpenBSD,OS X,Windows
编译为 32 位和 64 位
FreeBSD 许可证
唯一的依赖是 zlibKey Features – Reading:
完整读取数据
光标读取数据
按数据类型读取
xlsx 转 CSV
性能对比
先感谢网友提供数据Installation
Source code can be cloned from GitHub and the IDE helper installed via Composer:
github源码: https://github.com/viest/php-ext-xlswriter
xlswriter文档: https://xlswriter-docs.viest.me/zh-cn/an-zhuang/huan-jing-yao-qiu
composer require viest/php-ext-xlswriter-ide-helper:dev-masterWhen Docker is used, the extension can be installed with the following commands:
docker exec -it php72-fpm bash
cd /usr/local/bin
pecl install xlswriter
docker-php-ext-enable xlswriter
php -m
php --ri xlswriter
Version => 1.3.6
docker restart php72-fpmPerformance Test
Test data consisted of 20 columns, each containing 19 English letters. The xlswriter extension generated the file in about 1.5 seconds for 50,000 rows, outperforming PHPSpreadsheet and PHP_XLSXWriter.
Sample Export Code
private function rankPersonExport($activityInfo, $list) {
$date = date('Y-m-d');
$filename = "{$activityInfo['orgname']}-{$activityInfo['name']}-个人排行榜-{$date}";
$header = ['名次','用户ID','对接账号','姓名','电话','部门ID','一级部门','二级部门','三级部门','总积分','最后积分时间','毫秒'];
if (!empty($activityInfo['ext'])) {
$extArr = json_decode($activityInfo['ext'], true);
foreach ($extArr as $errItem) {
array_push($header, $errItem['name']);
}
}
$listVal = [];
foreach($list as $v){
$temp = [
$v['rank'], $v['userid'], $v['userName'], $v['nickName'], $v['phone'],
$v['departid'], $v['topDepartName'], $v['secDepartName'], $v['thirdDepartName'],
$v['score'], $v['updatetime'], $v['micro']
];
if (!empty($v['ext'])) {
$extArr = explode('|', $v['ext']);
foreach ($extArr as $k2 => $v2) {
$errItemArr = explode('^', $v2);
array_push($temp, $errItemArr[1]);
}
}
array_push($listVal, $temp);
}
$re = downloadXLSX($filename, $header, $listVal);
if($re){
return $this->output(0, $re);
} else {
return $this->output(1, 'success');
}
}
function getTmpDir(): string {
$tmp = ini_get('upload_tmp_dir');
if ($tmp !== False && file_exists($tmp)) {
return realpath($tmp);
}
return realpath(sys_get_temp_dir());
}
/**
* download xlsx file
* @param string $filename
* @param array $header
* @param array $list
* @return string errmsg
*/
function downloadXLSX(string $filename, array $header, array $list): string {
try {
$config = ['path' => getTmpDir() . '/'];
$excel = (new \Vtiful\Kernel\Excel($config))->fileName($filename.'.xlsx', 'Sheet1');
$fileHandle = $excel->getHandle();
$format1 = new \Vtiful\Kernel\Format($fileHandle);
$format2 = new \Vtiful\Kernel\Format($fileHandle);
$titleStyle = $format1->fontSize(16)->bold()->font("Calibri")
->align(\Vtiful\Kernel\Format::FORMAT_ALIGN_CENTER, \Vtiful\Kernel\Format::FORMAT_ALIGN_VERTICAL_CENTER)
->toResource();
$globalStyle = $format2->fontSize(10)->font("Calibri")
->align(\Vtiful\Kernel\Format::FORMAT_ALIGN_CENTER, \Vtiful\Kernel\Format::FORMAT_ALIGN_VERTICAL_CENTER)
->border(\Vtiful\Kernel\Format::BORDER_THIN)->toResource();
$headerLen = count($header);
array_unshift($list, $header);
$title = array_fill(1, $headerLen - 1, '');
$title[0] = $filename;
array_unshift($list, $title);
$end = strtoupper(chr(65 + $headerLen - 1));
$excel->setColumn("A:{$end}", 15, $globalStyle);
$excel->MergeCells("A1:{$end}1", $filename)->setRow("A1", 25, $titleStyle);
$excel->freezePanes(2, 0);
$filePath = $excel->data($list)->output();
header("Content-Disposition:attachment;filename={$filename}.xlsx");
$re = copy($filePath, 'php://output');
@unlink($filePath);
return $re === false ? 'failed to write output' : '';
} catch (\Vtiful\Kernel\Exception $e) {
return $e->getMessage();
}
}When the generated file cannot be opened, the issue is often caused by an outdated Content‑Length header; removing it or calling clearstatcache() resolves the problem.
Overall, php‑ext‑xlswriter provides a fast, memory‑efficient solution for PHP developers needing to export large Excel files, especially when used within Docker environments.
php中文网 Courses
php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.