tp5使用PHPWord(下载引入/composer与模板/生成方式搭配使用)

时间:2024-02-24 13:30:19

推荐使用模板方式,使用方便,样式也好调一些,大部分要求也都可以实现;生成方式目前我是在做表格单元格合并的时候用到过,下面会介绍使用方式(模板方式在单元格中插入一个小表格,然后用cloneRow复制小表格也可以实现,但是这样比较别扭,不完美)

一:引入

tp5.0tp5.1

1composer方式(推荐)

a:根目录下执行:composer require phpoffice/phpword

b:引入:

use PhpOffice\PhpWord\PhpWord;

2:下载引入方式

a:下载PHPWord

地址:https://pan.baidu.com/s/1H20kNc-67hT7fkZ5SI73WQ

提取码:zxcv

b:放到项目根目录extend文件夹下,目录结构如下:

  

c:引入

use PhpOffice\PhpWord\PhpWord;

二:模板方式导出


ob_clean(); //防止乱码
$file = \'../extend/files/pdf.docx\';//路径,可更改
$PHPWord = new PhpWord(); $template = $PHPWord->loadTemplate($file);//加载模板 $template->setValue(\'title\', \'标题\');//替换值 $file = date(\'Y-m-d-H-i-s\') . \'.docx\';//文件名 $encoded_filename = urlencode($file); // 将文件名进行urlencode转码 $file = str_replace(\'+\', \'%20\', $encoded_filename); header("Content-Description: File Transfer"); header(\'Content-Disposition: attachment; filename="\' . $file . \'"\'); header(\'Content-Type:application/vnd.openxmlformats-officedocument.wordprocessingml.document\'); header(\'Content-Transfer-Encoding: binary\'); header(\'Cache-Control: must-revalidate, post-check=0, pre-check=0\'); header(\'Expires: 0\'); $template->saveAs(\'php://output\');

格式:

//替换值(模板内为${title},如模板图)
$template->setValue(\'title\', \'标题\');

//选择框(模板内为check0和check1<字体是【Wingdings 2】>,替换时R是选中,£是未选,如模板图)
$template->setValue(\'check0\', 1? \'R\' : \'£\');//与模板内check0对应,变量命名可更改,与模板一致即可
$template->setValue(\'check1\', 0? \'R\' : \'£\');//与模板内check1对应,变量命名可更改,与模板一致即可

//复制行
$template->cloneRow(\'本行最左边的变量名\', \'要复制的行数\');

//复制行-举例(如模板图)
$user = [[\'no\'=>\'1\', \'name\'=>\'张三\', \'sex\'=>\'男\'], [\'no\'=>\'2\', \'name\'=>\'李四\', \'sex\'=>\'女\']];
$rows = count($user);
$template->cloneRow(\'no\', $rows);//复制行,no是要复制行的最左边变量,$rows代表复制几行,复制后会是no#1,name#1,sex#1;no#2,name#2,sex#2这样的
for ($i = 0; $i < $rows; $i++) {
    $template->setValue(\'no#\' . ($i + 1), $user[$i][\'no\']);
    $template->setValue(\'name#\' . ($i + 1), $user[$i][\'name\']);
    $template->setValue(\'sex#\' . ($i + 1), $user[$i][\'sex\']);
}

//复制块,也可用于是否显示
$template->cloneBlock(\'块标签名\',\'数量\');//模板内为${块标签名}和${/块标签名}和html标签一样,成对出现,内容放中间

//复制块-举例(如模板图)
$show_name=\'显示\';
$template->cloneBlock(\'show\', 2);//复制两个
$template->setValue(\'show_name\', $show_name);//设置值
$template->cloneBlock(\'hide\', 0);//复制0个,代表隐藏,值也不用设了

//插入图片(模板内为${img})
$template->setImageValue(\'img\', [\'path\'=>\'路径\', \'width\'=>500, \'height\'=>500]);

模板图

  

 

结果图

 

三:生成方式导出


$phpWord = new PhpWord();

//设置纸张与边距

$section = $phpWord->addSection(

array(\'paperSize\' => \'A4\', \'marginLeft\' => 1440, \'marginRight\' => 1440, \'marginTop\' => 1800, \'marginBottom\' => 1800, \'orientation\' => \'landscape\')

);

//添加页眉

$header = $section->createHeader();

$table = $header->addTable();

$table->addRow();

$table->addCell(4500)->addText(\'This is the header\');

$table->addCell(4500)->addImage(\'_earth.jpg\',array(\'width\'=>50,\'height\'=>50,\'align\'=>\'right\'));

//添加页脚

$footer = $section->addFooter();

$footer->addPreserveText(\'{PAGE} / {NUMPAGES}\', null, array(\'alignment\' => \'center\'));

 

//添加标题并设置字体字号对齐方式

//<w:br/>:换行;name:字体;bold:加粗;size:字号;alignment:对齐方式;index:缩进

$section->addText(\'This is title<w:br/>subtitle\', [\'name\' => \'宋体\', \'bold\' => true, \'size\' => 16], [\'alignment\' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER], [\'indent\' => 0]);

$section->addTextBreak();

//添加一个普通表格

//基础数据

$data = [

[\'id\' => \'1\', \'name\' => \'张三\', \'age\' => \'20\'],

[\'id\' => \'2\', \'name\' => \'李四\', \'age\' => \'20\'],

[\'id\' => \'3\', \'name\' => \'王五\', \'age\' => \'21\'],

[\'id\' => \'4\', \'name\' => \'赵六\', \'age\' => \'21\'],

];

//添加一个表格

$table = $section->addTable([\'borderSize\' => 6, \'cellMargin\' => 80, \'alignment\' => \'center\']);

//添加一行(addRow执行后才能使用addCell给本行添加列,括号内数字代表高度)

$table->addRow(1100);

//表头添加(数字代表宽度,valign代表对齐方式)

$table->addCell(900, [\'valign\' => \'center\'])->addText(\'序号\', \'default2\', [\'alignment\' => \'center\']);

$table->addCell(2000, [\'valign\' => \'center\'])->addText(\'名称\', \'default2\', [\'alignment\' => \'center\',\'blod\' => true]);

$table->addCell(1500, [\'valign\' => \'center\'])->addText(\'年龄\', \'default2\', [\'alignment\' => \'center\']);

//内容添加

foreach ($data as $k=>$v) {

$table->addRow(1100);

$table->addCell(900, [\'valign\' => \'center\'])->addText($v[\'id\'], \'default\', [\'alignment\' => \'center\']);

$table->addCell(2000, [\'valign\' => \'center\'])->addText($v[\'name\'], \'default\', [\'alignment\' => \'center\']);

$table->addCell(1500, [\'valign\' => \'center\'])->addText($val[\'age\'], \'default\', [\'alignment\' => \'center\']);

}

 

//添加一个带合并单元格的表格

//基础数据

$data = [

[\'id\' => \'1\', \'role\' => \'开发人员\', \'child\' => [[\'name\' => \'张三\', \'age\' => \'20\'], [\'name\' => \'李四\', \'age\' => \'20\']]],

[\'id\' => \'2\', \'role\' => \'测试人员\', \'child\' => [[\'name\' => \'王五\', \'age\' => \'20\'], [\'name\' => \'赵六\', \'age\' => \'20\']]],

];

//添加一个表格
$table = $section->addTable([\'borderSize\' => 6, \'cellMargin\' => 80, \'alignment\' => \'center\']);

//添加一行

$table->addRow(1100);

//表头添加
$table->addCell(900, [\'valign\' => \'center\'])->addText(\'序号\', \'default2\', [\'alignment\' => \'center\']);

$table->addCell(2000, [\'valign\' => \'center\'])->addText(\'角色\', \'default2\', [\'alignment\' => \'center\',\'blod\' => true]);

$table->addCell(2000, [\'valign\' => \'center\'])->addText(\'名称\', \'default2\', [\'alignment\' => \'center\',\'blod\' => true]);

$table->addCell(1500, [\'valign\' => \'center\'])->addText(\'年龄\', \'default2\', [\'alignment\' => \'center\']);

//内容添加

foreach ($data as $key=>$val) {

foreach ($val[\'child\'] as $k=>$v) {

$table->addRow(1100);

if($k == 0){

//本角色的第一行(和后面行区分开,前两列(序号,角色)要合并,所以这里设置一下,把vMerge设置成restart,代表向下合并,遇到vMerge为continue的就合并,直到下一个角色的起始行vMerge为restart停止合并)

$table->addCell(900, [\'vMerge\' => \'restart\', \'valign\' => \'center\'])->addText(htmlspecialchars($val[\'id\']), \'default\', [\'alignment\' => \'center\']);

$table->addCell(2000, [\'vMerge\' => \'restart\', \'valign\' => \'center\'])->addText(htmlspecialchars($val[\'role\']), \'default\', [\'alignment\' => \'center\']);

}else{

//本角色的2+行(和第一行合并,vMerge设置为continue,不用添加文本,因为第一行已经设置值了

$table->addCell(900, [\'vMerge\' => \'continue\', \'valign\' => \'center\']);

$table->addCell(2000, [\'vMerge\' => \'continue\', \'valign\' => \'center\']);

}

//不需要合并的列,不用区分是第几行,直接写入就行

$table->addCell(2000, [\'valign\' => \'center\'])->addText(htmlspecialchars($v[\'name\']), \'default\', [\'alignment\' => \'center\']);

$table->addCell(1500, [\'valign\' => \'center\'])->addText(htmlspecialchars($v[\'age\']), \'default\', [\'alignment\' => \'center\']);

}

}

$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, \'Word2007\');


$file = date(\'Ymd\') . \'.docx\';

$encoded_filename = urlencode($file);

header("Content-Description: File Transfer");

header(\'Content-Disposition: attachment; filename="\' . $file . \'"\');

$objWriter->save(\'php://output\');