☰
PHPWord 表格操作完全指南:addTable/addRow/addCell 与单元格合并实战
2026/9/28 3:00:18 网站建设 项目流程
  • 后端

【免费下载链接】PHPWord

A pure PHP library for reading and writing word processing documents

项目地址:https://gitcode.com/gh_mirrors/ph/PHPWord
点击查看免费下载

本文基于 PHPWord 官方文档 docs/usage/elements/table.md 展开,系统讲解在 Section 中创建表格、行、单元格的核心 API,以及通过addTableStyle定义可复用表格样式、通过gridSpan与vMerge实现跨列与跨行合并的完整用法。读完本文,你将能够在 PHPWord 中从零构建基础表格、精致样式表格、合并单元格表格、嵌套表格与浮动定位表格,并理解其底层实现原理。

一、表格的创建:addTable / addRow / addCell

在 PHPWord 中,表格是挂在 Section 之下的容器元素,由「表格 → 行 → 单元格」三层结构组成。创建一张表格只需三个方法调用:

<?php $table = $section->addTable([$tableStyle]); $table->addRow([$height], [$rowStyle]); $cell = $table->addCell($width, [$cellStyle]);
  • $section->addTable($style):向当前 Section 添加一个表格。$style既可以传入内联样式数组,也可以传入已注册的样式名称(字符串),不传则使用默认样式。
  • $table->addRow($height, $style):添加一行,$height指定行高(单位 twip),$style为行样式数组。
  • $table->addCell($width, $style):添加单元格,$width为单元格宽度(单位 twip),$style为单元格样式数组。

从源码看,Table::addRow() 会创建Row对象并设置其父容器为表格;Table::addCell() 则将单元格挂到当前(最后添加的)行上。单元格继承自AbstractContainer(见 Element/Cell.php),因此addCell()的返回值可以直接调用addText()、addImage()等容器方法写入内容,形成$table->addCell($width)->addText('...')的链式写法。

基础表格示例

<?php $phpWord = new PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $rows = 10; $cols = 5; $table = $section->addTable(); for ($r = 1; $r <= $rows; ++$r) { $table->addRow(); for ($c = 1; $c <= $cols; ++$c) { $table->addCell(1750)->addText("Row {$r}, Cell {$c}"); } }

以上代码生成一张 10 行 5 列、每列宽 1750 twip 的基础表格,完整可运行版本见 samples/Sample_09_Tables.php 的第 1 节。

二、用 addTableStyle 定义可复用表格样式

当同一张表格样式需要被多次使用(例如整套文档统一边框与表头底色)时,推荐先用PhpWord::addTableStyle()注册命名样式,再通过样式名引用:

<?php $tableStyle = array( 'borderColor' => '006699', 'borderSize' => 6, 'cellMargin' => 50 ); $firstRowStyle = array('bgColor' => '66BBFF'); $phpWord->addTableStyle('myTable', $tableStyle, $firstRowStyle); $table = $section->addTable('myTable');

addTableStyle(string $styleName, mixed $styleTable, mixed $styleFirstRow = null)的三个参数分别是:样式名称、表格样式数组、首行样式数组(可选)。从 PhpWord::addTableStyle() 的方法签名可以看到,首行样式是独立于表格样式传入的。

其底层实现位于 Style/Table.php 的构造函数:当传入$firstRowStyle时,会先克隆当前表格样式,禁用边框内部线(borderInside*)、单元格边距(cellMargin*)与cellSpacing等「仅表格层生效」的属性(对应 getTableOnlyProperty / setTableOnlyProperty 的保护逻辑),再套用首行样式。这意味着首行样式天然继承表格样式的外边框与底色基调,只需覆盖需要差异化的属性即可。

进阶:首行 + 单元格样式组合

samples/Sample_09_Tables.php第 2 节给出了更完整的组合用法,将表格样式、首行样式、单元格样式、字体样式四层叠加:

<?php $fancyTableStyleName = 'Fancy Table'; $fancyTableStyle = [ 'borderSize' => 6, 'borderColor' => '006699', 'cellMargin' => 80, 'alignment' => PhpOffice\PhpWord\SimpleType\JcTable::CENTER, 'cellSpacing' => 50, ]; $fancyTableFirstRowStyle = [ 'borderBottomSize' => 18, 'borderBottomColor' => '0000FF', 'bgColor' => '66BBFF', ]; $fancyTableCellStyle = ['valign' => 'center']; $fancyTableCellBtlrStyle = [ 'valign' => 'center', 'textDirection' => PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR, ]; $fancyTableFontStyle = ['bold' => true]; $phpWord->addTableStyle($fancyTableStyleName, $fancyTableStyle, $fancyTableFirstRowStyle); $table = $section->addTable($fancyTableStyleName); $table->addRow(900); $table->addCell(2000, $fancyTableCellStyle)->addText('Row 1', $fancyTableFontStyle); // ... 其余单元格同理

这里alignment使用的是表格专用的对齐枚举JcTable(start/center/end,见 SimpleType/JcTable.php),textDirection则来自Style\Cell的常量TEXT_DIR_BTLR(自底向上、从左到右的文字方向,见 Style/Cell.php)。

三、表格、行、单元格的完整样式参数

表格级样式(Table)

完整的表格样式选项在 docs/usage/styles/table.md 中定义,对应源码类为 Style/Table.php,其继承自Border,因此边框类参数全部可用:

参数说明取值/示例
alignment表格对齐方式见SimpleType\JcTable与SimpleType\Jc类常量(start/center/end等)
bgColor表格背景色如'9966CC'
border(Top\|Right\|Bottom\|Left)Color各边边框颜色如'9966CC'
border(Top\|Right\|Bottom\|Left)Size各边边框粗细,单位 twip整数
cellMargin(Top\|Right\|Bottom\|Left)单元格边距,单位 twip整数
indent表格相对左页边距的缩进必须是ComplexType\TblWidth实例
width表格宽度以五十分之一百分比(pct)或二十分之一磅(dxa/twip)为单位
unit宽度单位SimpleType\TblWidth常量之一,默认auto
layout表格布局fixed或autofit(Style\Table::LAYOUT_AUTO/LAYOUT_FIXED,见 Style/Table.php)
cellSpacing单元格间距,单位 twip整数
position浮动表格定位见下文「浮动表格定位选项」
bidiVisual以从右到左方式呈现表格布尔值

宽度单位枚举见 SimpleType/TblWidth.php:nil(无宽度)、auto(自动计算,默认)、pct(五十分之一百分比)、dxa(二十分之一磅,即 twip)。设置百分比宽度时需自行换算:50% 写成50 * 50(=2500),示例见Sample_09_Tables.php第 5 节:['width' => 50 * 50, 'unit' => 'pct', 'alignment' => JcTable::CENTER]。

表格布局枚举LAYOUT_AUTO(autofit,默认)与LAYOUT_FIXED(fixed)定义于 Style/Table.php,对应 OOXML 标准w:tblLayout的两种取值。

浮动表格定位选项(position)

当表格需要脱离文档流、环绕于文字周围时,使用position数组开启浮动定位:

参数说明取值
leftFromText表格左侧距文字的距离,twip整数
rightFromText表格右侧距文字的距离,twip整数
topFromText表格顶部距文字的距离,twip整数
bottomFromText表格底部距文字的距离,twip整数
vertAnchor表格垂直锚点Style\TablePosition::VANCHOR_*常量
horzAnchor表格水平锚点Style\TablePosition::HANCHOR_*常量
tblpXSpec相对锚点的水平对齐Style\TablePosition::XALIGN_*常量
tblpX距锚点的绝对水平距离,twip整数
tblpYSpec相对锚点的垂直对齐Style\TablePosition::YALIGN_*常量
tblpY距锚点的绝对垂直距离,twip整数

Sample_09_Tables.php第 6 节演示了结合Converter::cmToTwip()做单位换算的浮动表格:

<?php use PhpOffice\PhpWord\Shared\Converter; use PhpOffice\PhpWord\Style\TablePosition; $table = $section->addTable([ 'borderSize' => 6, 'borderColor' => '999999', 'position' => [ 'vertAnchor' => TablePosition::VANCHOR_TEXT, 'bottomFromText' => Converter::cmToTwip(1), ], ]);

行级样式(Row)

行样式定义于 Style/Row.php,共三个布尔开关:

参数说明默认
cantSplit行不允许跨页断开false
exactHeight行高为精确值(否则为「至少」高度)false
tblHeader跨页时重复表头行false

其中tblHeader用于长表格分页时每页顶部重复显示标题行,cantSplit保证一行内容不被拆到两页。需要说明的是,ODText 写入器将行高序列化为原生 ODF 表格行样式:精确高度使用style:row-height,「至少」高度使用style:min-row-height,见 docs/usage/styles/table.md。

单元格级样式(Cell)

单元格样式对应 Style/Cell.php,同样继承Border:

参数说明取值/示例
bgColor单元格背景色如'9966CC'
border(Top\|Right\|Bottom\|Left)Color各边边框颜色如'9966CC'
border(Top\|Right\|Bottom\|Left)Size各边边框粗细,twip整数
border(Top\|Right\|Bottom\|Left)Style边框线型SimpleType\Border常量
gridSpan跨列数(colspan)整数,如 5
textDirection(btLr\|tbRl)文字方向Style\Cell::TEXT_DIR_BTLR/TEXT_DIR_TBRL(源码中还支持lrTb、lrTbV、tbRlV、tbLrV等常量,见 Style/Cell.php)
valign垂直对齐top、center、both、bottom
vMerge纵向合并restart或continue
width单元格宽度,twip整数

关于 ODText 写入器:单元格边框会被序列化为原生 ODF 表格单元格样式,各边独立写入,因此同一行内非对称边框、不同单元格的不同边框定义都能保留;表格与单元格的bgColor会映射为原生 ODF 背景色,单元格内边距、垂直对齐、文字方向、换行、列跨度、表格对齐与宽度在设置了对应样式时也会一并映射(见 docs/usage/styles/table.md)。

四、单元格合并:gridSpan 跨列、vMerge 跨行

表格合并单元格有两种方式:

  • gridSpan:让一个单元格横跨多列,即 HTML 中的colspan;
  • vMerge:让单元格纵跨多行,即 HTML 中的rowspan,通过restart开启合并、continue延续合并实现。

gridSpan 跨列

文档给出的最简用法:

<?php $cell = $table->addCell(200); $cell->getStyle()->setGridSpan(5);

也可以直接在单元格样式数组中声明(效果等价):

<?php $cell = $table->addCell(200, ['gridSpan' => 5]);

在 Word2007 写入器中,gridSpan与vMerge会被序列化为 OOXML 的w:gridSpan与w:vMerge元素(见 Writer/Word2007/Style/Cell.php),保证生成的 docx 与 Word 原生合并行为一致。

vMerge 跨行

<?php $row1 = $table->addRow(); $row1->addCell(500)->addText('A'); $row1->addCell(1000, ['gridSpan' => 2])->addText('B'); $row1->addCell(500, ['vMerge' => 'restart'])->addText('C'); $row2 = $table->addRow(); $row2->addCell(1500, ['gridSpan' => 3])->addText('D'); $row2->addCell(null, ['vMerge' => 'continue']); // 延续 C 的合并 $row3 = $table->addRow(); $row3->addCell(500)->addText('E'); $row3->addCell(500)->addText('F'); $row3->addCell(500)->addText('G'); $row3->addCell(null, ['vMerge' => 'continue']); // 再次延续

关键规则:

  • 合并起始单元格写'vMerge' => 'restart',后续行对应位置写'vMerge' => 'continue';
  • 延续单元格通常不需要宽度,传null即可;
  • vMerge取值restart/continue对应 Style/Cell.php 中的VMERGE_RESTART与VMERGE_CONTINUE常量。

上述代码对应Sample_09_Tables.php第 3 节的布局示意:

------------------------- | A | B | C | |-----|-----------| | | D | | ------|-----------| | | E | F | G | | -------------------------

Sample_09_Tables.php第 4 节还演示了 gridSpan 与 vMerge 同时作用于同一单元格(如['gridSpan' => 2, 'vMerge' => 'restart'])的复合合并,这是实现「先跨列再跨行」复杂表头布局的常用手法。

五、进阶场景:嵌套表格与 50% 宽度表格

表格单元格本身是容器(AbstractContainer),因此可以在单元格内再嵌表格。Sample_09_Tables.php第 5 节演示了嵌套表格与百分比宽度:

<?php use PhpOffice\PhpWord\SimpleType\JcTable; $table = $section->addTable([ 'width' => 50 * 50, // 50% 宽度(pct 单位下 ×50 换算) 'unit' => 'pct', 'alignment' => JcTable::CENTER, ]); $cell = $table->addRow()->addCell(); $cell->addText('This cell contains nested table.'); $innerCell = $cell->addTable([ 'alignment' => JcTable::CENTER, ])->addRow()->addCell(); $innerCell->addText('Inside nested table');

嵌套时只需在单元格对象上再次调用addTable(),PHPWord 会自动维护父子容器关系;外层表格通过unit => 'pct'+width => 2500实现 50% 相对宽度并居中,内层表格同样居中展示。

六、从源码理解表格的数据结构与列宽计算

从源码结构看,PHPWord 的表格对象模型是纯内存树:

  • Element\Table持有rows数组,提供addRow()、addCell()、getRows()、countColumns()与findFirstDefinedCellWidths()等方法(见 Element/Table.php);
  • Element\Row持有height与cells数组,addCell()创建Element\Cell(见 Element/Row.php);
  • Element\Cell继承自AbstractContainer,宽度与样式在构造时注入(见 Element/Cell.php)。

值得留意的是countColumns()的实现:它遍历所有行并取「最大单元格数」作为列数,而findFirstDefinedCellWidths()则按行序收集第一处定义了宽度的列宽序列(见 Element/Table.php)。这说明 PHPWord 允许不同行的单元格数量不一致,最终列宽由各列单元格宽度协调决定——这也正是合并单元格场景下null宽度(延续格)能被正确推算的原因。

七、运行示例与深入阅读

Sample_09_Tables.php可在仓库根目录直接通过命令行或浏览器运行:

php samples/Sample_09_Tables.php

它依次输出基础表格、Fancy Table、colspan/rowspan 合并表格、嵌套表格与浮动定位表格,是本文全部要点的可运行合集。

  • 核心文档:docs/usage/elements/table.md、docs/usage/styles/table.md
  • 完整示例:samples/Sample_09_Tables.php
  • 元素实现:src/PhpWord/Element/Table.php、src/PhpWord/Element/Row.php、src/PhpWord/Element/Cell.php
  • 样式实现:src/PhpWord/Style/Table.php、src/PhpWord/Style/Row.php、src/PhpWord/Style/Cell.php
  • 枚举定义:src/PhpWord/SimpleType/JcTable.php、src/PhpWord/SimpleType/TblWidth.php
  • OOXML 序列化:src/PhpWord/Writer/Word2007/Style/Cell.php
  • 后端

【免费下载链接】PHPWord

A pure PHP library for reading and writing word processing documents

项目地址:https://gitcode.com/gh_mirrors/ph/PHPWord
点击查看免费下载

相关推荐

上一篇:Android Studio中文界面终极指南:5分钟打造高效开发环境 🚀
下一篇:llama.cpp Server buttons-top 主题指南:把 Send/Stop 操作按钮固定在页面顶部(PowerInfer 仓库实例)

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询