Merge pull request #4152 from oleibman/issue3185

Xls Writer Conditional Rules Applied to Whole Rows or Columns
This commit is contained in:
oleibman
2024-10-06 05:21:39 +00:00
committed by GitHub
3 changed files with 117 additions and 3 deletions
@@ -30,8 +30,8 @@ class ConditionalHelper
$this->condition = $condition;
$this->cellRange = $cellRange;
if (is_int($condition) || is_float($condition)) {
$this->size = ($condition <= 65535 ? 3 : 0x0000);
if (is_int($condition) && $condition >= 0 && $condition <= 65535) {
$this->size = 3;
$this->tokens = pack('Cv', 0x1E, $condition);
} else {
try {
+29 -1
View File
@@ -489,6 +489,31 @@ class Worksheet extends BIFFwriter
$this->storeEof();
}
public const MAX_XLS_COLUMN = 256;
public const MAX_XLS_COLUMN_STRING = 'IV';
public const MAX_XLS_ROW = 65536;
private static function limitRange(string $exploded): string
{
$retVal = '';
$ranges = Coordinate::getRangeBoundaries($exploded);
$firstCol = Coordinate::columnIndexFromString($ranges[0][0]);
$firstRow = (int) $ranges[0][1];
if ($firstCol <= self::MAX_XLS_COLUMN && $firstRow <= self::MAX_XLS_ROW) {
$retVal = $exploded;
if (str_contains($exploded, ':')) {
$lastCol = Coordinate::columnIndexFromString($ranges[1][0]);
$ranges[1][1] = min(self::MAX_XLS_ROW, (int) $ranges[1][1]);
if ($lastCol > self::MAX_XLS_COLUMN) {
$ranges[1][0] = self::MAX_XLS_COLUMN_STRING;
}
$retVal = "{$ranges[0][0]}{$ranges[0][1]}:{$ranges[1][0]}{$ranges[1][1]}";
}
}
return $retVal;
}
private function writeConditionalFormatting(): void
{
$conditionalFormulaHelper = new ConditionalHelper($this->parser);
@@ -497,7 +522,10 @@ class Worksheet extends BIFFwriter
foreach ($this->phpSheet->getConditionalStylesCollection() as $key => $value) {
$keyExplode = explode(',', Coordinate::resolveUnionAndIntersection($key));
foreach ($keyExplode as $exploded) {
$arrConditionalStyles[$exploded] = $value;
$range = self::limitRange($exploded);
if ($range !== '') {
$arrConditionalStyles[$range] = $value;
}
}
}
if (!empty($arrConditionalStyles)) {
@@ -0,0 +1,86 @@
<?php
declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests\Writer\Xls;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Style\Conditional;
use PhpOffice\PhpSpreadsheet\Style\Style;
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
class ConditionalLimitsTest extends AbstractFunctional
{
public function testLimits(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->fromArray(
[
['Cell', 0, null, null, 'Col Rng', -2, -1],
[null, null, null, null, null, 0, 1],
['Cell Rng', -2, -1, 0, null, 2, 3],
[null, 1, 2, 3, null, 4, -1],
[],
['Row Rng'],
[-2, -1, 0],
[1, 2, 3],
],
strictNullComparison: true
);
$redStyle = new Style(false, true);
$redStyle->getFont()->setColor(new Color(Color::COLOR_RED));
$condition1 = new Conditional();
$condition1->setConditionType(Conditional::CONDITION_CELLIS)
->setOperatorType(Conditional::OPERATOR_BETWEEN)
->addCondition(-1)
->addCondition(1)
->setStyle($redStyle);
$conditionalStyles = [$condition1];
$cellRange = 'B1';
$sheet->getStyle($cellRange)->setConditionalStyles($conditionalStyles);
$condition2 = new Conditional();
$condition2->setConditionType(Conditional::CONDITION_CELLIS)
->setOperatorType(Conditional::OPERATOR_BETWEEN)
->addCondition(-1.5)
->addCondition(1.5)
->setStyle($redStyle);
$conditionalStyles = [$condition2];
$cellRange = 'F:G';
$sheet->getStyle($cellRange)->setConditionalStyles($conditionalStyles);
$condition3 = new Conditional();
$condition3->setConditionType(Conditional::CONDITION_CELLIS)
->setOperatorType(Conditional::OPERATOR_BETWEEN)
->addCondition(-1)
->addCondition(70000)
->setStyle($redStyle);
$conditionalStyles = [$condition3];
$cellRange = '7:8';
$sheet->getStyle($cellRange)->setConditionalStyles($conditionalStyles);
$cellRange = 'B3:D4';
$sheet->getStyle($cellRange)->setConditionalStyles($conditionalStyles);
$sheet->setSelectedCells('A1');
$keys = array_keys($sheet->getConditionalStylesCollection());
self::assertSame(['B1', 'F1:G1048576', 'A7:XFD8', 'B3:D4'], $keys);
$robj = $this->writeAndReload($spreadsheet, 'Xls');
$spreadsheet->disconnectWorksheets();
$sheet0 = $robj->getActiveSheet();
$conditionals = $sheet0->getConditionalStylesCollection();
self::assertSame(['B1', 'F1:G65536', 'A7:IV8', 'B3:D4'], array_keys($conditionals));
$b1 = $conditionals['B1'][0];
self::assertSame([-1, 1], $b1->getConditions());
$b1 = $conditionals['F1:G65536'][0];
self::assertSame([-1.5, 1.5], $b1->getConditions());
$b1 = $conditionals['A7:IV8'][0];
self::assertSame([-1, 70000], $b1->getConditions());
$b1 = $conditionals['B3:D4'][0];
self::assertSame([-1, 70000], $b1->getConditions());
$robj->disconnectWorksheets();
}
}