PHPWord的應用
發表於 : 2024-12-30, 22:58
1. 安裝 composer (前提 PHP需安裝有 SSL和 mbstring的extension功能)
2. 安裝 PHPWord (依PHP版本不同,會有版本上限)(PHP 5.6 只能用到 0.17.0)
3. 簡易入手文件,可參考 https://gist.github.com/thomasjao/316fb835dd1e3a3333aa
4. 好好利用 ChatGPT, 時代不同了. 雖然ChatGPT未必能給出 100% 正確的回答.
可在 c:\composer 目錄下建立 PHPWord子目錄, 然後開啟 command 模式, cd C:\composer\PHPWord, 再下達 composer 指令:
最新版則為
3. 輸出Word的重點
5. 產生的WORD檔無法開啟時,可以將下載的WORD檔重新命名為 .zip, 將其解壓縮後檢查 word/document.xml 的格式是否有錯?
https://www.runoob.com/xml/xml-validator.html
大都會產生的錯誤原因為資料裡有 < >; 或者資料裡含 html tags, 此時若丟給 addText()會產生錯誤(0.17.0版會有錯誤).
因為轉成 Word檔時,時常要處理的是表格和圖檔,故確認有圖或表格時,調用特化的函式.
否則就用一般的方式處理.
2. 安裝 PHPWord (依PHP版本不同,會有版本上限)(PHP 5.6 只能用到 0.17.0)
3. 簡易入手文件,可參考 https://gist.github.com/thomasjao/316fb835dd1e3a3333aa
4. 好好利用 ChatGPT, 時代不同了. 雖然ChatGPT未必能給出 100% 正確的回答.
可在 c:\composer 目錄下建立 PHPWord子目錄, 然後開啟 command 模式, cd C:\composer\PHPWord, 再下達 composer 指令:
代碼: 選擇全部
composer require phpoffice/phpword:^0.17.0
代碼: 選擇全部
composer require phpoffice/phpword
代碼: 選擇全部
require_once 'vendor/autoload.php';
header: header('Content-Type: text/html; charset=utf-8');
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\IOFactory;
PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true); //可避免輸出 <= 這類的問題
// 初始化 PHPWord
$phpWord = new PhpWord();
...
// 儲存 Word 文件
$fileName = 'output.docx';
$writer = IOFactory::createWriter($phpWord, 'Word2007');
ob_clean(); //重要,否則可能會產生: This file is corrupt and cannot be opened. 的開檔警告訊息
$writer->save($fileName);
// 提供下載
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=" . basename($fileName));
header("Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document");
header("Content-Transfer-Encoding: binary");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Pragma: public");
header("Content-Length: " . filesize($fileName));
readfile($fileName);
// 刪除文件
unlink($fileName);
exit;
https://www.runoob.com/xml/xml-validator.html
大都會產生的錯誤原因為資料裡有 < >; 或者資料裡含 html tags, 此時若丟給 addText()會產生錯誤(0.17.0版會有錯誤).
代碼: 選擇全部
// 匹配完整的 <table> 和 <img> 標籤
$patternTable = '/<\s*table\b[^>]*>/i';
$patternImg = '/<\s*img\b[^>]*>/i';
$search = array('<br/>','<br />', ' ','<p>','<p/>','</p>',
'<h1>','</h1>','<h2>','</h2>','<h3>','</h3>');
$replace= array("\n","\n",' ',"","\n","\n","[","]","[","]","[","]");
...
if (preg_match($patternTable, $htmlContent) ||
preg_match($patternImg, $htmlContent)) {
processHtmlContent($section, $htmlContent);
}
else {
$htmlContent = str_ireplace($search, $replace, $htmlContent); //替換
$section->addText($htmlContent, array('name' => 'Arial', 'size' => 12));
}
否則就用一般的方式處理.
代碼: 選擇全部
// 定義處理圖片的函式
function processImage($sectionOrTextRun, $imgNode, $isTextRun = false) {
$imgSrc = $_SESSION["PICT_ROOT"].$imgNode->getAttribute('src');
// 獲取圖片原始大小
list($originalWidth, $originalHeight) = getimagesize($imgSrc);
// 縮小圖片為原始大小的 1/2
$scaledWidth = intval($originalWidth / 2);
$scaledHeight = intval($originalHeight / 2);
if (file_exists($imgSrc)) {
$options = array(
'width' => $scaledWidth,
'height' => $scaledHeight,
);
if ($isTextRun) {
$sectionOrTextRun->addImage($imgSrc, $options);
} else {
$sectionOrTextRun->addImage($imgSrc, array_merge($options, array('alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER)));
}
} else {
$sectionOrTextRun->addText("圖片未找到: $imgSrc", array('color' => 'FF0000', 'name' => 'Arial', 'size' => 12));
}
}
// 定義處理表格的函式
function processTable($section, $tableNode) {
$wordTable = $section->addTable(array(
'borderSize' => 6,
'borderColor' => '000000',
'alignment' => 'center'
));
$rows = $tableNode->getElementsByTagName('tr');
foreach ($rows as $row) {
$wordRow = $wordTable->addRow();
$cells = $row->getElementsByTagName('td');
foreach ($cells as $cell) {
$wordRow->addCell(2000)->addText(trim($cell->textContent), array('name' => 'Arial', 'size' => 12));
}
}
}
// 定義處理 HTML 的函式
function processHtmlContent($section, $htmlContent) {
libxml_use_internal_errors(true);
$dom = new DOMDocument('1.0', 'utf-8');
@$dom->loadHTML('<?xml encoding="UTF-8">' . $htmlContent);
libxml_clear_errors();
$body = $dom->getElementsByTagName('body')->item(0);
foreach ($body->childNodes as $node) {
if ($node->nodeName === 'p') {
$textRun = $section->addTextRun();
foreach ($node->childNodes as $childNode) {
if ($childNode->nodeName === '#text') {
$textRun->addText(trim($childNode->textContent), array('name' => 'Arial', 'size' => 12));
} elseif ($childNode->nodeName === 'img') {
processImage($textRun, $childNode, true);
}
}
} elseif ($node->nodeName === 'table') {
processTable($section, $node);
} elseif ($node->nodeName === 'img') {
processImage($section, $node);
}
}
}