如何解决PhpWord 输出在 LibreOffice 中不起作用,但在 MS Word 中工作正常
这与 GitHub 页面 [link] 上列出的一个半已知问题有关,其中 PhpWord 生成表格的方式导致它将单元格宽度设置为“”,这在 LibreOffice 中无效,但是在 Word 中没问题。
GitHub 上的问题专门列出了 html-to-word 转换,但我在使用常规的面向对象界面时也遇到了这个问题。
我尝试手动设置单元格宽度,但似乎没有任何作用。
我在这里询问是否有人对此问题有任何解决方法,因为它几乎不可能在不访问 MS Word 的情况下在 Linux 机器上调试我的输出。我需要为客户导出 .docx。
为什么不直接导出到 .odt 来测试呢?如果我这样做,它也不会呈现我在页面上的列表......
这是我正在处理的文档的粗略大纲(由于保密协议,我不能随意分享确切的代码):
$document = new PhpWord\PhpWord();
$section = $document->addSection();
// This list doesn't get rendered in the ODT file
$section->addListItem('Employee ID: 98765');
$section->addListItem('First Name: John');
$section->addListItem('Last Name: Doe');
$section->addListItem('SSN: 12345');
// This table has errors in LibreOffice when exported to .docx
if ($show_adv_details) {
$table = $section->addTable();
$table->addRow();
$table->addCell()->addText('SSN');
$table->addCell()->addText('Email');
$table->addCell()->addText('Phone No');
$table->addRow();
$table->addCell()->addText('12345');
$table->addCell()->addText('jd@example.com');
$table->addCell()->addText('999 1234');
// repeat ad nauseam
}
$section->addTitle('Comment');
$section->addTitle('Lorem ipsum dolor sit amet,consectetur adipiscing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.');
我在 Ubuntu 上使用 PHP 7.0(古老的遗留系统,对此无能为力)。
所以在最后重申一下这个问题:
我可以做些什么来使该文档在所有不同的输出上正确呈现?文档似乎没有多大帮助。
解决方法
好吧,我不是 PHPOffice 包的维护者,但这里有一个解决方法,我挖掘了包代码并解决了您的两个问题:
- ODT 列表不起作用;
- 使用 LibreOffice 打开 Word2007 Writer 上的表格不起作用。
我意识到 ODText 编写器上不存在 ListItem.php 类,我想这是因为您无法将列表添加到 .odt 文件中。
您需要手动为列添加宽度以使其在 LibreOffice 上工作(如 Nigel 所说,您可以通过每个 addCell()
调用并添加一些数字,甚至“1”也可以)。
如何解决这两个问题
我们将“覆盖”原始文件,并提供一些解决问题的更新。 为了使其工作,您应该使用 Composer 安装 PHPWord。 (这是安装指南中唯一可用的选项,但还有其他方法可以做到这一点)。
如果没有 Composer,PHPWord require 之后需要自定义文件(我认为它有效)。或者直接更改其位置上的文件(一个坏主意)。
文件
创建一个这样的结构:
Custom
├── Element
│ └── Table.php
└── Writer
└── ODText
└── Element
└── ListItem.php
当然,您可以使用任何其他文件,但我们将“覆盖”包的原始文件,因此我保留了其结构。
我们将使用 Autoload Files 来获取这些文件:
composer.json:
...
"autoload": {
"files": [
"Custom/Element/Table.php","Custom/Writer/ODText/Element/ListItem.php"
]
},...
如果您的 composer.json 上没有“自动加载”键,您必须添加它,“文件”键也是如此。
运行 composer dump-autoload
以更新更改。
自定义类
现在,我们必须将代码添加到我们的自定义文件中。
Custom/Writer/ODText/Element/ListItem.php:
<?php
namespace PhpOffice\PhpWord\Writer\ODText\Element;
/**
* ListItem element writer
*/
class ListItem extends AbstractElement
{
/**
* Write list item element.
*/
public function write()
{
$xmlWriter = $this->getXmlWriter();
$element = $this->getElement();
if (!$element instanceof \PhpOffice\PhpWord\Element\ListItem) {
return;
}
$textObject = $element->getTextObject();
$xmlWriter->startElement('text:list');
$xmlWriter->writeAttribute('text:style-name','L1');
$xmlWriter->startElement('text:list-item');
$xmlWriter->startElement('text:p');
$xmlWriter->writeAttribute('text:style-name','P1');
$elementWriter = new Text($xmlWriter,$textObject,true);
$elementWriter->write();
$xmlWriter->endElement(); // text:list
$xmlWriter->endElement(); // text:p
$xmlWriter->endElement(); // text:list-item
}
}
该文件已改编自 Word2007 版本并修复了您的第一个问题。现在列表将适用于 ODText。
自定义/元素/Table.php:
<?php
namespace PhpOffice\PhpWord\Element;
use PhpOffice\PhpWord\Style\Table as TableStyle;
/**
* Table element writer
*/
class Table extends AbstractElement
{
/**
* Table style
*
* @var \PhpOffice\PhpWord\Style\Table
*/
private $style;
/**
* Table rows
*
* @var \PhpOffice\PhpWord\Element\Row[]
*/
private $rows = array();
/**
* Table width
*
* @var int
*/
private $width = null;
/**
* Create a new table
*
* @param mixed $style
*/
public function __construct($style = null)
{
$this->style = $this->setNewStyle(new TableStyle(),$style);
}
/**
* Add a row
*
* @param int $height
* @param mixed $style
* @return \PhpOffice\PhpWord\Element\Row
*/
public function addRow($height = null,$style = null)
{
$row = new Row($height,$style);
$row->setParentContainer($this);
$this->rows[] = $row;
return $row;
}
/**
* Add a cell
*
* @param int $width
* @param mixed $style
* @return \PhpOffice\PhpWord\Element\Cell
*/
public function addCell($width = 1,$style = null)
{
$index = count($this->rows) - 1;
$row = $this->rows[$index];
$cell = $row->addCell($width,$style);
return $cell;
}
/**
* Get all rows
*
* @return \PhpOffice\PhpWord\Element\Row[]
*/
public function getRows()
{
return $this->rows;
}
/**
* Get table style
*
* @return \PhpOffice\PhpWord\Style\Table
*/
public function getStyle()
{
return $this->style;
}
/**
* Get table width
*
* @return int
*/
public function getWidth()
{
return $this->width;
}
/**
* Set table width.
*
* @param int $width
*/
public function setWidth($width)
{
$this->width = $width;
}
/**
* Get column count
*
* @return int
*/
public function countColumns()
{
$columnCount = 0;
$rowCount = count($this->rows);
for ($i = 0; $i < $rowCount; $i++) {
/** @var \PhpOffice\PhpWord\Element\Row $row Type hint */
$row = $this->rows[$i];
$cellCount = count($row->getCells());
if ($columnCount < $cellCount) {
$columnCount = $cellCount;
}
}
return $columnCount;
}
/**
* The first declared cell width for each column
*
* @return int[]
*/
public function findFirstDefinedCellWidths()
{
$cellWidths = array();
foreach ($this->rows as $row) {
$cells = $row->getCells();
if (count($cells) <= count($cellWidths)) {
continue;
}
$cellWidths = array();
foreach ($cells as $cell) {
$cellWidths[] = $cell->getWidth();
}
}
return $cellWidths;
}
}
当我们“覆盖”文件时,我们不能重用扩展它的原始文件(至少我不知道如何)。此处唯一的更改是 public function addCell($width = 1,$style = null)
始终将“1”作为函数的默认值。这解决了您的第二个问题,现在您可以在没有值的情况下调用 $table->addCell()
。
演示
require __DIR__ . '/vendor/autoload.php';
$document = new \PhpOffice\PhpWord\PhpWord();
$section = $document->addSection();
// This list **does** get rendered in the ODT file
$section->addListItem('Employee ID: 98765');
$section->addListItem('First Name: John');
$section->addListItem('Last Name: Doe');
$section->addListItem('SSN: 12345');
$table = $section->addTable();
$table->addRow();
$table->addCell()->addText('SSN');
$table->addCell()->addText('Email');
$table->addCell()->addText('Phone No');
$table->addRow();
$table->addCell()->addText('12345');
$table->addCell()->addText('jd@example.com');
$table->addCell()->addText('999 1234');
// Save the document as DOCX
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($document,'Word2007');
$objWriter->save('document.docx');
// Save the document as ODT
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($document,'ODText');
$objWriter->save('document.odt');
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。