推薦使用模板方式,使用方便,樣式也好調一些,大部分要求也都可以實現;生成方式目前我是在做表格單元格合並的時候用到過,下面會介紹使用方式(模板方式在單元格中插入一個小表格,然后用cloneRow復制小表格也可以實現,但是這樣比較別扭,不完美)
一:引入
tp5.0,tp5.1:
1:composer方式(推薦)
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');
