PhpSpreadsheet导入HTML表格时如何保留单元格内的富文本格式
PhpSpreadsheet转换HTML表格丢失行内格式的解决方法
问题成因
- 官方内置的
Html读取器默认仅提取HTML标签包裹的纯文本,完全忽略行内标签携带的样式属性,<strong>加粗、<em>斜体这类行内格式会被直接丢弃 - HTML解析逻辑默认折叠标签前后的连续空白,读取器处理时会直接清除这类空白,最终出现
Hi mi name is <strong>SAM</strong> and i feel good被拼接为Hi mi name isSAMand i feel good的异常
实现思路
原生Html读取器本身不支持单元格内混合格式的解析,需要手动拆分HTML单元格的文本片段,调用PhpSpreadsheet的RichText类给不同片段绑定对应的字体样式,最终实现和HTML一致的行内格式效果。
核心实现步骤
- 空白预处理
对所有单元格内的HTML内容做正则替换,把标签前后的连续换行、缩进等空白统一替换为单个普通空格,避免被解析器折叠清除,保证文本的间隔和原始HTML一致 - HTML结构解析
用内置的DOMDocument加载单元格内容,遍历所有子节点,区分纯文本节点和带格式的元素节点 - 富文本组装
- 纯文本节点直接写入
RichText对象,使用默认字体样式 - 带格式的节点根据标签类型(
<strong>/<em>等)生成对应的TextRun实例,给实例绑定加粗、斜体等字体属性
- 纯文本节点直接写入
- 常规输出
把组装完成的RichText对象赋值给对应单元格,后续走正常的Excel文件输出逻辑即可
可参考的核心代码片段
require 'vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\RichText\RichText; $spreadsheet = new Spreadsheet(); $worksheet = $spreadsheet->getActiveSheet(); // 示例待处理的TD原始内容 $tdContent = " Hi mi name is <strong>SAM</strong> and i feel good "; // 预处理空白,避免被折叠 $tdContent = preg_replace('/\s*</', ' <', $tdContent); $tdContent = preg_replace('/>\s*/', '> ', $tdContent); $tdContent = trim(preg_replace('/\s+/', ' ', $tdContent)); // 解析DOM结构 libxml_use_internal_errors(true); $dom = new DOMDocument(); $dom->loadHTML('<?xml encoding="utf-8" ?>' . $tdContent); $contentNode = $dom->getElementsByTagName('body')->item(0); // 组装富文本 $richText = new RichText(); foreach ($contentNode->childNodes as $node) { if ($node->nodeType === XML_TEXT_NODE) { $richText->createText($node->nodeValue); } elseif ($node->nodeType === XML_ELEMENT_NODE) { $textRun = $richText->createTextRun($node->nodeValue); $font = $textRun->getFont(); // 匹配strong标签设置加粗 if ($node->tagName === 'strong') { $font->setBold(true); } // 匹配em标签设置斜体 if ($node->tagName === 'em') { $font->setItalic(true); } } } // 赋值给对应单元格 $worksheet->getCell('A1')->setValue($richText); // 原有输出逻辑保持不变 header('Content-Type: application/vnd.ms-excel'); header('Content-Disposition: attachment;filename="export.xls"'); header('Cache-Control: max-age=0'); $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, 'Xls'); $writer->save('php://output');
扩展说明
- 如需支持更多行内格式(如字体颜色、下划线、删除线),可在解析DOM节点时读取元素的
style属性,给TextRun的Font对象调用对应set方法即可实现 - 遇到嵌套标签场景(如
<strong><em>加粗斜体文本</em></strong>),需要调整DOM遍历逻辑做递归解析,将嵌套的样式属性叠加到对应文本片段上 - 不建议直接使用原生
Html读取器加载完整HTML表格来处理这类需求,因为其本身不支持富文本场景,需要逐单元格走上述组装逻辑
内容的提问来源于stack exchange,提问作者Giuseppe Lodi Rizzini
相关产品推荐
相关产品推荐

