From @Skrol29 answer i understand the current situation and wrote a simple function for my case since I need to work with an excel with dozens of merged cells. What my function did is to push all the merged cells located entirely under the placeholder row
function pushMergedCellsDown($TBS, $placeholderRow, $dataCount) {
if ($dataCount <= 1) {
return; // No need to move anything if there's no additional data
}
$pushDistance = $dataCount - 1;
$pattern = '/<mergeCell ref="([A-Z]+)(\d+):([A-Z]+)(\d+)"\/>/';
// Find all merged cells in the XML
if (preg_match_all($pattern, $TBS->Source, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
$colStart = $match[1];
$rowStart = intval($match[2]);
$colEnd = $match[3];
$rowEnd = intval($match[4]);
// Check if any mergeCell crosses or is on the placeholder row
if ($rowStart <= $placeholderRow && $rowEnd >= $placeholderRow) {
throw new Exception("Merge cell crossing placeholder row detected: {$match[0]}");
}
// Only process mergeCells entirely below the placeholder row
if ($rowStart > $placeholderRow) {
$newRowStart = $rowStart + $pushDistance;
$newRowEnd = $rowEnd + $pushDistance;
$newTag = "<mergeCell ref=\"{$colStart}{$newRowStart}:{$colEnd}{$newRowEnd}\"/>";
$TBS->Source = str_replace($match[0], $newTag, $TBS->Source);
}
}
}
}
the function takes 3 parameters: $TBS the opentbs object, $placeholderRow the row where our data placeholder is located, and $dataCount which is the size of our data.
for my example case, the usage is like this
// Merge data in the first sheet
$TBS->MergeBlock('a,b', $data);
pushMergedCellsDown($TBS, 20, count($data));
Appreciated your work on openTBS library @Skrol29 ^^