最近,因为公司在某些水平上要生成 word 文档. 在网上于是就找了 PHPOffice 团队出品的 PHPword. 说实话,在用的过程中很不错. 然而有一些非凡的属性就不反对. 例如, 容许在西文单词中换行这个属性就没有. 上面就记录一下我整个的过程.
源码
咱们通过源代码查看, 在最终生成 word 的时候, 是应用的 writer 类的 save 办法. 如下
use PhpOffice\PhpWord\IOFactory;
use PhpOffice\PhpWord\PhpWord;
// 开始解决 word.
$word = new PhpWord();
$writer = IOFactory::createWriter($word, 'Word2007');
$full_path = \Yii::$app->getRuntimePath() . DIRECTORY_SEPARATOR . '域名.docx';
$writer->save($full_path);
咱们找到 writer 类的 save 办法.
// vendor/phpoffice/phpword/src/PhpWord/Writer/Word2007.php
// 137 行左右
foreach ($this->parts as $partName => $fileName) {if ($fileName != '') {
// 这段话用了 zip 的形式.
$zip->addFromString($fileName, $this->getWriterPart($partName)->write());
}
}
在 137 行左右应用了 addFromString 办法. 这个是用 zip 扩大来进行生成的.zip 扩大是用来创立压缩文件 . 难道 word 是一个 zip 文件? so 那咱们来试试. 将导出的文件改成.zip 为后缀的压缩文件. 如下
不难发现. 咱们胜利了. 在 zip 外面咱们果决看到了一堆 xml. 通过查找. 在 zip 文件中 word/document.xml 这个外面会含有咱们的文字信息. 和一些排版款式. 剩下的咱们就须要做比照了. 将一个有西文单词换行的和一个没有西文单词换行的来进行比照. 如下图所示. 仅仅是多了这几列.
左侧是勾选了容许在西文单词中换行这个属性, 右侧则是没有. 剩下就是依据这个规定生成就能够了.
批改源码
通过浏览网址, 发现咱们只须要实现 wordwrap 就能够了. 开干. 咱们先看看其余属性的实现. 例如 keepNext. 他的调用形式如下
$word = new PhpWord();
$section = $word->addSection();
$element = $section->addText('There are moments in life when you miss someone so much that you just want to pick them supercalifragilisticexpiadocious your dreams and hug them for real! Dream what you want to dream;go where you want to go;be what you want to be,because you have only one life and one chance to do all the things you want to do.');
$paragraph = new Paragraph();
// 减少段落标识.
$paragraph->setKeepNext(true);
$element->setParagraphStyle($paragraph);
$writer = IOFactory::createWriter($word, 'Word2007');
$writer->save(\Yii::$app->getRuntimePath() . '/1.docx');
那咱们就在 Paragraph 中减少 setWordWrap 办法. 同时咱们还发现他有 hasKeepNext. 也是须要咱们减少的.
// 默认是不容许的
private $wordWrap = true;
// 是由含有容许在西文单词中换行属性
public function hasWordWrap()
{return $this->wordWrap;}
// 设置容许在西文单词中换行
public function setWordWrap($value = true)
{$this->wordWrap = $this->setBoolVal($value, $this->wordWrap);
return $this;
}
public function getStyleValues()
{
$styles = array('name' => $this->getStyleName(),
'basedOn' => $this->getBasedOn(),
'next' => $this->getNext(),
'alignment' => $this->getAlignment(),
'indentation' => $this->getIndentation(),
'spacing' => $this->getSpace(),
'pagination' => array('widowControl' => $this->hasWidowControl(),
'keepNext' => $this->isKeepNext(),
'keepLines' => $this->isKeepLines(),
'pageBreak' => $this->hasPageBreakBefore(),
// 新增.
'wordWrap' => $this->hasWordWrap(),),
'numbering' => array('style' => $this->getNumStyle(),
'level' => $this->getNumLevel(),),
'tabs' => $this->getTabs(),
'shading' => $this->getShading(),
'contextualSpacing' => $this->hasContextualSpacing(),
'bidi' => $this->isBidi(),
'textAlignment' => $this->getTextAlignment(),
'suppressAutoHyphens' => $this->hasSuppressAutoHyphens(),);
return $styles;
}
同时. 在输入的时候 咱们须要减少这个 element. 所以咱们在 phpoffice/phpword/src/PhpWord/Writer/Word2007/Style/Paragraph.php, 96 行减少如下代码
$xmlWriter->writeElementIf($styles['pagination']['wordWrap'] !== true, 'w:wordWrap', 'w:val', '0');
最初
批改测试代码
$word = new PhpWord();
$section = $word->addSection();
$element = $section->addText('There are moments in life when you miss someone so much that you just want to pick them supercalifragilisticexpiadocious your dreams and hug them for real! Dream what you want to dream;go where you want to go;be what you want to be,because you have only one life and one chance to do all the things you want to do.');
$paragraph = new Paragraph();
// 减少段落标识.
$paragraph->setWordWrap(false);
$element->setParagraphStyle($paragraph);
$writer = IOFactory::createWriter($word, 'Word2007');
$writer->save(\Yii::$app->getRuntimePath() . '/1.docx');
测试一下, 完满解决. 上面是我的一些参考文档
http://officeopenxml.com/WPparagraphProperties.php
https://docs.microsoft.com/zh-cn/office/vba/api/word.paragraph