mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-14 20:16:34 +00:00
Better Definitions for Mixed Parameters and Values Part 2 of Many
Continuing work started with PR #4019. Improve documentation within program by making explicit what types of values are allowed for variables described as "mixed". In order to avoid broken functionality, this is done mainly through doc-blocks. This will get us closer to Phpstan Level 9, but many changes will be needed before we can consider that. This change has more executable code changes than its predecessor. I will wait longer than normal before merging it to allow for additional testing.
This commit is contained in:
@@ -288,7 +288,7 @@ class Cells
|
||||
$newCollection->index[$key] = $value;
|
||||
$stored = $newCollection->cache->set(
|
||||
$newCollection->cachePrefix . $key,
|
||||
clone $this->cache->get($this->cachePrefix . $key)
|
||||
clone $this->getCache($key)
|
||||
);
|
||||
if ($stored === false) {
|
||||
$this->destructIfNeeded($newCollection, 'Failed to copy cells in cache');
|
||||
@@ -410,11 +410,7 @@ class Cells
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if the entry that has been requested actually exists in the cache
|
||||
$cell = $this->cache->get($this->cachePrefix . $cellCoordinate);
|
||||
if ($cell === null) {
|
||||
throw new PhpSpreadsheetException("Cell entry {$cellCoordinate} no longer exists in cache. This probably means that the cache was cleared by someone else.");
|
||||
}
|
||||
$cell = $this->getcache($cellCoordinate);
|
||||
|
||||
// Set current entry to the requested entry
|
||||
$this->currentCoordinate = $cellCoordinate;
|
||||
@@ -466,4 +462,14 @@ class Cells
|
||||
yield $this->cachePrefix . $coordinate;
|
||||
}
|
||||
}
|
||||
|
||||
private function getCache(string $cellCoordinate): Cell
|
||||
{
|
||||
$cell = $this->cache->get($this->cachePrefix . $cellCoordinate);
|
||||
if (!($cell instanceof Cell)) {
|
||||
throw new PhpSpreadsheetException("Cell entry {$cellCoordinate} no longer exists in cache. This probably means that the cache was cleared by someone else.");
|
||||
}
|
||||
|
||||
return $cell;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Helper;
|
||||
|
||||
use DOMAttr;
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use DOMNode;
|
||||
@@ -708,6 +709,7 @@ class Html
|
||||
{
|
||||
$attrs = $tag->attributes;
|
||||
if ($attrs !== null) {
|
||||
/** @var DOMAttr $attribute */
|
||||
foreach ($attrs as $attribute) {
|
||||
$attributeName = strtolower($attribute->name);
|
||||
$attributeName = preg_replace('/^html:/', '', $attributeName) ?? $attributeName; // in case from Xml spreadsheet
|
||||
|
||||
@@ -81,13 +81,9 @@ class Sample
|
||||
$regex = new RegexIterator($iterator, '/^.+\.php$/', RecursiveRegexIterator::GET_MATCH);
|
||||
|
||||
$files = [];
|
||||
/** @var string[] $file */
|
||||
foreach ($regex as $file) {
|
||||
$file = str_replace(str_replace('\\', '/', $baseDir) . '/', '', str_replace('\\', '/', $file[0]));
|
||||
if (is_array($file)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new RuntimeException('str_replace returned array');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
$info = pathinfo($file);
|
||||
$category = str_replace('_', ' ', $info['dirname'] ?? '');
|
||||
$name = str_replace('_', ' ', (string) preg_replace('/(|\.php)/', '', $info['filename']));
|
||||
@@ -254,10 +250,10 @@ class Sample
|
||||
?string $descriptionCell = null
|
||||
): void {
|
||||
if ($descriptionCell !== null) {
|
||||
$this->log($worksheet->getCell($descriptionCell)->getValue());
|
||||
$this->log($worksheet->getCell($descriptionCell)->getValueString());
|
||||
}
|
||||
$this->log($worksheet->getCell($formulaCell)->getValue());
|
||||
$this->log(sprintf('%s() Result is ', $functionName) . $worksheet->getCell($formulaCell)->getCalculatedValue());
|
||||
$this->log($worksheet->getCell($formulaCell)->getValueString());
|
||||
$this->log(sprintf('%s() Result is ', $functionName) . $worksheet->getCell($formulaCell)->getCalculatedValueString());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Reader;
|
||||
|
||||
use DOMAttr;
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use DOMNode;
|
||||
@@ -291,6 +292,7 @@ class Html extends BaseReader
|
||||
private function processDomElementBody(Worksheet $sheet, int &$row, string &$column, string &$cellContent, DOMElement $child): void
|
||||
{
|
||||
$attributeArray = [];
|
||||
/** @var DOMAttr $attribute */
|
||||
foreach ($child->attributes as $attribute) {
|
||||
$attributeArray[$attribute->name] = $attribute->value;
|
||||
}
|
||||
|
||||
@@ -268,6 +268,7 @@ class Slk extends BaseReader
|
||||
if ($sharedFormula === true && $sharedRow >= 0 && $sharedColumn >= 0) {
|
||||
$thisCoordinate = Coordinate::stringFromColumnIndex((int) $column) . $row;
|
||||
$sharedCoordinate = Coordinate::stringFromColumnIndex($sharedColumn) . $sharedRow;
|
||||
/** @var string */
|
||||
$formula = $spreadsheet->getActiveSheet()->getCell($sharedCoordinate)->getValue();
|
||||
$spreadsheet->getActiveSheet()->getCell($thisCoordinate)->setValue($formula);
|
||||
$referenceHelper = ReferenceHelper::getInstance();
|
||||
@@ -281,6 +282,7 @@ class Slk extends BaseReader
|
||||
return;
|
||||
}
|
||||
$columnLetter = Coordinate::stringFromColumnIndex((int) $column);
|
||||
/** @var string */
|
||||
$cellData = Calculation::unwrapResult($cellData);
|
||||
|
||||
// Set cell value
|
||||
|
||||
@@ -32,6 +32,8 @@ class SpgrContainer
|
||||
|
||||
/**
|
||||
* Add a child. This will be either spgrContainer or spContainer.
|
||||
*
|
||||
* @param SpgrContainer|SpgrContainer\SpContainer $child child to be added
|
||||
*/
|
||||
public function addChild(mixed $child): void
|
||||
{
|
||||
|
||||
@@ -253,7 +253,7 @@ class Spreadsheet implements JsonSerializable
|
||||
*/
|
||||
public function setRibbonXMLData(mixed $target, mixed $xmlData): void
|
||||
{
|
||||
if ($target !== null && $xmlData !== null) {
|
||||
if (is_string($target) && is_string($xmlData)) {
|
||||
$this->ribbonXMLData = ['target' => $target, 'data' => $xmlData];
|
||||
} else {
|
||||
$this->ribbonXMLData = null;
|
||||
|
||||
@@ -235,7 +235,7 @@ class CellMatcher
|
||||
self::COMPARISON_DUPLICATES_OPERATORS[$conditional->getConditionType()],
|
||||
$worksheetName,
|
||||
$this->conditionalRange,
|
||||
$this->cellConditionCheck($this->cell->getCalculatedValue())
|
||||
$this->cellConditionCheck($this->cell->getCalculatedValueString())
|
||||
);
|
||||
|
||||
return $this->evaluateExpression($expression);
|
||||
|
||||
@@ -69,6 +69,7 @@ class CellValue extends WizardAbstract implements WizardInterface
|
||||
$this->operandValueType[$index] = $operandValueType;
|
||||
}
|
||||
|
||||
/** @param null|bool|float|int|string $value value to be wrapped */
|
||||
protected function wrapValue(mixed $value, string $operandValueType): float|int|string
|
||||
{
|
||||
if (!is_numeric($value) && !is_bool($value) && null !== $value) {
|
||||
@@ -175,7 +176,9 @@ class CellValue extends WizardAbstract implements WizardInterface
|
||||
if (count($arguments) < 2) {
|
||||
$this->operand(0, $arguments[0]);
|
||||
} else {
|
||||
$this->operand(0, $arguments[0], $arguments[1]);
|
||||
/** @var string */
|
||||
$arg1 = $arguments[1];
|
||||
$this->operand(0, $arguments[0], $arg1);
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
||||
@@ -54,7 +54,7 @@ class Expression extends WizardAbstract implements WizardInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $arguments
|
||||
* @param string[] $arguments
|
||||
*/
|
||||
public function __call(string $methodName, array $arguments): self
|
||||
{
|
||||
|
||||
@@ -148,9 +148,15 @@ class TextValue extends WizardAbstract implements WizardInterface
|
||||
$this->operator(self::MAGIC_OPERATIONS[$methodName]);
|
||||
//$this->operand(...$arguments);
|
||||
if (count($arguments) < 2) {
|
||||
$this->operand($arguments[0]);
|
||||
/** @var string */
|
||||
$arg0 = $arguments[0];
|
||||
$this->operand($arg0);
|
||||
} else {
|
||||
$this->operand($arguments[0], $arguments[1]);
|
||||
/** @var string */
|
||||
$arg0 = $arguments[0];
|
||||
/** @var string */
|
||||
$arg1 = $arguments[1];
|
||||
$this->operand($arg0, $arg1);
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
||||
@@ -115,6 +115,7 @@ class DateFormatter
|
||||
}
|
||||
}
|
||||
|
||||
/** @param float|int $value value to be formatted */
|
||||
public static function format(mixed $value, string $format): string
|
||||
{
|
||||
// strip off first part containing e.g. [$-F800] or [$USD-409]
|
||||
|
||||
@@ -185,6 +185,7 @@ class NumberFormatter extends BaseFormatter
|
||||
return self::pregReplace(self::NUMBER_REGEX, $value, $format);
|
||||
}
|
||||
|
||||
/** @param float|int|numeric-string $value value to be formatted */
|
||||
public static function format(mixed $value, string $format): string
|
||||
{
|
||||
// The "_" in this string has already been stripped out,
|
||||
|
||||
@@ -309,7 +309,7 @@ class AutoFilter implements Stringable
|
||||
/**
|
||||
* Test if cell value is in the defined set of values.
|
||||
*
|
||||
* @param mixed[] $dataSet
|
||||
* @param array{blanks: bool, filterValues: array<string,array<string,string>>} $dataSet
|
||||
*/
|
||||
protected static function filterTestInSimpleDataSet(mixed $cellValue, array $dataSet): bool
|
||||
{
|
||||
@@ -325,7 +325,7 @@ class AutoFilter implements Stringable
|
||||
/**
|
||||
* Test if cell value is in the defined set of Excel date values.
|
||||
*
|
||||
* @param mixed[] $dataSet
|
||||
* @param array{blanks: bool, filterValues: array<string,array<string,string>>} $dataSet
|
||||
*/
|
||||
protected static function filterTestInDateGroupSet(mixed $cellValue, array $dataSet): bool
|
||||
{
|
||||
@@ -763,9 +763,13 @@ class AutoFilter implements Stringable
|
||||
sort($dataValues);
|
||||
}
|
||||
|
||||
$slice = array_slice($dataValues, 0, $ruleValue);
|
||||
|
||||
$retVal = array_pop($slice);
|
||||
if (is_numeric($ruleValue)) {
|
||||
$ruleValue = (int) $ruleValue;
|
||||
}
|
||||
if ($ruleValue === null || is_int($ruleValue)) {
|
||||
$slice = array_slice($dataValues, 0, $ruleValue);
|
||||
$retVal = array_pop($slice);
|
||||
}
|
||||
}
|
||||
|
||||
return $retVal;
|
||||
@@ -968,7 +972,7 @@ class AutoFilter implements Stringable
|
||||
$ruleOperator = $rule->getOperator();
|
||||
}
|
||||
if (is_numeric($ruleValue) && $ruleOperator === Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) {
|
||||
$ruleValue = floor((float) $ruleValue * ($dataRowCount / 100));
|
||||
$ruleValue = (int) floor((float) $ruleValue * ($dataRowCount / 100));
|
||||
}
|
||||
if (!is_array($ruleValue) && $ruleValue < 1) {
|
||||
$ruleValue = 1;
|
||||
@@ -977,6 +981,7 @@ class AutoFilter implements Stringable
|
||||
$ruleValue = 500;
|
||||
}
|
||||
|
||||
/** @var float|int|string */
|
||||
$maxVal = $this->calculateTopTenValue($columnID, $rangeStart[1] + 1, (int) $rangeEnd[1], $toptenRuleType, $ruleValue);
|
||||
|
||||
$operator = ($toptenRuleType == Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP)
|
||||
@@ -1003,6 +1008,7 @@ class AutoFilter implements Stringable
|
||||
// Execute the filter test
|
||||
/** @var callable */
|
||||
$temp = [self::class, $columnFilterTest['method']];
|
||||
/** @var bool */
|
||||
$result // $result && // phpstan says $result is always true here
|
||||
= call_user_func_array($temp, [$cellValue, $columnFilterTest['arguments']]);
|
||||
// If filter test has resulted in FALSE, exit the loop straightaway rather than running any more tests
|
||||
|
||||
@@ -76,7 +76,7 @@ class Column
|
||||
/**
|
||||
* Autofilter Column Dynamic Attributes.
|
||||
*
|
||||
* @var mixed[]
|
||||
* @var (float|int|string)[]
|
||||
*/
|
||||
private array $attributes = [];
|
||||
|
||||
@@ -209,7 +209,7 @@ class Column
|
||||
/**
|
||||
* Set AutoFilter Attributes.
|
||||
*
|
||||
* @param mixed[] $attributes
|
||||
* @param (float|int|string)[] $attributes
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -225,7 +225,7 @@ class Column
|
||||
* Set An AutoFilter Attribute.
|
||||
*
|
||||
* @param string $name Attribute Name
|
||||
* @param int|string $value Attribute Value
|
||||
* @param float|int|string $value Attribute Value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
@@ -240,7 +240,7 @@ class Column
|
||||
/**
|
||||
* Get AutoFilter Column Attributes.
|
||||
*
|
||||
* @return int[]|string[]
|
||||
* @return (float|int|string)[]
|
||||
*/
|
||||
public function getAttributes(): array
|
||||
{
|
||||
@@ -252,7 +252,7 @@ class Column
|
||||
*
|
||||
* @param string $name Attribute Name
|
||||
*/
|
||||
public function getAttribute(string $name): null|int|string
|
||||
public function getAttribute(string $name): null|float|int|string
|
||||
{
|
||||
if (isset($this->attributes[$name])) {
|
||||
return $this->attributes[$name];
|
||||
@@ -360,6 +360,7 @@ class Column
|
||||
public function __clone()
|
||||
{
|
||||
$vars = get_object_vars($this);
|
||||
/** @var AutoFilter\Column\Rule[] $value */
|
||||
foreach ($vars as $key => $value) {
|
||||
if ($key === 'parent') {
|
||||
// Detach from autofilter parent
|
||||
|
||||
@@ -745,7 +745,7 @@ class Worksheet implements IComparable
|
||||
// Calculated value
|
||||
// To formatted string
|
||||
$cellValue = NumberFormat::toFormattedString(
|
||||
$cell->getCalculatedValue(),
|
||||
$cell->getCalculatedValueString(),
|
||||
(string) $this->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex())
|
||||
->getNumberFormat()->getFormatCode(true)
|
||||
);
|
||||
@@ -2795,6 +2795,8 @@ class Worksheet implements IComparable
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|bool|float|int|RichText|string $nullValue value to use when null
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws \PhpOffice\PhpSpreadsheet\Calculation\Exception
|
||||
*/
|
||||
@@ -2811,8 +2813,10 @@ class Worksheet implements IComparable
|
||||
|
||||
if ($formatData) {
|
||||
$style = $this->getParentOrThrow()->getCellXfByIndex($cell->getXfIndex());
|
||||
/** @var null|bool|float|int|RichText|string */
|
||||
$returnValuex = $returnValue;
|
||||
$returnValue = NumberFormat::toFormattedString(
|
||||
$returnValue,
|
||||
$returnValuex,
|
||||
$style->getNumberFormat()->getFormatCode() ?? NumberFormat::FORMAT_GENERAL
|
||||
);
|
||||
}
|
||||
@@ -2824,7 +2828,7 @@ class Worksheet implements IComparable
|
||||
/**
|
||||
* Create array from a range of cells.
|
||||
*
|
||||
* @param mixed $nullValue Value returned in the array entry if a cell doesn't exist
|
||||
* @param null|bool|float|int|RichText|string $nullValue Value returned in the array entry if a cell doesn't exist
|
||||
* @param bool $calculateFormulas Should formulas be calculated?
|
||||
* @param bool $formatData Should formatting be applied to cell values?
|
||||
* @param bool $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero
|
||||
@@ -2854,7 +2858,7 @@ class Worksheet implements IComparable
|
||||
/**
|
||||
* Create array from a range of cells, yielding each row in turn.
|
||||
*
|
||||
* @param mixed $nullValue Value returned in the array entry if a cell doesn't exist
|
||||
* @param null|bool|float|int|RichText|string $nullValue Value returned in the array entry if a cell doesn't exist
|
||||
* @param bool $calculateFormulas Should formulas be calculated?
|
||||
* @param bool $formatData Should formatting be applied to cell values?
|
||||
* @param bool $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero
|
||||
@@ -3002,7 +3006,7 @@ class Worksheet implements IComparable
|
||||
* Create array from a range of cells.
|
||||
*
|
||||
* @param string $definedName The Named Range that should be returned
|
||||
* @param mixed $nullValue Value returned in the array entry if a cell doesn't exist
|
||||
* @param null|bool|float|int|RichText|string $nullValue Value returned in the array entry if a cell doesn't exist
|
||||
* @param bool $calculateFormulas Should formulas be calculated?
|
||||
* @param bool $formatData Should formatting be applied to cell values?
|
||||
* @param bool $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero
|
||||
@@ -3035,7 +3039,7 @@ class Worksheet implements IComparable
|
||||
/**
|
||||
* Create array from worksheet.
|
||||
*
|
||||
* @param mixed $nullValue Value returned in the array entry if a cell doesn't exist
|
||||
* @param null|bool|float|int|RichText|string $nullValue Value returned in the array entry if a cell doesn't exist
|
||||
* @param bool $calculateFormulas Should formulas be calculated?
|
||||
* @param bool $formatData Should formatting be applied to cell values?
|
||||
* @param bool $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero
|
||||
@@ -3650,13 +3654,14 @@ class Worksheet implements IComparable
|
||||
{
|
||||
$toArray = Coordinate::extractAllCellReferencesInRange($toCells);
|
||||
$value = $this->getCell($fromCell)->getValue();
|
||||
$valueString = $this->getCell($fromCell)->getValueString();
|
||||
$style = $this->getStyle($fromCell)->exportArray();
|
||||
$fromIndexes = Coordinate::indexesFromString($fromCell);
|
||||
$referenceHelper = ReferenceHelper::getInstance();
|
||||
foreach ($toArray as $destination) {
|
||||
if ($destination !== $fromCell) {
|
||||
$toIndexes = Coordinate::indexesFromString($destination);
|
||||
$this->getCell($destination)->setValue($referenceHelper->updateFormulaReferences($value, 'A1', $toIndexes[0] - $fromIndexes[0], $toIndexes[1] - $fromIndexes[1]));
|
||||
$this->getCell($destination)->setValue($referenceHelper->updateFormulaReferences($valueString, 'A1', $toIndexes[0] - $fromIndexes[0], $toIndexes[1] - $fromIndexes[1]));
|
||||
if ($copyStyle) {
|
||||
$this->getCell($destination)->getStyle()->applyFromArray($style);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,9 @@ class ConditionalHelper
|
||||
$this->tokens = pack('Cv', 0x1E, $condition);
|
||||
} else {
|
||||
try {
|
||||
$formula = Wizard\WizardAbstract::reverseAdjustCellRef((string) $condition, $cellRange);
|
||||
/** @var float|int|string */
|
||||
$conditionx = $condition;
|
||||
$formula = Wizard\WizardAbstract::reverseAdjustCellRef((string) $conditionx, $cellRange);
|
||||
$this->parser->parse($formula);
|
||||
$this->tokens = $this->parser->toReversePolish();
|
||||
$this->size = strlen($this->tokens ?? '');
|
||||
|
||||
@@ -542,18 +542,18 @@ class Parser
|
||||
/**
|
||||
* Convert a number token to ptgInt or ptgNum.
|
||||
*
|
||||
* @param mixed $num an integer or double for conversion to its ptg value
|
||||
* @param float|int|string $num an integer or double for conversion to its ptg value
|
||||
*/
|
||||
private function convertNumber(mixed $num): string
|
||||
{
|
||||
// Integer in the range 0..2**16-1
|
||||
if ((preg_match('/^\\d+$/', $num)) && ($num <= 65535)) {
|
||||
if ((preg_match('/^\\d+$/', (string) $num)) && ($num <= 65535)) {
|
||||
return pack('Cv', $this->ptg['ptgInt'], $num);
|
||||
}
|
||||
|
||||
// A float
|
||||
if (BIFFwriter::getByteOrder()) { // if it's Big Endian
|
||||
$num = strrev($num);
|
||||
$num = strrev((string) $num);
|
||||
}
|
||||
|
||||
return pack('Cd', $this->ptg['ptgNum'], $num);
|
||||
|
||||
@@ -382,37 +382,37 @@ class Worksheet extends BIFFwriter
|
||||
if ($cVal === '' || $cVal === null) {
|
||||
$this->writeBlank($row, $column, $xfIndex);
|
||||
} else {
|
||||
$this->writeString($row, $column, $cVal, $xfIndex);
|
||||
$this->writeString($row, $column, $cell->getValueString(), $xfIndex);
|
||||
}
|
||||
|
||||
break;
|
||||
case DataType::TYPE_NUMERIC:
|
||||
$this->writeNumber($row, $column, $cVal, $xfIndex);
|
||||
$this->writeNumber($row, $column, is_numeric($cVal) ? ($cVal + 0) : 0, $xfIndex);
|
||||
|
||||
break;
|
||||
case DataType::TYPE_FORMULA:
|
||||
$calculatedValue = $this->preCalculateFormulas
|
||||
? $cell->getCalculatedValue() : null;
|
||||
if (self::WRITE_FORMULA_EXCEPTION == $this->writeFormula($row, $column, $cVal, $xfIndex, $calculatedValue)) {
|
||||
$calculatedValue = $this->preCalculateFormulas ? $cell->getCalculatedValue() : null;
|
||||
$calculatedValueString = $this->preCalculateFormulas ? $cell->getCalculatedValueString() : '';
|
||||
if (self::WRITE_FORMULA_EXCEPTION == $this->writeFormula($row, $column, $cell->getValueString(), $xfIndex, $calculatedValue)) {
|
||||
if ($calculatedValue === null) {
|
||||
$calculatedValue = $cell->getCalculatedValue();
|
||||
}
|
||||
$calctype = gettype($calculatedValue);
|
||||
match ($calctype) {
|
||||
'integer', 'double' => $this->writeNumber($row, $column, (float) $calculatedValue, $xfIndex),
|
||||
'string' => $this->writeString($row, $column, $calculatedValue, $xfIndex),
|
||||
'boolean' => $this->writeBoolErr($row, $column, (int) $calculatedValue, 0, $xfIndex),
|
||||
default => $this->writeString($row, $column, $cVal, $xfIndex),
|
||||
'integer', 'double' => $this->writeNumber($row, $column, is_numeric($calculatedValue) ? ((float) $calculatedValue) : 0.0, $xfIndex),
|
||||
'string' => $this->writeString($row, $column, $calculatedValueString, $xfIndex),
|
||||
'boolean' => $this->writeBoolErr($row, $column, (int) $calculatedValueString, 0, $xfIndex),
|
||||
default => $this->writeString($row, $column, $cell->getValueString(), $xfIndex),
|
||||
};
|
||||
}
|
||||
|
||||
break;
|
||||
case DataType::TYPE_BOOL:
|
||||
$this->writeBoolErr($row, $column, $cVal, 0, $xfIndex);
|
||||
$this->writeBoolErr($row, $column, (int) $cell->getValueString(), 0, $xfIndex);
|
||||
|
||||
break;
|
||||
case DataType::TYPE_ERROR:
|
||||
$this->writeBoolErr($row, $column, ErrorCode::error($cVal), 1, $xfIndex);
|
||||
$this->writeBoolErr($row, $column, ErrorCode::error($cell->getValueString()), 1, $xfIndex);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1399,6 +1399,7 @@ class Worksheet extends WriterPart
|
||||
private function writeCellFormula(XMLWriter $objWriter, string $cellValue, Cell $cell): void
|
||||
{
|
||||
$calculatedValue = $this->getParentWriter()->getPreCalculateFormulas() ? $cell->getCalculatedValue() : $cellValue;
|
||||
$calculatedValueString = $this->getParentWriter()->getPreCalculateFormulas() ? $cell->getCalculatedValueString() : $cellValue;
|
||||
if (is_string($calculatedValue)) {
|
||||
if (ErrorValue::isError($calculatedValue)) {
|
||||
$this->writeCellError($objWriter, 'e', $cellValue, $calculatedValue);
|
||||
@@ -1407,13 +1408,15 @@ class Worksheet extends WriterPart
|
||||
}
|
||||
$objWriter->writeAttribute('t', 'str');
|
||||
$calculatedValue = StringHelper::controlCharacterPHP2OOXML($calculatedValue);
|
||||
$calculatedValueString = $calculatedValue;
|
||||
} elseif (is_bool($calculatedValue)) {
|
||||
$objWriter->writeAttribute('t', 'b');
|
||||
$calculatedValue = (int) $calculatedValue;
|
||||
$calculatedValueString = (string) $calculatedValue;
|
||||
}
|
||||
|
||||
$attributes = $cell->getFormulaAttributes();
|
||||
if (($attributes['t'] ?? null) === 'array') {
|
||||
if (is_array($attributes) && ($attributes['t'] ?? null) === 'array') {
|
||||
$objWriter->startElement('f');
|
||||
$objWriter->writeAttribute('t', 'array');
|
||||
$objWriter->writeAttribute('ref', $cell->getCoordinate());
|
||||
@@ -1429,8 +1432,8 @@ class Worksheet extends WriterPart
|
||||
&& $this->getParentWriter()->getPreCalculateFormulas()
|
||||
&& $calculatedValue !== null,
|
||||
'v',
|
||||
(!is_array($calculatedValue) && !str_starts_with($calculatedValue ?? '', '#'))
|
||||
? StringHelper::formatNumber($calculatedValue) : '0'
|
||||
(!is_array($calculatedValue) && !str_starts_with($calculatedValueString, '#'))
|
||||
? StringHelper::formatNumber($calculatedValueString) : '0'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1447,6 +1450,7 @@ class Worksheet extends WriterPart
|
||||
$pCell = $worksheet->getCell($cellAddress);
|
||||
$xfi = $pCell->getXfIndex();
|
||||
$cellValue = $pCell->getValue();
|
||||
$cellValueString = $pCell->getValueString();
|
||||
$writeValue = $cellValue !== '' && $cellValue !== null;
|
||||
if (empty($xfi) && !$writeValue) {
|
||||
return;
|
||||
@@ -1469,27 +1473,30 @@ class Worksheet extends WriterPart
|
||||
// Write data depending on its type
|
||||
switch (strtolower($mappedType)) {
|
||||
case 'inlinestr': // Inline string
|
||||
$this->writeCellInlineStr($objWriter, $mappedType, $cellValue);
|
||||
/** @var RichText|string */
|
||||
$richText = $cellValue;
|
||||
$this->writeCellInlineStr($objWriter, $mappedType, $richText);
|
||||
|
||||
break;
|
||||
case 's': // String
|
||||
$this->writeCellString($objWriter, $mappedType, $cellValue, $flippedStringTable);
|
||||
$this->writeCellString($objWriter, $mappedType, $cellValueString, $flippedStringTable);
|
||||
|
||||
break;
|
||||
case 'f': // Formula
|
||||
$this->writeCellFormula($objWriter, $cellValue, $pCell);
|
||||
$this->writeCellFormula($objWriter, $cellValueString, $pCell);
|
||||
|
||||
break;
|
||||
case 'n': // Numeric
|
||||
$this->writeCellNumeric($objWriter, $cellValue);
|
||||
$cellValueNumeric = is_numeric($cellValue) ? ($cellValue + 0) : 0;
|
||||
$this->writeCellNumeric($objWriter, $cellValueNumeric);
|
||||
|
||||
break;
|
||||
case 'b': // Boolean
|
||||
$this->writeCellBoolean($objWriter, $mappedType, $cellValue);
|
||||
$this->writeCellBoolean($objWriter, $mappedType, (bool) $cellValue);
|
||||
|
||||
break;
|
||||
case 'e': // Error
|
||||
$this->writeCellError($objWriter, $mappedType, $cellValue);
|
||||
$this->writeCellError($objWriter, $mappedType, $cellValueString);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user