@@ -766,6 +766,77 @@ public function cloneRow($search, $numberOfClones)
766
766
$ this ->tempDocumentMainPart = $ result ;
767
767
}
768
768
769
+ /**
770
+ * Delete a table row in a template document.
771
+ *
772
+ * @param string $search
773
+ *
774
+ * @return void
775
+ *
776
+ * @throws \PhpOffice\PhpWord\Exception\Exception
777
+ */
778
+ public function deleteRow ($ search )
779
+ {
780
+ if ('${ ' !== substr ($ search , 0 , 2 ) && '} ' !== substr ($ search , -1 )) {
781
+ $ search = '${ ' . $ search . '} ' ;
782
+ }
783
+
784
+ $ tagPos = strpos ($ this ->tempDocumentMainPart , $ search );
785
+ if (!$ tagPos ) {
786
+ throw new Exception (sprintf ("Can not delete row %s, template variable not found or variable contains markup. " , $ search ));
787
+ }
788
+
789
+ $ tableStart = $ this ->findTableStart ($ tagPos );
790
+ $ tableEnd = $ this ->findTableEnd ($ tagPos );
791
+ $ xmlTable = $ this ->getSlice ($ tableStart , $ tableEnd );
792
+
793
+ if (substr_count ($ xmlTable , '<w:tr ' ) === 1 ) {
794
+ $ this ->tempDocumentMainPart = $ this ->getSlice (0 , $ tableStart ) . $ this ->getSlice ($ tableEnd );
795
+
796
+ return ;
797
+ }
798
+
799
+ $ rowStart = $ this ->findRowStart ($ tagPos );
800
+ $ rowEnd = $ this ->findRowEnd ($ tagPos );
801
+ $ xmlRow = $ this ->getSlice ($ rowStart , $ rowEnd );
802
+
803
+ $ this ->tempDocumentMainPart = $ this ->getSlice (0 , $ rowStart ) . $ this ->getSlice ($ rowEnd );
804
+
805
+ // Check if there's a cell spanning multiple rows.
806
+ if (preg_match ('#<w:vMerge w:val="restart"/># ' , $ xmlRow )) {
807
+ // $extraRowStart = $rowEnd;
808
+ $ extraRowStart = $ rowStart ;
809
+ while (true ) {
810
+ $ extraRowStart = $ this ->findRowStart ($ extraRowStart + 1 );
811
+ $ extraRowEnd = $ this ->findRowEnd ($ extraRowStart + 1 );
812
+
813
+ // If extraRowEnd is lower then 7, there was no next row found.
814
+ if ($ extraRowEnd < 7 ) {
815
+ break ;
816
+ }
817
+
818
+ // If tmpXmlRow doesn't contain continue, this row is no longer part of the spanned row.
819
+ $ tmpXmlRow = $ this ->getSlice ($ extraRowStart , $ extraRowEnd );
820
+ if (!preg_match ('#<w:vMerge/># ' , $ tmpXmlRow ) &&
821
+ !preg_match ('#<w:vMerge w:val="continue" /># ' , $ tmpXmlRow )
822
+ ) {
823
+ break ;
824
+ }
825
+
826
+ $ tableStart = $ this ->findTableStart ($ extraRowEnd + 1 );
827
+ $ tableEnd = $ this ->findTableEnd ($ extraRowEnd + 1 );
828
+ $ xmlTable = $ this ->getSlice ($ tableStart , $ tableEnd );
829
+ if (substr_count ($ xmlTable , '<w:tr ' ) === 1 ) {
830
+ $ this ->tempDocumentMainPart = $ this ->getSlice (0 , $ tableStart ) . $ this ->getSlice ($ tableEnd );
831
+
832
+ return ;
833
+ }
834
+
835
+ $ this ->tempDocumentMainPart = $ this ->getSlice (0 , $ extraRowStart ) . $ this ->getSlice ($ extraRowEnd );
836
+ }
837
+ }
838
+ }
839
+
769
840
/**
770
841
* Clones a table row and populates it's values from a two-dimensional array in a template document.
771
842
*
@@ -1088,6 +1159,43 @@ protected function getDocumentContentTypesName()
1088
1159
return '[Content_Types].xml ' ;
1089
1160
}
1090
1161
1162
+ /**
1163
+ * Find the start position of the nearest table before $offset.
1164
+ *
1165
+ * @param integer $offset
1166
+ *
1167
+ * @return integer
1168
+ *
1169
+ * @throws \PhpOffice\PhpWord\Exception\Exception
1170
+ */
1171
+ protected function findTableStart ($ offset )
1172
+ {
1173
+ $ rowStart = strrpos ($ this ->tempDocumentMainPart , '<w:tbl ' ,
1174
+ ((strlen ($ this ->tempDocumentMainPart ) - $ offset ) * -1 ));
1175
+
1176
+ if (!$ rowStart ) {
1177
+ $ rowStart = strrpos ($ this ->tempDocumentMainPart , '<w:tbl> ' ,
1178
+ ((strlen ($ this ->tempDocumentMainPart ) - $ offset ) * -1 ));
1179
+ }
1180
+ if (!$ rowStart ) {
1181
+ throw new Exception ('Can not find the start position of the table. ' );
1182
+ }
1183
+
1184
+ return $ rowStart ;
1185
+ }
1186
+
1187
+ /**
1188
+ * Find the end position of the nearest table row after $offset.
1189
+ *
1190
+ * @param integer $offset
1191
+ *
1192
+ * @return integer
1193
+ */
1194
+ protected function findTableEnd ($ offset )
1195
+ {
1196
+ return strpos ($ this ->tempDocumentMainPart , '</w:tbl> ' , $ offset ) + 7 ;
1197
+ }
1198
+
1091
1199
/**
1092
1200
* Find the start position of the nearest table row before $offset.
1093
1201
*
0 commit comments