PHPWord icon indicating copy to clipboard operation
PHPWord copied to clipboard

How to delete row from table in phpword tamplate?

Open n-osennij opened this issue 9 years ago • 9 comments

I have a table in my *.docx tamplate. I clonerow it. But how can i delete some clonerowed row? Fore example, how can i delete clonerowed row with mark ${names17}? It is very important fore my.


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

n-osennij avatar Mar 18 '16 09:03 n-osennij

I join a question

ZAZmaster avatar Jul 26 '16 11:07 ZAZmaster

HI, i add this function in Template.php

`public function removeTableRow($search){ if (substr($search, 0, 2) !== "${" && substr($search, -1) !== "}") { $search = "${" . $search . "}"; }

    $tagPos = strpos($this->documentXML, $search);
    
    if (!$tagPos) {
        throw new Exception("Can not remove row, template variable not found or variable contains markup.");
    }
    
    $rowStart = $this->findRowStart($tagPos);
    $rowEnd = $this->findRowEnd($tagPos);
    $xmlRow = $this->getSlice($rowStart, $rowEnd);
    
    $this->documentXML = str_replace($xmlRow, "", $this->documentXML);
    return TRUE;
}`

lahirwisada avatar Apr 03 '17 16:04 lahirwisada

@lahirwisada need replace $this->documentXML (is not found in TemplateProcessor) to $this->tempDocumentMainPart

public function deleteRow($search) { if ('${' !== substr($search, 0, 2) && '}' !== substr($search, -1)) { $search = '${' . $search . '}'; }

    $tagPos = strpos($this->tempDocumentMainPart, $search);

    if (!$tagPos) {
        throw new Exception("Can not remove row, template variable not found or variable contains markup. ". $search);
    }

    $rowStart = $this->findRowStart($tagPos);
    $rowEnd = $this->findRowEnd($tagPos);
    $xmlRow = $this->getSlice($rowStart, $rowEnd);

    $this->tempDocumentMainPart = str_replace($xmlRow, "", $this->tempDocumentMainPart);

    return true;

}

curtisjackson avatar Dec 26 '17 12:12 curtisjackson

i got a case inside the row there is an nest table , and will got issues. so i change the code a bit . in the template , if added "${/keyword}" , then will check the row end from here instead of from "${keywords}"

` public function deleteRow($search) {

    if ('${' !== substr($search, 0, 2) && '}' !== substr($search, -1)) {
        $search_start = '${' . $search . '}';
    }

    $tagPos = strpos($this->tempDocumentMainPart, $search_start);
    
    if (!$tagPos) {
        // throw new Exception("Can not remove row, template variable not found or variable contains markup.");
        return FALSE;
    }

    $search_end = '${/' . $search . '}';
    $tagPos_end = strpos($this->tempDocumentMainPart, $search_end);
    if (!$tagPos_end) {
        $tagPos_end = $tagPos;
        // error_log($search_end . 'not found');
    }
    
    $rowStart = $this->findRowStart($tagPos);
    $rowEnd = $this->findRowEnd($tagPos_end);
    $xmlRow = $this->getSlice($rowStart, $rowEnd);
    
    $this->tempDocumentMainPart = str_replace($xmlRow, "", $this->tempDocumentMainPart);
    return TRUE;
    

}`

melice avatar Jun 30 '18 09:06 melice

This is the solution that I came up with based on the ideas above:

/**
    * Deletes all rows matching the provided search tag.
    * Inspired by <https://github.com/PHPOffice/PHPWord/issues/762>
    *
    * @param $search - string to query
    * @return int - number of rows removed.
    */
public function deleteRow(string $search): int
{
    if ('${' !== substr($search, 0, 2) && '}' !== substr($search, -1)) {
        $search = '${' . $search . '}';
    }

    $count = 0;
    while (($tagPos = strpos($this->tempDocumentMainPart, $search))) {
        $count++;
        $rowStart = $this->findRowStart($tagPos);
        $rowEnd = $this->findRowEnd($tagPos);
        $xmlRow = $this->getSlice($rowStart, $rowEnd);
        $this->tempDocumentMainPart = str_replace($xmlRow, "", $this->tempDocumentMainPart);
    }
    return $count;
}

Append the function to vendor/phpoffice/phpword/src/PhpWord/TemplateProcessor.php in your project. Hope this helps future devs. 🙂

Edit: A more elegant solution would be to subclass TemplateProcessor with this method overridden.

scottzach1 avatar Jun 18 '21 05:06 scottzach1

Thanks a lot, that helps!!! Why sould this not be added to the next release version?

strtob avatar Jun 20 '21 19:06 strtob

Pity, the decision for this problem is not in the prodaction.

A simple task to delete one row from a table cannot be accomplished. And I certainly will not be editing vendor files for this.

mgrechanik avatar Sep 10 '21 11:09 mgrechanik

+1 for MR the solution

liluxdev avatar Oct 19 '21 12:10 liluxdev

Hey, you can try this: $templateProcessor->cloneRow($fieldName, 0); also: $templateProcessor->cloneRowAndSetValues($fieldName, []); It work for me

YummiK avatar Aug 05 '22 06:08 YummiK

Hey, you can try this: $templateProcessor->cloneRow($fieldName, 0); also: $templateProcessor->cloneRowAndSetValues($fieldName, []); It work for me

Thanks for this solution, worked exactly as I needed !

singeryo avatar Oct 31 '22 09:10 singeryo