PhpWord输出在LibreOffice中不起作用,但在MSWord中工作正常

这与 GitHub 页面 [链接]上列出的一个半已知问题有关,其中 PhpWord 生成表格的方式导致它将单元格宽度设置为“”,这在 LibreOffice 中无效,但在 Word 中很好。

GitHub 上的问题专门列出了 html-to-word 转换,但我在使用常规的面向对象界面时也遇到了这个问题。

我试过手动设置单元格宽度,但它似乎没有做任何事情。

我在这里询问是否有人对此问题有任何解决方法,因为它几乎不可能在不访问 MS Word 的情况下在 Linux 机器上调试我的输出。我需要为客户导出 .docx。

为什么不直接导出到 .odt 来测试它呢?如果我这样做,它也不会呈现我在页面上的列表......

这是我正在处理的文档的粗略概述(由于保密协议,我不能随意分享确切的代码):

$document = new PhpWordPhpWord();
$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 包的维护者,但这里有一个解决方法,我在包代码中挖掘并解决了您的两个问题:

  1. ODT 列表不起作用;
  2. Word2007 Writer 上的表格在使用 LibreOffice 打开时不起作用。

我意识到ODText 编写器上不存在ListItem.php类,我想这是因为您无法将列表添加到 .odt 文件中。

您需要手动为列添加宽度以使其在 LibreOffice 上工作(正如Nigel所说,您可以通过每次addCell()调用并添加一些数字,甚至“1”也可以)。

如何解决这两个问题

我们将“覆盖”原始文件,并提供一些解决问题的更新。为了使其工作,您应该使用 Composer安装PHPWord。
(这是安装指南中唯一可用的选项,但还有其他方法可以做到这一点)。

如果没有 Composer,在 PHPWord require 之后需要自定义文件(我认为它有效)。或者直接更改其位置上的文件(一个坏主意)。

文件

创建一个这样的结构:

Custom
??? Element
?   ??? Table.php
??? Writer
    ??? ODText
        ??? Element
            ??? ListItem.php
Custom
??? Element
?   ??? Table.php
??? Writer
    ??? ODText
        ??? Element
            ??? ListItem.php

当然,你可以使用任何其他的,但我们将“覆盖”包的原始文件,所以我保留了它的结构。

我们将使用自动加载文件来获取这些文件:

作曲家.json

如果您的composer.json上没有“自动加载”键,您必须添加它,“文件”键也是如此。

运行composer dump-autoload以更新更改。

自定义类

现在,我们必须将代码添加到我们的自定义文件中。

自定义/Writer/ODText/Element/ ListItem.php :

...
"autoload": {
    "files": [
        "Custom/Element/Table.php",
        "Custom/Writer/ODText/Element/ListItem.php"
    ]
},
...

该文件已改编自 Word2007 版本并修复了您的第一个问题。现在列表将适用于 ODText。

自定义/元素/ Table.php :

<?php
namespace PhpOfficePhpWordWriterODTextElement;

/**
 * ListItem element writer
 */
class ListItem extends AbstractElement
{
    /**
     * Write list item element.
     */
    public function write()
    {
        $xmlWriter = $this->getXmlWriter();
        $element = $this->getElement();
        if (!$element instanceof PhpOfficePhpWordElementListItem) {
            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
    }
}

当我们“覆盖”文件时,我们不能重用扩展它的原始文件(至少我不知道如何)。这里唯一的变化是public function addCell($width = 1, $style = null)始终将“1”作为函数的默认值。这解决了您的第二个问题,现在您可以在$table->addCell()没有值的情况下调用。

演示

<?php
namespace PhpOfficePhpWordElement;

use PhpOfficePhpWordStyleTable as TableStyle;

/**
 * Table element writer
 */
class Table extends AbstractElement
{
    /**
     * Table style
     *
     * @var PhpOfficePhpWordStyleTable
     */
    private $style;

    /**
     * Table rows
     *
     * @var PhpOfficePhpWordElementRow[]
     */
    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 PhpOfficePhpWordElementRow
     */
    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 PhpOfficePhpWordElementCell
     */
    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 PhpOfficePhpWordElementRow[]
     */
    public function getRows()
    {
        return $this->rows;
    }

    /**
     * Get table style
     *
     * @return PhpOfficePhpWordStyleTable
     */
    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 PhpOfficePhpWordElementRow $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;
    }
}


以上是PhpWord输出在LibreOffice中不起作用,但在MSWord中工作正常的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>