当前位置: 首页 > news >正文

PHP 基于模板动态生成 Word 文档:图片 + 表格数据填充全方案(PHPOffice 实战)

在企业级应用中,经常需要根据模板批量生成标准化 Word 文档(如合同、报表、证明等),且需支持文本替换、表格动态生成、图片插入等功能。本文基于 PHPOffice/PHPWord 库,通过封装工具函数 writeDocxByTemplate,实现「模板驱动 + 动态数据填充」的 Word 生成方案,适用于各类业务场景。

一、技术栈与核心依赖

核心库: PHPOffice/PHPWord(PHP 处理 Word 文档的主流库,支持模板替换、图片插入、表格操作等)
功能目标:

  • 文本内容批量替换
  • 动态生成表格(支持多行数据克隆)
  • 图片插入(支持模板占位符替换)
  • 兼容 .docx 格式模板

二、环境准备:安装 PHPWord

首先通过 Composer 安装 PHPOffice/PHPWord:

composer require phpoffice/phpword

注意:PHP 版本需 ≥ 7.1,且确保 php_zip、php_xml 等扩展已启用(处理 Word 文档依赖)。

三、核心实现:通用 Word 生成函数

封装 writeDocxByTemplate 函数,实现「文本 + 表格 + 图片」的一站式填充。函数逻辑如下:

1. 函数完整代码

/*** 根据 Word 模板生成文档(支持文本、表格、图片填充)* @param string $fileName 生成的文件名(含路径,如 'output.docx')* @param string $template 模板路径(如 'template.docx')* @param array $datas 填充数据(格式:['占位符' => '替换值' 或 数组/图片路径])* @return string 生成的文件路径*/
function writeDocxByTemplate($fileName, $template, $datas)
{// 初始化模板处理器$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor($template);foreach ($datas as $key => $value) {// 处理图片(键名以 'img' 开头,如 'imgLogo' 对应模板中的 ${Logo})if (substr($key, 0, 3) === 'img') {$placeholder = substr($key, 3); // 提取占位符(如 'Logo')if (!empty($value)) {// 插入图片(调用自定义图片处理函数)setWordImageValue($templateProcessor, $placeholder, $value);} else {// 图片为空时,用空格替换占位符(避免残留 ${xxx})$templateProcessor->setValue($placeholder, ' ');}} // 处理数组(通常为表格数据,需要克隆行)elseif (is_array($value)) {// 克隆行:$key 为模板中的行标识(如 'product'),克隆次数为数组长度$templateProcessor->cloneRow($key, count($value));// 遍历行数据,替换每行的占位符foreach ($value as $rowIndex => $rowData) {$rowNumber = $rowIndex + 1; // 行号从 1 开始(PHPWord 规则)foreach ($rowData as $macro => $replace) {// 处理行内图片(如 'imgProduct' 对应模板中的 ${Product#1})if (substr($macro, 0, 3) === 'img') {$placeholder = substr($macro, 3) . '#' . $rowNumber;if (!empty($replace)) {setWordImageValue($templateProcessor, $placeholder, $replace);} else {$templateProcessor->setValue($placeholder, ' ');}} // 处理行内文本(如 'productName' 对应模板中的 ${productName#1})else {$placeholder = $macro . '#' . $rowNumber;$templateProcessor->setValue($placeholder, $replace ?? ' ');}}}} // 处理普通文本(直接替换占位符)elseif (is_scalar($value)) {$templateProcessor->setValue($key, $value);}}// 保存生成的文档$templateProcessor->saveAs($fileName);return $fileName;
}/*** 向 Word 模板插入图片(封装图片处理细节)* @param \PhpOffice\PhpWord\TemplateProcessor $templateProcessor 模板处理器* @param string $placeholder 图片占位符(如 'Logo',对应模板中的 ${Logo})* @param string $imagePath 图片路径(支持本地路径或 URL)* @param array $options 图片选项(宽、高,可选)*/
function setWordImageValue($templateProcessor, $placeholder, $imagePath, $options = [])
{// 图片默认尺寸(可根据需求调整)$width = $options['width'] ?? 150; // 宽度(像素)$height = $options['height'] ?? null; // 高度(null 表示按比例缩放)// 检查图片是否存在if (!file_exists($imagePath)) {throw new \Exception("图片不存在:{$imagePath}");}// 获取图片信息(类型、尺寸)$imageInfo = getimagesize($imagePath);$imageType = $imageInfo[2] === IMAGETYPE_PNG ? 'image/png' : 'image/jpeg';// 替换模板中的图片占位符$templateProcessor->setImageValue($placeholder,['path' => $imagePath,'type' => $imageType,'width' => $width,'height' => $height,]);
}

2. 函数核心逻辑解析

函数通过遍历 $datas 数组,根据数据类型(文本 / 数组 / 图片)执行不同操作:

  • 文本替换: 直接调用 setValue 替换模板中的 ${占位符};
  • 图片插入: 识别键名以 img 开头的数据(如 ‘imgLogo’ => ‘logo.png’),通过 setImageValue 替换图片占位符;
  • 表格生成: 当数据为数组时,调用 cloneRow 克隆模板中的表格行,再按行号(#1、#2)替换每行数据。

四、模板设计规范

模板文件(.docx)需按以下规则设置占位符,确保数据正确填充:

1. 文本占位符

在 Word 模板中直接输入 ${占位符},如:

标题:${Title}
公司:${Company}
生成日期:${Date}

2. 图片占位符

图片占位符与文本类似,使用 ${图片标识},但需在模板中预留图片位置(可插入一张空白图片作为占位,或直接输入 ${Logo} 文本)。

3. 表格占位符(动态行)

表格需按「一行模板」设计,通过 cloneRow 动态生成多行:

  1. 表格行的「标识占位符」:如 ${Product}(作为整行的克隆标识);
  2. 行内单元格占位符:需包含行号占位符 #,如 KaTeX parse error: Expected '}', got '#' at position 13: {ProductName#̲}、{Price#}(实际填充时会替换为 #1、#2)。

示例表格模板:

产品名称单价数量金额
${ProductName#}${Price#}${Qty#}${Total#}
${Product}

五、使用示例:生成带图片和表格的合同

以下示例演示如何使用 writeDocxByTemplate 生成一份包含公司 logo、产品表格的合同文档。

1. 准备数据

$datas = [// 文本数据'Title' => '产品采购合同','Company' => 'XX科技有限公司','Date' => date('Y年m月d日'),'TotalAmount' => '¥25,000.00',// 图片数据(键名以 'img' 开头)'imgLogo' => 'static/logo.png', // 公司logo'imgSignature' => 'static/signature.png', // 签名图片// 表格数据(数组形式,对应模板中的 ${Product} 行)'Product' => [['ProductName#' => '笔记本电脑','Price#' => '5,000.00','Qty#' => 2,'Total#' => '10,000.00','imgProduct#' => 'static/laptop.png' // 行内图片],['ProductName#' => '打印机','Price#' => '3,000.00','Qty#' => 5,'Total#' => '15,000.00','imgProduct#' => 'static/printer.png']]
];

2. 调用函数生成文档

// 模板路径
$template = 'templates/contract_template.docx';
// 生成的文件名
$outputFile = 'output/contract_' . date('Ymd') . '.docx';// 生成文档
try {$result = writeDocxByTemplate($outputFile, $template, $datas);echo "文档生成成功:{$result}";
} catch (Exception $e) {echo "生成失败:{$e->getMessage()}";
}

3. 效果展示

生成的 Word 文档会自动替换:

  • 文本占位符为实际数据;
  • 图片占位符为指定图片;
  • 表格行根据数组长度动态生成,每行填充对应数据。

五、常见问题与解决方案

1. 占位符未替换

  • 检查 $datas 中的键名是否与模板占位符一致(区分大小写);
  • 确保模板中的占位符格式正确(${占位符},注意英文大括号)。

2. 图片不显示或变形

  • 图片路径需为绝对路径或相对于脚本的相对路径;
  • 通过 setWordImageValue 的 $options 参数指定宽高(如 [‘width’ => 200]);
  • 避免使用过大的图片(建议压缩至 1MB 以内)。

3. 表格行克隆后格式错乱

  • 模板表格需保持「一行模板」,避免合并单元格(复杂表格可能导致克隆异常);
  • 行内占位符必须包含 #(如 ${Name#}),否则无法按行替换。

4. 中文乱码

  • 确保模板使用支持中文的字体(如「微软雅黑」「宋体」);
  • PHP 脚本编码为 UTF-8(避免数据本身乱码)。

六、扩展场景

  • 多模板支持:根据业务类型动态选择模板(如 $template = $type == 1 ? ‘template1.docx’ : ‘template2.docx’);
  • 页眉页脚动态设置
http://www.dtcms.com/a/270543.html

相关文章:

  • 使用python 将多个docx文件合并为一个word
  • 【Unity】MiniGame编辑器小游戏(十)连连看【Link】
  • 实时地震分析:AI+Python如何帮我们提前感知大地的怒吼?
  • 使用 Docker 搭建 Go Web 应用开发环境——AI教你学Docker
  • NO.1数据结构绪论|数据结构|逻辑结构|物理结构|算法|算法的度量
  • 从救火到赋能:运维的职责演进与云原生时代的未来图景
  • 聚铭安全管家平台2.0实战解码 | 安服篇(二):无人值守自动化封禁
  • 【Unity】MiniGame编辑器小游戏(十一)消消乐【Crush】
  • 本地Qwen中医问诊小程序系统开发
  • 【目标检测之Ultralytics预测框颜色修改】
  • OpenCV哈希算法------Marr-Hildreth 边缘检测哈希算法
  • 基于DeepSeek构建的openGauss AI智能优化助手:数据库性能提升新利器
  • 微软 Bluetooth LE Explorer 实用工具的详细使用分析
  • 【DOCKER】-3 数据持久化
  • OpenCV图像增强秘籍:高通滤波与特效艺术
  • Web 前端框架选型:React、Vue 和 Angular 的对比与实践
  • PiscTrace深蹲计数功能实现:基于 YOLO-Pose 和人体关键点分析
  • 【python处理excel】B列单元格中的内容都是回车换行的,把这些信息拆成多行多列,并且把A列对应的信息带过去。
  • A模块 系统与网络安全 第四门课 弹性交换网络-2
  • C#正则表达式全面详解:从基础到高级应用
  • 跨部门协作难以对齐项目进度,如何促进协同
  • Rust #[] 语法
  • PHP语法高级篇(一):日期时间处理和包含文件
  • 【系统与工具】Linux——Linux简介、安装、简单使用
  • 详解Kafka重平衡机制详解
  • MySQL8.0基于GTID的组复制分布式集群的环境部署
  • mysql互为主从失效,重新同步
  • 超越公有云:在裸金属服务器上构建低成本、高性能的静态资源服务
  • 创客匠人:创始人 IP 打造中 “放下身段” 的深层逻辑
  • 身份证识别api-便捷生活与安全社会的双重保障