Resolve saving cell references, string literals and formula as values for conditional formatting rules in the Xls file save
The code is ugly as sin; but it works... I'll do some refactoring and cleaning later (once I've had some sleep, because I'm stupidly still working on this at 3am) The main remaining issue is formulae that can't be parsed in BIFF8 files; e.g. formulae that use functions that aren't available. In this case, all CF in that worksheet is corrupted, and the file errors when opened, so it is a serious issue. The ISODD()/ISEVEN example in 07_Expression_Comparisons.php uses these, so I've temporarily commented out setting that CF range until I've solved that problem. There are other limitations listed in the BIFF documentation; but they're harder to detect. I've also left a couple of debug statements in the code to display these formula errors: I'll remove them once I've resolved the issue.
This commit is contained in:
parent
7e89d3397e
commit
9ca9d741fe
|
|
@ -28,6 +28,7 @@ $helper->log('Add data');
|
||||||
$spreadsheet->setActiveSheetIndex(0);
|
$spreadsheet->setActiveSheetIndex(0);
|
||||||
$spreadsheet->getActiveSheet()
|
$spreadsheet->getActiveSheet()
|
||||||
->setCellValue('A1', 'Odd/Even Expression Comparison')
|
->setCellValue('A1', 'Odd/Even Expression Comparison')
|
||||||
|
->setCellValue('A4', 'Note that these functions are not available for Xls files')
|
||||||
->setCellValue('A15', 'Sales Grid Expression Comparison')
|
->setCellValue('A15', 'Sales Grid Expression Comparison')
|
||||||
->setCellValue('A25', 'Sales Grid Multiple Expression Comparison');
|
->setCellValue('A25', 'Sales Grid Multiple Expression Comparison');
|
||||||
|
|
||||||
|
|
@ -101,9 +102,9 @@ $expressionWizard->expression('ISEVEN(A1)')
|
||||||
->setStyle($yellowStyle);
|
->setStyle($yellowStyle);
|
||||||
$conditionalStyles[] = $expressionWizard->getConditional();
|
$conditionalStyles[] = $expressionWizard->getConditional();
|
||||||
|
|
||||||
$spreadsheet->getActiveSheet()
|
//$spreadsheet->getActiveSheet()
|
||||||
->getStyle($expressionWizard->getCellRange())
|
// ->getStyle($expressionWizard->getCellRange())
|
||||||
->setConditionalStyles($conditionalStyles);
|
// ->setConditionalStyles($conditionalStyles);
|
||||||
|
|
||||||
// Set rules for Sales Grid Row match against Country Comparison
|
// Set rules for Sales Grid Row match against Country Comparison
|
||||||
$cellRange = 'A17:D22';
|
$cellRange = 'A17:D22';
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ abstract class WizardAbstract
|
||||||
return "{$worksheet}{$column}{$row}";
|
return "{$worksheet}{$column}{$row}";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function reverseAdjustCellRef(string $condition, string $cellRange): string
|
public static function reverseAdjustCellRef(string $condition, string $cellRange): string
|
||||||
{
|
{
|
||||||
$conditionalRange = Coordinate::splitRange(str_replace('$', '', strtoupper($cellRange)));
|
$conditionalRange = Coordinate::splitRange(str_replace('$', '', strtoupper($cellRange)));
|
||||||
[$referenceCell] = $conditionalRange[0];
|
[$referenceCell] = $conditionalRange[0];
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ use PhpOffice\PhpSpreadsheet\Shared\Xls;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Color;
|
use PhpOffice\PhpSpreadsheet\Style\Color;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Conditional;
|
use PhpOffice\PhpSpreadsheet\Style\Conditional;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard;
|
||||||
use PhpOffice\PhpSpreadsheet\Style\Protection;
|
use PhpOffice\PhpSpreadsheet\Style\Protection;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup;
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\SheetView;
|
use PhpOffice\PhpSpreadsheet\Worksheet\SheetView;
|
||||||
|
|
@ -569,7 +570,7 @@ class Worksheet extends BIFFwriter
|
||||||
$arrConditional[$conditional->getHashCode()] = true;
|
$arrConditional[$conditional->getHashCode()] = true;
|
||||||
|
|
||||||
// Write CFRULE record
|
// Write CFRULE record
|
||||||
$this->writeCFRule($conditional);
|
$this->writeCFRule($conditional, $cellCoordinate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2779,7 +2780,7 @@ class Worksheet extends BIFFwriter
|
||||||
/**
|
/**
|
||||||
* Write CFRule Record.
|
* Write CFRule Record.
|
||||||
*/
|
*/
|
||||||
private function writeCFRule(Conditional $conditional): void
|
private function writeCFRule(Conditional $conditional, string $cellRange): void
|
||||||
{
|
{
|
||||||
$record = 0x01B1; // Record identifier
|
$record = 0x01B1; // Record identifier
|
||||||
$type = null; // Type of the CF
|
$type = null; // Type of the CF
|
||||||
|
|
@ -2832,21 +2833,59 @@ class Worksheet extends BIFFwriter
|
||||||
// $szValue2 : size of the formula data for second value or formula
|
// $szValue2 : size of the formula data for second value or formula
|
||||||
$arrConditions = $conditional->getConditions();
|
$arrConditions = $conditional->getConditions();
|
||||||
$numConditions = count($arrConditions);
|
$numConditions = count($arrConditions);
|
||||||
if ($numConditions == 1) {
|
|
||||||
$szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000);
|
|
||||||
$szValue2 = 0x0000;
|
|
||||||
$operand1 = pack('Cv', 0x1E, $arrConditions[0]);
|
|
||||||
$operand2 = null;
|
|
||||||
} elseif ($numConditions == 2 && ($conditional->getOperatorType() == Conditional::OPERATOR_BETWEEN)) {
|
|
||||||
$szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000);
|
|
||||||
$szValue2 = ($arrConditions[1] <= 65535 ? 3 : 0x0000);
|
|
||||||
$operand1 = pack('Cv', 0x1E, $arrConditions[0]);
|
|
||||||
$operand2 = pack('Cv', 0x1E, $arrConditions[1]);
|
|
||||||
} else {
|
|
||||||
$szValue1 = 0x0000;
|
$szValue1 = 0x0000;
|
||||||
$szValue2 = 0x0000;
|
$szValue2 = 0x0000;
|
||||||
$operand1 = null;
|
$operand1 = null;
|
||||||
$operand2 = null;
|
$operand2 = null;
|
||||||
|
|
||||||
|
if ($numConditions == 1) {
|
||||||
|
if (is_int($arrConditions[0]) || is_float($arrConditions[0])) {
|
||||||
|
$szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000);
|
||||||
|
$operand1 = pack('Cv', 0x1E, $arrConditions[0]);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$formula1 = Wizard\WizardAbstract::reverseAdjustCellRef((string) $arrConditions[0], $cellRange);
|
||||||
|
$this->parser->parse($formula1);
|
||||||
|
$formula1 = $this->parser->toReversePolish();
|
||||||
|
$szValue1 = strlen($formula1);
|
||||||
|
} catch (PhpSpreadsheetException $e) {
|
||||||
|
var_dump("PARSER EXCEPTION: {$e->getMessage()}");
|
||||||
|
$formula1 = null;
|
||||||
|
}
|
||||||
|
$operand1 = $formula1;
|
||||||
|
}
|
||||||
|
} elseif ($numConditions == 2 && ($conditional->getOperatorType() == Conditional::OPERATOR_BETWEEN)) {
|
||||||
|
if (is_int($arrConditions[0]) || is_float($arrConditions[0])) {
|
||||||
|
$szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000);
|
||||||
|
$operand1 = pack('Cv', 0x1E, $arrConditions[0]);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$formula1 = Wizard\WizardAbstract::reverseAdjustCellRef((string) $arrConditions[0], $cellRange);
|
||||||
|
$this->parser->parse($formula1);
|
||||||
|
$formula1 = $this->parser->toReversePolish();
|
||||||
|
$szValue1 = strlen($formula1);
|
||||||
|
} catch (PhpSpreadsheetException $e) {
|
||||||
|
var_dump("PARSER EXCEPTION: {$e->getMessage()}");
|
||||||
|
$formula1 = null;
|
||||||
|
}
|
||||||
|
$operand1 = $formula1;
|
||||||
|
}
|
||||||
|
if (is_int($arrConditions[1]) || is_float($arrConditions[1])) {
|
||||||
|
$szValue2 = ($arrConditions[1] <= 65535 ? 3 : 0x0000);
|
||||||
|
$operand2 = pack('Cv', 0x1E, $arrConditions[1]);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$formula2 = Wizard\WizardAbstract::reverseAdjustCellRef((string) $arrConditions[1], $cellRange);
|
||||||
|
$this->parser->parse($formula2);
|
||||||
|
$formula2 = $this->parser->toReversePolish();
|
||||||
|
$szValue2 = strlen($formula2);
|
||||||
|
} catch (PhpSpreadsheetException $e) {
|
||||||
|
var_dump("PARSER EXCEPTION: {$e->getMessage()}");
|
||||||
|
$formula2 = null;
|
||||||
|
}
|
||||||
|
$operand2 = $formula2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// $flags : Option flags
|
// $flags : Option flags
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue