Forum


Replies: 3   Views: 46
Libreoffice conversion - table columns width

Posted by magira  · 10-07-2019 - 14:03

Hello,

I have a probleme when i convert my document using PHPDocx8 with LibreOffice.


$docx = new CreateDocx();

$docx->enableCompatibilityMode();
$html = '<h1 style="color: #b70000">An embedHTML() example</h1>';
$html .= '<p>We draw a table with border and rawspans and colspans:</p>';
$html .= '<table border="1" style="border-collapse: collapse" width="600px">
            <tbody>
                <tr width="600px">
                    <td width="100px">3_2</td>
                    <td width="50px">3_3</td>
                    <td width="450px">3_3</td>
                </tr>
            </tbody>
        </table>';

$docx->embedHTML($html);

$docx->createDocx('example_text');

$docx->transformDocument('example_text.docx', 'example_text.pdf');

I just create an exemple code.

The result in MSWord is allrigth but the converted PDF don't use width attribut.

See result here :https://ibb.co/V21rnMb

What i'm doing wrong ?

Thanks.

Posted by admin  · 10-07-2019 - 14:47

Hello,

You are not doing anything wrong. The issue is that phpdocx 8.0 needs as many (or more) rows as columns when setting widths to get a proper output with LibreOffice; for example:

$html .= '<table border="1" style="border-collapse: collapse" width="600px">
            <tbody>
                <tr width="600px">
                    <td width="100px">3_2</td>
                    <td width="50px">3_3</td>
                    <td width="450px">3_3</td>
                </tr>
                <tr width="600px">
                    <td width="100px">3_2</td>
                    <td width="50px">3_3</td>
                    <td width="450px">3_3</td>
                </tr>
                <tr width="600px">
                    <td width="100px">3_2</td>
                    <td width="50px">3_3</td>
                    <td width="450px">3_3</td>
                </tr>
            </tbody>
        </table>';

phpdocx 8.5 added some improvements to get a proper output using all DOCX viewers with any number of rows and columns.

If you want to update your file, please edit HTML2WordML.php and in the closePreviousTags method, you need to replace two case lines ('table' and 'tr') with these lines:

case 'table':
    if (self::$openPs) {
        if (self::$openLinks) {
            $sRet.= '</w:hyperlink>';
            self::$openLinks = false;
        }
        if (self::$openBookmark > 0) {
            $sRet.= '<w:bookmarkEnd w:id="' . self::$openBookmark . '" />';
            self::$openBookmark = 0;
        }
        $sRet .= '</w:p></w:tbl>';
        self::$openPs = false;
    } else {
        if (self::$openTable > 1) {
            //This is to fix a Word bug that does not allow to close a table and write just after a </w:tc>
            $sRet .= '</w:tbl><w:p />';
        } else {
            $sRet .= '</w:tbl>';
        }
    }

    // clean previous gridCol placeholder to prevent adding extra tags when adding more than one table
    if (count($this->gridColValues) > 0) {
        foreach ($this->gridColValues as $gridColValue) {
            self::$WordML = str_replace('#<w:gridCol/>#', '<w:gridCol w:w="'.$gridColValue.'"/>#<w:gridCol/>#', self::$WordML);
        }
    } else {
        self::$WordML = str_replace('#<w:gridCol/>#', str_repeat('<w:gridCol w:w="1"/>', $column), self::$WordML);
    }
    self::$WordML = str_replace('#<w:gridCol/>#', '', self::$WordML);
    $this->gridColValues = array();
    
    self::$openTable--;
    break;
case 'tr':
    //Before closing a row we should make sure that there are no lacking cells due to a previous rowspan
    $row = count(self::$tableGrid[self::$openTable]) - 1;
    $column = count(self::$tableGrid[self::$openTable][$row]);
    $sRet .= $this->closeTr($row, $column);
    if (strpos(self::$WordML, '#<w:gridCol/>#') !== false) {
        // get the cell width
        if (self::$tableGrid[self::$openTable][$row][$row][2]['width'] !== null) {
            list($cellWidth, $cellWidthType) = $this->_wordMLUnits(self::$tableGrid[self::$openTable][$row][$row][2]['width']);
        }

        if ($cellWidth) {
            $i = 0;
            foreach (self::$tableGrid[self::$openTable][$row] as $rowProperties) {
                list($cellWidth, $cellWidthType) = $this->_wordMLUnits($rowProperties[2]['width']);
                if (!isset($this->gridColValues[$i]) || $this->gridColValues[$i] > $cellWidth) {
                    $this->gridColValues[$i] = $cellWidth;
                }
                $i++;
            }
        }
    }
    //We now may close the tr tag
    $sRet .= '</w:tr>';
    break;

After applying this change your HTML will work perfectly with LibreOffice.

We have sent the full class with these same changes to your e-mail.

Regards.

Posted by magira  · 10-07-2019 - 15:46

Hello,

Oh, yes thanks you!  it's solved my problem.

But, just one case : if i have a colspan at first line on my table, it's doesn't work.

<table width="600">
<tr>
<td coldspan="2" width="100"></td> <!-- or width="600" is equal...-->
</tr>
<tr>
<td width="100"></td>
<td width="500"></td>
</tr>
</table>

Have you a fix for it ?

Posted by admin  · 10-07-2019 - 16:12

Hello,

We have tested your HTML with the colspan value using the previous changes and it works correctly as well with MS Word and LibreOffice.

Please note that the code you have posted:

<table width="600">
<tr>
<td coldspan="2" width="100"></td> <!-- or width="600" is equal...-->
</tr>
<tr>
<td width="100"></td>
<td width="500"></td>
</tr>
</table>

isn't correct. It should be:

<table width="600">
<tr>
<td colspan="2" width="100"></td> <!-- or width="600" is equal...-->
</tr>
<tr>
<td width="100"></td>
<td width="500"></td>
</tr>
</table>

This is using colspan (not coldspan). You can use an auto value, or 100 or 600 as width in the td.

We have tested it using the following code:

$html = '
<table border="1" width="600">
<tr>
<td colspan="2" width="100">A</td>
</tr>
<tr>
<td width="100">B</td>
<td width="500">C</td>
</tr>
</table>';

$docx->embedHTML($html);

Regards.