Workaround for copying style with PHPExcel

phpexcel

I want to copy the style information from cells to ranges, like Format Painter in Excel. The documentation says to do something like this:

$activeSheet->duplicateStyle($activeSheet->getStyle('A1'), 'D1:D100');
$activeSheet->duplicateStyle($activeSheet->getStyle('B1'), 'E1:E100');

There appears to be a bug because both D1:D100 and E1:E100 get the style from cell B1. If I change the order of the two lines, both ranges get the style from A1. Similarly,

$styleA = $activeSheet->getStyle('A1');
$styleB = $activeSheet->getStyle('B1');
$activeSheet->duplicateStyle($styleA, 'D1:D100');

results in D1:D100 getting style info from cell B1. The last getStyle value is used in all duplicateStyle results.

I'm sure that a future release of PHPExcel will have a fix, I just need to figure out a work-around until then.

Best Answer

One workround for you might be to use the style xf Indexes:

$xfIndex = $activeSheet->getCell('A1')->getXfIndex();

Then to set that value for the xfIndex of all cells in the range

for ($col = 'D'; $col != 'E'; ++$col) {
    for ($row = 1; $row <= 100; ++$row) {
        $activeSheet->getCell($col . $row)->setXfIndex($xfIndex);
    }
}

EDIT

Alternatively, apply fix to the duplicateStyle() method in Classes/PHPExcel/Worksheet.php

lines 1479 to 1486 currently read:

if ($this->_parent->cellXfExists($pCellStyle)) {
    // there is already this cell Xf in our collection
    $xfIndex = $pCellStyle->getIndex();
} else {
    // we don't have such a cell Xf, need to add
    $workbook->addCellXf($pCellStyle);
    $xfIndex = $pCellStyle->getIndex();
}

change to:

if ($existingStyle = $this->_parent->getCellXfByHashCode($pCellStyle->getHashCode())) {
    // there is already such cell Xf in our collection
    $xfIndex = $existingStyle->getIndex();
} else {
    // we don't have such a cell Xf, need to add
    $workbook->addCellXf($pCellStyle);
    $xfIndex = $pCellStyle->getIndex();
}

Similarly in the applyFromArray() method in Classes/PHPExcel/Style.php

lines 425 to 432 currently read:

if ($workbook->cellXfExists($newStyle)) {
    // there is already such cell Xf in our collection
    $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex();
} else {
    // we don't have such a cell Xf, need to add
    $workbook->addCellXf($newStyle);
    $newXfIndexes[$oldXfIndex] = $newStyle->getIndex();
}

change to:

if ($existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode())) {
    // there is already such cell Xf in our collection
    $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex();
} else {
    // we don't have such a cell Xf, need to add
    $workbook->addCellXf($newStyle);
    $newXfIndexes[$oldXfIndex] = $newStyle->getIndex();
}

EDIT #2

Fix has now been pushed to the develop branch on github. It does give a slight performance hit, depending on the number of styles in use... I'll try and get a faster version tomorrow night

Related Topic