ThinkPHP导出Excel中文乱码主因是输出缓冲污染、字符集未生效及Office解析适配不足;须清空缓冲(ob_end_clean)、确保UTF-8数据流纯净、正确设文件头与格式,同时MySQL连接、字体、日期格式、CSV BOM等均需规范处理。

ThinkPHP导出Excel出现中文乱码,核心原因不是编码声明写得不够多,而是输出缓冲区被污染、字符集未真正生效、或生成逻辑未适配Office解析机制。修复要从三处下手:清空缓冲、确保UTF-8数据流纯净、正确设置文件头与格式。
必须在导出前调用 ob_end_clean()
这是最常被忽略却最关键的一环。只要导出前有任何 echo、var_dump、调试日志、甚至模板里多出的空格或BOM,都会被写入响应体开头,破坏Excel二进制结构。
- 在导出方法第一行就加
ob_end_clean();——不是ob_clean(),也不是ob_flush() - 检查是否被中间件、Hook、日志组件提前输出内容(比如开启debug模式时自动打印SQL)
- 若使用TP6的StreamResponse返回,也要确认没触发过任何模板渲染或echo
数据库连接和数据本身必须是 utf8mb4
即使表结构设为utf8mb4,PHP连接MySQL时没生效SET NAMES utf8mb4,查出来的数据在内存里就是乱码字节,导出自然还是问号。
Excel/WPS 公式大师。用大白话描述需求,直接给出可用的公式、函数组合和数据处理方案,并解释每一段的作用。当用户提到"Excel 公式"、"表格函数"、"VLOOKUP 怎么用"、"XLOOKUP"、"LET"、"LAMBDA"、"动态数组"、"这个公式报错了"、"#N/A"、"#REF!"、"
- 检查
config/database.php中是否明确配置'charset' => 'utf8mb4' - 运行一句验证SQL:
Db::query("SELECT CHARSET('你好')")[0]['CHARSET(\'你好\')'],结果必须是utf8mb4 - 避免用
mysql_query("SET NAMES utf8")这类旧写法,TP6中应靠配置驱动层自动处理
Excel导出需设SimSun字体 + 正确处理日期
中文显示为方框或替换字体,通常是因为用了非Office内置字体;日期变成44562这类数字,则是没分步设置单元格类型与格式码。
立即学习“PHP免费学习笔记(深入)”;
- 全局设置字体:
$spreadsheet->getDefaultStyle()->getFont()->setName('SimSun');(禁用“微软雅黑”“黑体”等) - 写入日期字段必须两步走:
→ 先用setValueExplicit(strtotime($date), DataType::TYPE_NUMERIC)
→ 再用getStyle()->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_DATE_DATETIME) - 响应头只需
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,charset=utf-8可省略,对.xlsx无效
CSV导出必须手动加 UTF-8 BOM
Excel for Windows默认按ANSI(GBK)解析CSV,不加BOM就会把UTF-8中文全读成乱码,而记事本能正常打开只是因为它自动检测了BOM。
- 在写入第一行数据前,输出BOM:
echo "\xEF\xBB\xBF"; - 再调用
fputcsv($fp, ['ID', '姓名', '电话']) - 不要依赖header中的charset参数,它对CSV解析无影响


















