FIXED: Table Height Problems

Apr 19, 2013 at 4:00 PM
Hi all! I have modified a couple files to fully handle the configuration of tables and their row heights. All I added to the addRow() function was an additional parameter that indicated the hRule to be used in the document.xml file of the Word docx. Here is a before and after of the PHP usage.
Before:
$table->addRow(100);
After:
$table->addRow(100,"exact");
$table->addRow(100,null);
Using "exact" makes the row height adhere to the value. Using a null value will provide the current default behavior of giving you the "At least" property in Word. To glue all of this together, I modified the Table.php and Base.php scripts. This was added to the top of Table.php just behind the $_rowHeights = array(); statement:
    /**
     * Row height rule
     *
     * @var array
     */
    private $_rowHeightRules = array();
The addRow function was updated to be this:
    /**
    * Add a row
    *
    * @param int $height
    * @param string $hRule
    */
    public function addRow($height = null,$hRule) {
        $this->_rows[] = array();
        $this->_rowHeights[] = $height;
        $this->_rowHeightRules[] = $hRule;
    }
This was added near the bottom of Table.php just behind the getRowHeights() function:
    /**
     * Get all row height rules
     *
     * @return array
     */
    public function getRowHeightRules() {
            return $this->_rowHeightRules;
    }
And I modified the function in Base.php to handle the additional instructions:
protected function _writeTable(PHPWord_Shared_XMLWriter $objWriter = null, PHPWord_Section_Table $table) {
        $_rows = $table->getRows();
        $_cRows = count($_rows);
        
        if($_cRows > 0) {
            $objWriter->startElement('w:tbl');
                $tblStyle = $table->getStyle();
                if($tblStyle instanceof PHPWord_Style_Table) {
                    $this->_writeTableStyle($objWriter, $tblStyle);
                } else {
                    if(!empty($tblStyle)) {
                        $objWriter->startElement('w:tblPr');
                            $objWriter->startElement('w:tblStyle');
                                $objWriter->writeAttribute('w:val', $tblStyle);
                            $objWriter->endElement();
                        $objWriter->endElement();
                    }
                }

                $_heights = $table->getRowHeights();
                $_height_rule = $table->getRowHeightRules();
                for($i=0; $i<$_cRows; $i++) {
                    $row = $_rows[$i];
                    $height = $_heights[$i];
                    $rule = $_height_rule[$i];
                    
                    $objWriter->startElement('w:tr');
                    
                        if(!is_null($height)) {
                            $objWriter->startElement('w:trPr');
                                $objWriter->startElement('w:trHeight');
                                    if(!is_null($rule)) {
                                        $objWriter->startAttribute('w:hRule');
                                            $objWriter->text($rule);
                                        $objWriter->endAttribute();
                                    }
                                    $objWriter->startAttribute('w:val');
                                        $objWriter->text($height);
                                    $objWriter->endAttribute();
                                $objWriter->endElement();
                            $objWriter->endElement();
                        }
                        
                        foreach($row as $cell) {
                            $objWriter->startElement('w:tc');
                                
                                $cellStyle = $cell->getStyle();
                                $width = $cell->getWidth();
                                
                                $objWriter->startElement('w:tcPr');
                                    $objWriter->startElement('w:tcW');
                                        $objWriter->writeAttribute('w:w', $width);
                                        $objWriter->writeAttribute('w:type', 'dxa');
                                    $objWriter->endElement();
                                    
                                    if($cellStyle instanceof PHPWord_Style_Cell) {
                                        $this->_writeCellStyle($objWriter, $cellStyle);
                                    }
                                    
                                $objWriter->endElement();
                                
                                $_elements = $cell->getElements();
                                if(count($_elements) > 0) {
                                    foreach($_elements as $element) {
                                        if($element instanceof PHPWord_Section_Text) {
                                            $this->_writeText($objWriter, $element);
                                        } elseif($element instanceof PHPWord_Section_TextRun) {
                                            $this->_writeTextRun($objWriter, $element);
                                        } elseif($element instanceof PHPWord_Section_Link) {
                                            $this->_writeLink($objWriter, $element);
                                        } elseif($element instanceof PHPWord_Section_TextBreak) {
                                            $this->_writeTextBreak($objWriter);
                                        } elseif($element instanceof PHPWord_Section_ListItem) {
                                            $this->_writeListItem($objWriter, $element);
                                        } elseif($element instanceof PHPWord_Section_Image ||
                                                 $element instanceof PHPWord_Section_MemoryImage) {
                                            $this->_writeImage($objWriter, $element);
                                        } elseif($element instanceof PHPWord_Section_Object) {
                                            $this->_writeObject($objWriter, $element);
                                        } elseif($element instanceof PHPWord_Section_Footer_PreserveText) {
                                            $this->_writePreserveText($objWriter, $element);
                                        }
                                    }
                                } else {
                                    $this->_writeTextBreak($objWriter);
                                }
                                
                            $objWriter->endElement();
                        }
                    $objWriter->endElement();
                }
            $objWriter->endElement();
        }
    }
This all works well in my own usage and testing. Anyone needing a diff/patch/script should reply. Thanks!

Adam
Apr 22, 2013 at 6:35 AM
Edited Apr 22, 2013 at 7:44 AM
Thanks a lot it will be usefull for my project ;)!

EDIT: It's corrupting my reports... :(
Apr 22, 2013 at 7:50 PM
I'm happy to troubleshoot if you can give examples. Ideally, you'd be able to pass along a ZIP of your library, a dataset, and your script.
Apr 22, 2013 at 10:55 PM
Hi Aburgett, would you be able to attach - or paste - a patch file for the changes?
Apr 22, 2013 at 11:09 PM
Sure thing, as soon as I return to the office tomorrow (EST). I have also updated the code base to allow column spanning in tables in Word, but that will be a new thread.
Apr 23, 2013 at 6:01 AM
Brilliant. By the way, if you want to add the patch as an attachment this can be done by creating a new issue (you can't add attachments to discussion threads).
Developer
Apr 23, 2013 at 6:44 AM
On 23/04/2013 07:01, neilt17 wrote:

From: neilt17

Brilliant. By the way, if you want to add the patch as an attachment this can be done by creating a new issue (you can't add attachments to discussion threads).
If you want to add a pull request, it can be done via https://github.com/PHPOffice/PHPWord
Apr 23, 2013 at 12:55 PM
I'm not familiar enough with Git yet to be confident in a pull request. Please see:

https://phpword.codeplex.com/workitem/48

for the attached diff that includes BOTH updates.
Feb 20, 2014 at 1:38 PM
Edited Feb 20, 2014 at 2:28 PM
I have also updated the code base to allow column spanning in tables in Word, but that will be a new thread.
I don't see anything in the documentation or examples of column spanning. Please advise.
Feb 20, 2014 at 9:13 PM
I don't believe it's made it into the code or documentation yet as there hasn't been a recent release. The code I wrote is in production with me however. Please review this:

https://phpword.codeplex.com/workitem/48

Adam
Feb 21, 2014 at 1:24 AM
Adam, since the last release was almost 3 years ago, any ETA on another release? This tool is really an awesome thing. I found PHPExcel a couple weeks ago and am now able to create some really nice and complicated spreadsheets. This PHPWord tool is shaping up to being something really great.

Did I read your other comment right about you all working on a PHP to PDF tool?
Feb 21, 2014 at 1:20 PM
Bill,

I don't know when the next release may be. I'm pretty comfortable with the product as is, so I'm not anxious for anything different. Do you a copy of my production version to solve your table problem, or do you have it working. Yes, I agree, these are great tools.

As far as the PHP to PDF tool, the answer is "sort of". I work for a company in the service and maintenance industry and we're about 10 years behind in our technology "vision". With that being said, every step is a leap and the return is massive but so are the efforts at times. To be specific our external service providers have been printing PDFs, filling them out with pen, and faxing/mailing them to us before we can invoice and be invoiced. Jumping from A to Z in this situation would be to go from paper to a mobile web application and create a PDF based on the data only if necessary, but I'm instead having to go from A to C to F... so building a PDF form that can be submitted via email is the next step. I created a template of the form in LibreOffice (as opposed to MS Word because the PDF form is retained when exporting as a PDF and LibreOffice is cross platform and scriptable). Then I apply a Submit button using Acrobat and have a full PDF template. Using iText (iTextSharp and C# via VisualStudio or SharpDevelop on Windows or Monodevelop on Linux), I can update the PDF template with work order specific information (work order #, date, location, equipment, etc) and distribute it to the provider via email. The provider performs the work and emails it back using the Submit button. I have a PHP script that watches a mailbox, and calls PDFtk against the attachment to pull the field names and values, validate that the necessary information is included, kicks it back to the provider if not or attaches to the work order in our CRM.

Believe it or not, this could be fully automatic if I could figure out how to make LibreOffice make the submit button properly, or apply it programmatically otherwise. No matter what templating scheme you use, it usually boils down to working in XML. Scribus, LibreOffice/OpenOffice and Word are all based on XML. Normally, LibreOffice/OpenOffice and Word work with a zip file container of the data (meaning you can open a DOCX file with a zip program to see the content as individual components). They all have the ability to work with flat XML files (fodt, xml, and sla) which is very handy for creating automated templates as you can work with the XML directly (without decompressing, modifying and recreating the container) and then perform various functions using a script interface to the software itself.

Adam
Apr 23, 2014 at 9:24 AM
Edited Apr 23, 2014 at 9:24 AM
Hi
I try to do that ut I have now an error xml on the header2.xml
I try to do a table on the header
It's not possible to use on the header ?
Thanks
Apr 23, 2014 at 5:41 PM
Post or email your PHP script and I'll check it against my package. Thanks!
May 5, 2014 at 3:07 AM
Hi
Do you think that I can do this package with the new version of phpword 0.9 ?
We can find already a 2nd parameter $rowStyle
Thanks
May 8, 2014 at 12:03 AM
I'm not aware of version .9 being available. I looked just now and do not see it available in the Source Code area or the Downloads area. I believe my changes received good feedback, so I wouldn't be surprised if they were integrated in a future release though.

I'm happy to assist you, but you're not being very forthcoming or helpful.
May 8, 2014 at 12:26 AM
Bill_VA wrote:
Adam, since the last release was almost 3 years ago, any ETA on another release? This tool is really an awesome thing. I found PHPExcel a couple weeks ago and am now able to create some really nice and complicated spreadsheets. This PHPWord tool is shaping up to being something really great.

Did I read your other comment right about you all working on a PHP to PDF tool?
Hi again Bill. I wanted to circle back with you and mention the TCPDF library. One of the most frustrating things about working with PHPWord for me is pagination and breaks. The ability to tell with much certainty where I am on a page (cursor wise, if that's a good analogy) isn't as clear in PHPWord as I would like and it makes outputting a 'mostly polished' document difficult when you start using tables.

TCPDF gives you fairly accurate X,Y coordinate of where you are that is very helpful. But the output is then mostly static being a PDF.
May 8, 2014 at 1:33 AM
FYI, I had some issues with version 8 today (page numbers in footers) and went to GitHub and found version 10 was released and stable. I had to redo a little bit of code, but otherwise looks and works well. (https://github.com/PHPOffice/PHPWord/releases/tag/0.10.0)

Adam, thanks for the info on TCPDF, I'll take a look.
May 8, 2014 at 3:19 AM
Hi
Thanks
I try also version 10 and it 's same better