You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需第三方库实现PHP从SQL导出无报错的XLS/XLSX文件

解决无第三方库导出XLSX/XLS无报错的问题

问题根源

你当前的代码本质是输出制表符分隔的纯文本,只是修改了文件名和HTTP Content-Type,但实际内容和XLSX/XLS的格式完全不匹配——XLSX是基于OpenXML的压缩包格式,XLS是二进制BIFF格式,因此Excel会检测到格式与扩展名不符并报错。


优先实现:无第三方库导出XLSX

XLSX本质是包含特定XML文件的ZIP压缩包,我们可以用PHP内置的ZipArchive类(属于PHP原生扩展,无需额外安装第三方库)来构建标准格式:

代码示例

// DB Connection included by a config.php file
$sql = $db->prepare("SELECT * FROM myTable");
$sql->execute();
$result = $sql->fetchAll(PDO::FETCH_ASSOC);

// 生成符合标准的XLSX文件
function createXLSX($records) {
    if (empty($records)) return false;

    // 创建临时文件存储ZIP内容
    $tempFile = tempnam(sys_get_temp_dir(), 'xlsx');
    $zip = new ZipArchive();
    $zip->open($tempFile, ZipArchive::CREATE | ZipArchive::OVERWRITE);

    // 1. 添加XLSX必需的核心配置文件
    // [Content_Types].xml
    $contentTypes = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
    <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
    <Default Extension="xml" ContentType="application/xml"/>
    <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
    <Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
    <Override PartName="/xl/_rels/workbook.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
</Types>';
    $zip->addFromString('[Content_Types].xml', $contentTypes);

    // _rels/.rels
    $rels = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
    <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
</Relationships>';
    $zip->addFromString('_rels/.rels', $rels);

    // xl/_rels/workbook.xml.rels
    $workbookRels = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
    <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>
</Relationships>';
    $zip->addFromString('xl/_rels/workbook.xml.rels', $workbookRels);

    // xl/workbook.xml
    $workbook = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
    <sheets>
        <sheet name="导出数据" sheetId="1" r:id="rId1"/>
    </sheets>
</workbook>';
    $zip->addFromString('xl/workbook.xml', $workbook);

    // 2. 构建工作表数据(sheet1.xml)
    $sheetXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
    <sheetData>';

    // 添加表头
    $headers = array_keys($records[0]);
    $sheetXml .= '<row>';
    foreach ($headers as $header) {
        $sheetXml .= '<c t="inlineStr"><is><t>' . htmlspecialchars($header) . '</t></is></c>';
    }
    $sheetXml .= '</row>';

    // 添加数据行
    foreach ($records as $row) {
        $sheetXml .= '<row>';
        foreach ($row as $cell) {
            $cellValue = htmlspecialchars((string)$cell);
            $sheetXml .= '<c t="inlineStr"><is><t>' . $cellValue . '</t></is></c>';
        }
        $sheetXml .= '</row>';
    }

    $sheetXml .= '</sheetData></worksheet>';
    $zip->addFromString('xl/worksheets/sheet1.xml', $sheetXml);

    // 关闭ZIP包
    $zip->close();

    return $tempFile;
}

// 输出XLSX文件
$xlsxFile = createXLSX($result);
if ($xlsxFile) {
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Disposition: attachment; filename=Export.xlsx');
    header('Content-Length: ' . filesize($xlsxFile));
    readfile($xlsxFile);
    unlink($xlsxFile); // 清理临时文件
}
exit;

说明

  • 严格遵循OpenXML标准构建XLSX结构,Excel打开不会有格式报错
  • 所有内容做htmlspecialchars转义,避免XML解析错误
  • 使用临时文件存储ZIP内容,输出后自动删除,无残留文件

导出XLS格式(无第三方库)

XLS是二进制BIFF格式,手动编写完整格式复杂度极高,推荐用HTML表格模拟的方式,Excel可直接识别且无报错:

代码示例

// DB Connection included by a config.php file
$sql = $db->prepare("SELECT * FROM myTable");
$sql->execute();
$result = $sql->fetchAll(PDO::FETCH_ASSOC);

header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename=Export.xls');

// 输出标准HTML表格
echo '<table>';
// 输出表头
echo '<tr>';
foreach (array_keys($result[0]) as $header) {
    echo '<th>' . htmlspecialchars($header) . '</th>';
}
echo '</tr>';
// 输出数据行
foreach ($result as $row) {
    echo '<tr>';
    foreach ($row as $cell) {
        echo '<td>' . htmlspecialchars((string)$cell) . '</td>';
    }
    echo '</tr>';
}
echo '</table>';
exit;

说明

  • 输出标准HTML表格,设置application/vnd.ms-excel的Content-Type,Excel会将其识别为XLS格式
  • 对内容做转义处理,避免特殊字符导致格式混乱
  • 实现简单,无需处理复杂的二进制结构

内容的提问来源于stack exchange,提问作者Trombone0904

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 11:10:14