mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2025-12-24 10:21:32 +01:00
Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
This commit is contained in:
22
htdocs/includes/phpoffice/phpspreadsheet/src/Bootstrap.php
Normal file
22
htdocs/includes/phpoffice/phpspreadsheet/src/Bootstrap.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Bootstrap for PhpSpreadsheet classes.
|
||||
*/
|
||||
|
||||
// This sucks, but we have to try to find the composer autoloader
|
||||
|
||||
$paths = [
|
||||
__DIR__ . '/../vendor/autoload.php', // In case PhpSpreadsheet is cloned directly
|
||||
__DIR__ . '/../../../autoload.php', // In case PhpSpreadsheet is a composer dependency.
|
||||
];
|
||||
|
||||
foreach ($paths as $path) {
|
||||
if (file_exists($path)) {
|
||||
require_once $path;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new \Exception('Composer autoloader could not be found. Install dependencies with `composer install` and try again.');
|
||||
@@ -25,7 +25,7 @@ class Calculation
|
||||
// Function (allow for the old @ symbol that could be used to prefix a function, but we'll ignore it)
|
||||
const CALCULATION_REGEXP_FUNCTION = '@?(?:_xlfn\.)?([A-Z][A-Z0-9\.]*)[\s]*\(';
|
||||
// Cell reference (cell or range of cells, with or without a sheet reference)
|
||||
const CALCULATION_REGEXP_CELLREF = '((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]{1,3})\$?(\d{1,7})';
|
||||
const CALCULATION_REGEXP_CELLREF = '((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?\b([a-z]{1,3})\$?(\d{1,7})(?![\w.])';
|
||||
// Named Range of cells
|
||||
const CALCULATION_REGEXP_NAMEDRANGE = '((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?([_A-Z][_A-Z0-9\.]*)';
|
||||
// Error
|
||||
@@ -66,6 +66,15 @@ class Calculation
|
||||
*/
|
||||
private $calculationCacheEnabled = true;
|
||||
|
||||
/**
|
||||
* Used to generate unique store keys.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $branchStoreKeyCounter = 0;
|
||||
|
||||
private $branchPruningEnabled = true;
|
||||
|
||||
/**
|
||||
* List of operators that can be used within formulae
|
||||
* The true/false value indicates whether it is a binary operator or a unary operator.
|
||||
@@ -254,6 +263,11 @@ class Calculation
|
||||
'functionCall' => [Logical::class, 'logicalAnd'],
|
||||
'argumentCount' => '1+',
|
||||
],
|
||||
'ARABIC' => [
|
||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||
'functionCall' => [MathTrig::class, 'ARABIC'],
|
||||
'argumentCount' => '1',
|
||||
],
|
||||
'AREAS' => [
|
||||
'category' => Category::CATEGORY_LOOKUP_AND_REFERENCE,
|
||||
'functionCall' => [Functions::class, 'DUMMY'],
|
||||
@@ -319,6 +333,11 @@ class Calculation
|
||||
'functionCall' => [Functions::class, 'DUMMY'],
|
||||
'argumentCount' => '1',
|
||||
],
|
||||
'BASE' => [
|
||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||
'functionCall' => [MathTrig::class, 'BASE'],
|
||||
'argumentCount' => '2,3',
|
||||
],
|
||||
'BESSELI' => [
|
||||
'category' => Category::CATEGORY_ENGINEERING,
|
||||
'functionCall' => [Engineering::class, 'BESSELI'],
|
||||
@@ -527,7 +546,7 @@ class Calculation
|
||||
],
|
||||
'COUNTIFS' => [
|
||||
'category' => Category::CATEGORY_STATISTICAL,
|
||||
'functionCall' => [Functions::class, 'DUMMY'],
|
||||
'functionCall' => [Statistical::class, 'COUNTIFS'],
|
||||
'argumentCount' => '2+',
|
||||
],
|
||||
'COUPDAYBS' => [
|
||||
@@ -895,6 +914,16 @@ class Calculation
|
||||
'functionCall' => [MathTrig::class, 'FLOOR'],
|
||||
'argumentCount' => '2',
|
||||
],
|
||||
'FLOOR.MATH' => [
|
||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||
'functionCall' => [MathTrig::class, 'FLOORMATH'],
|
||||
'argumentCount' => '3',
|
||||
],
|
||||
'FLOOR.PRECISE' => [
|
||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||
'functionCall' => [MathTrig::class, 'FLOORPRECISE'],
|
||||
'argumentCount' => '2',
|
||||
],
|
||||
'FORECAST' => [
|
||||
'category' => Category::CATEGORY_STATISTICAL,
|
||||
'functionCall' => [Statistical::class, 'FORECAST'],
|
||||
@@ -1018,6 +1047,16 @@ class Calculation
|
||||
'functionCall' => [Logical::class, 'IFERROR'],
|
||||
'argumentCount' => '2',
|
||||
],
|
||||
'IFNA' => [
|
||||
'category' => Category::CATEGORY_LOGICAL,
|
||||
'functionCall' => [Logical::class, 'IFNA'],
|
||||
'argumentCount' => '2',
|
||||
],
|
||||
'IFS' => [
|
||||
'category' => Category::CATEGORY_LOGICAL,
|
||||
'functionCall' => [Functions::class, 'DUMMY'],
|
||||
'argumentCount' => '2+',
|
||||
],
|
||||
'IMABS' => [
|
||||
'category' => Category::CATEGORY_ENGINEERING,
|
||||
'functionCall' => [Engineering::class, 'IMABS'],
|
||||
@@ -1356,10 +1395,10 @@ class Calculation
|
||||
'functionCall' => [Statistical::class, 'MAXA'],
|
||||
'argumentCount' => '1+',
|
||||
],
|
||||
'MAXIF' => [
|
||||
'MAXIFS' => [
|
||||
'category' => Category::CATEGORY_STATISTICAL,
|
||||
'functionCall' => [Statistical::class, 'MAXIF'],
|
||||
'argumentCount' => '2+',
|
||||
'functionCall' => [Statistical::class, 'MAXIFS'],
|
||||
'argumentCount' => '3+',
|
||||
],
|
||||
'MDETERM' => [
|
||||
'category' => Category::CATEGORY_MATH_AND_TRIG,
|
||||
@@ -1401,10 +1440,10 @@ class Calculation
|
||||
'functionCall' => [Statistical::class, 'MINA'],
|
||||
'argumentCount' => '1+',
|
||||
],
|
||||
'MINIF' => [
|
||||
'MINIFS' => [
|
||||
'category' => Category::CATEGORY_STATISTICAL,
|
||||
'functionCall' => [Statistical::class, 'MINIF'],
|
||||
'argumentCount' => '2+',
|
||||
'functionCall' => [Statistical::class, 'MINIFS'],
|
||||
'argumentCount' => '3+',
|
||||
],
|
||||
'MINUTE' => [
|
||||
'category' => Category::CATEGORY_DATE_AND_TIME,
|
||||
@@ -1474,7 +1513,12 @@ class Calculation
|
||||
'NETWORKDAYS' => [
|
||||
'category' => Category::CATEGORY_DATE_AND_TIME,
|
||||
'functionCall' => [DateTime::class, 'NETWORKDAYS'],
|
||||
'argumentCount' => '2+',
|
||||
'argumentCount' => '2-3',
|
||||
],
|
||||
'NETWORKDAYS.INTL' => [
|
||||
'category' => Category::CATEGORY_DATE_AND_TIME,
|
||||
'functionCall' => [Functions::class, 'DUMMY'],
|
||||
'argumentCount' => '2-4',
|
||||
],
|
||||
'NOMINAL' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
@@ -2143,7 +2187,12 @@ class Calculation
|
||||
'WORKDAY' => [
|
||||
'category' => Category::CATEGORY_DATE_AND_TIME,
|
||||
'functionCall' => [DateTime::class, 'WORKDAY'],
|
||||
'argumentCount' => '2+',
|
||||
'argumentCount' => '2-3',
|
||||
],
|
||||
'WORKDAY.INTL' => [
|
||||
'category' => Category::CATEGORY_DATE_AND_TIME,
|
||||
'functionCall' => [Functions::class, 'DUMMY'],
|
||||
'argumentCount' => '2-4',
|
||||
],
|
||||
'XIRR' => [
|
||||
'category' => Category::CATEGORY_FINANCIAL,
|
||||
@@ -2196,7 +2245,7 @@ class Calculation
|
||||
private static $controlFunctions = [
|
||||
'MKMATRIX' => [
|
||||
'argumentCount' => '*',
|
||||
'functionCall' => 'self::mkMatrix',
|
||||
'functionCall' => [__CLASS__, 'mkMatrix'],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -2251,6 +2300,7 @@ class Calculation
|
||||
public function flushInstance()
|
||||
{
|
||||
$this->clearCalculationCache();
|
||||
$this->clearBranchStore();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2394,6 +2444,32 @@ class Calculation
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable calculation cache.
|
||||
*
|
||||
* @param bool $pValue
|
||||
* @param mixed $enabled
|
||||
*/
|
||||
public function setBranchPruningEnabled($enabled)
|
||||
{
|
||||
$this->branchPruningEnabled = $enabled;
|
||||
}
|
||||
|
||||
public function enableBranchPruning()
|
||||
{
|
||||
$this->setBranchPruningEnabled(true);
|
||||
}
|
||||
|
||||
public function disableBranchPruning()
|
||||
{
|
||||
$this->setBranchPruningEnabled(false);
|
||||
}
|
||||
|
||||
public function clearBranchStore()
|
||||
{
|
||||
$this->branchStoreKeyCounter = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently defined locale code.
|
||||
*
|
||||
@@ -2416,7 +2492,7 @@ class Calculation
|
||||
// Identify our locale and language
|
||||
$language = $locale = strtolower($locale);
|
||||
if (strpos($locale, '_') !== false) {
|
||||
list($language) = explode('_', $locale);
|
||||
[$language] = explode('_', $locale);
|
||||
}
|
||||
if (count(self::$validLocaleLanguages) == 1) {
|
||||
self::loadLocales();
|
||||
@@ -2441,9 +2517,9 @@ class Calculation
|
||||
// Retrieve the list of locale or language specific function names
|
||||
$localeFunctions = file($functionNamesFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
foreach ($localeFunctions as $localeFunction) {
|
||||
list($localeFunction) = explode('##', $localeFunction); // Strip out comments
|
||||
[$localeFunction] = explode('##', $localeFunction); // Strip out comments
|
||||
if (strpos($localeFunction, '=') !== false) {
|
||||
list($fName, $lfName) = explode('=', $localeFunction);
|
||||
[$fName, $lfName] = explode('=', $localeFunction);
|
||||
$fName = trim($fName);
|
||||
$lfName = trim($lfName);
|
||||
if ((isset(self::$phpSpreadsheetFunctions[$fName])) && ($lfName != '') && ($fName != $lfName)) {
|
||||
@@ -2466,9 +2542,9 @@ class Calculation
|
||||
if (file_exists($configFile)) {
|
||||
$localeSettings = file($configFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
foreach ($localeSettings as $localeSetting) {
|
||||
list($localeSetting) = explode('##', $localeSetting); // Strip out comments
|
||||
[$localeSetting] = explode('##', $localeSetting); // Strip out comments
|
||||
if (strpos($localeSetting, '=') !== false) {
|
||||
list($settingName, $settingValue) = explode('=', $localeSetting);
|
||||
[$settingName, $settingValue] = explode('=', $localeSetting);
|
||||
$settingName = strtoupper(trim($settingName));
|
||||
switch ($settingName) {
|
||||
case 'ARGUMENTSEPARATOR':
|
||||
@@ -2772,7 +2848,7 @@ class Calculation
|
||||
}
|
||||
self::$returnArrayAsType = $returnArrayAsType;
|
||||
|
||||
if ($result === null) {
|
||||
if ($result === null && $pCell->getWorksheet()->getSheetView()->getShowZeros()) {
|
||||
return 0;
|
||||
} elseif ((is_float($result)) && ((is_nan($result)) || (is_infinite($result)))) {
|
||||
return Functions::NAN();
|
||||
@@ -2823,13 +2899,13 @@ class Calculation
|
||||
$this->debugLog->clearLog();
|
||||
$this->cyclicReferenceStack->clear();
|
||||
|
||||
$resetCache = $this->getCalculationCacheEnabled();
|
||||
if ($this->spreadsheet !== null && $cellID === null && $pCell === null) {
|
||||
$cellID = 'A1';
|
||||
$pCell = $this->spreadsheet->getActiveSheet()->getCell($cellID);
|
||||
} else {
|
||||
// Disable calculation cacheing because it only applies to cell calculations, not straight formulae
|
||||
// But don't actually flush any cache
|
||||
$resetCache = $this->getCalculationCacheEnabled();
|
||||
$this->calculationCacheEnabled = false;
|
||||
}
|
||||
|
||||
@@ -2862,6 +2938,7 @@ class Calculation
|
||||
if (($this->calculationCacheEnabled) && (isset($this->calculationCache[$cellReference]))) {
|
||||
$this->debugLog->writeDebugLog('Retrieving value for cell ', $cellReference, ' from cache');
|
||||
// Return the cached result
|
||||
|
||||
$cellValue = $this->calculationCache[$cellReference];
|
||||
|
||||
return true;
|
||||
@@ -2977,17 +3054,17 @@ class Calculation
|
||||
// Examine each of the two operands, and turn them into an array if they aren't one already
|
||||
// Note that this function should only be called if one or both of the operand is already an array
|
||||
if (!is_array($operand1)) {
|
||||
list($matrixRows, $matrixColumns) = self::getMatrixDimensions($operand2);
|
||||
[$matrixRows, $matrixColumns] = self::getMatrixDimensions($operand2);
|
||||
$operand1 = array_fill(0, $matrixRows, array_fill(0, $matrixColumns, $operand1));
|
||||
$resize = 0;
|
||||
} elseif (!is_array($operand2)) {
|
||||
list($matrixRows, $matrixColumns) = self::getMatrixDimensions($operand1);
|
||||
[$matrixRows, $matrixColumns] = self::getMatrixDimensions($operand1);
|
||||
$operand2 = array_fill(0, $matrixRows, array_fill(0, $matrixColumns, $operand2));
|
||||
$resize = 0;
|
||||
}
|
||||
|
||||
list($matrix1Rows, $matrix1Columns) = self::getMatrixDimensions($operand1);
|
||||
list($matrix2Rows, $matrix2Columns) = self::getMatrixDimensions($operand2);
|
||||
[$matrix1Rows, $matrix1Columns] = self::getMatrixDimensions($operand1);
|
||||
[$matrix2Rows, $matrix2Columns] = self::getMatrixDimensions($operand2);
|
||||
if (($matrix1Rows == $matrix2Columns) && ($matrix2Rows == $matrix1Columns)) {
|
||||
$resize = 1;
|
||||
}
|
||||
@@ -3197,7 +3274,7 @@ class Calculation
|
||||
/**
|
||||
* @param string $formula
|
||||
*
|
||||
* @return string
|
||||
* @return false|string False indicates an error
|
||||
*/
|
||||
private function convertMatrixReferences($formula)
|
||||
{
|
||||
@@ -3321,9 +3398,53 @@ class Calculation
|
||||
// - is a negation or + is a positive operator rather than an operation
|
||||
$expectingOperand = false; // We use this test in syntax-checking the expression to determine whether an operand
|
||||
// should be null in a function call
|
||||
|
||||
// IF branch pruning
|
||||
// currently pending storeKey (last item of the storeKeysStack
|
||||
$pendingStoreKey = null;
|
||||
// stores a list of storeKeys (string[])
|
||||
$pendingStoreKeysStack = [];
|
||||
$expectingConditionMap = []; // ['storeKey' => true, ...]
|
||||
$expectingThenMap = []; // ['storeKey' => true, ...]
|
||||
$expectingElseMap = []; // ['storeKey' => true, ...]
|
||||
$parenthesisDepthMap = []; // ['storeKey' => 4, ...]
|
||||
|
||||
// The guts of the lexical parser
|
||||
// Loop through the formula extracting each operator and operand in turn
|
||||
while (true) {
|
||||
// Branch pruning: we adapt the output item to the context (it will
|
||||
// be used to limit its computation)
|
||||
$currentCondition = null;
|
||||
$currentOnlyIf = null;
|
||||
$currentOnlyIfNot = null;
|
||||
$previousStoreKey = null;
|
||||
$pendingStoreKey = end($pendingStoreKeysStack);
|
||||
|
||||
if ($this->branchPruningEnabled) {
|
||||
// this is a condition ?
|
||||
if (isset($expectingConditionMap[$pendingStoreKey]) && $expectingConditionMap[$pendingStoreKey]) {
|
||||
$currentCondition = $pendingStoreKey;
|
||||
$stackDepth = count($pendingStoreKeysStack);
|
||||
if ($stackDepth > 1) { // nested if
|
||||
$previousStoreKey = $pendingStoreKeysStack[$stackDepth - 2];
|
||||
}
|
||||
}
|
||||
if (isset($expectingThenMap[$pendingStoreKey]) && $expectingThenMap[$pendingStoreKey]) {
|
||||
$currentOnlyIf = $pendingStoreKey;
|
||||
} elseif (isset($previousStoreKey)) {
|
||||
if (isset($expectingThenMap[$previousStoreKey]) && $expectingThenMap[$previousStoreKey]) {
|
||||
$currentOnlyIf = $previousStoreKey;
|
||||
}
|
||||
}
|
||||
if (isset($expectingElseMap[$pendingStoreKey]) && $expectingElseMap[$pendingStoreKey]) {
|
||||
$currentOnlyIfNot = $pendingStoreKey;
|
||||
} elseif (isset($previousStoreKey)) {
|
||||
if (isset($expectingElseMap[$previousStoreKey]) && $expectingElseMap[$previousStoreKey]) {
|
||||
$currentOnlyIfNot = $previousStoreKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$opCharacter = $formula[$index]; // Get the first character of the value at the current index position
|
||||
if ((isset(self::$comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset(self::$comparisonOperators[$formula[$index + 1]]))) {
|
||||
$opCharacter .= $formula[++$index];
|
||||
@@ -3333,10 +3454,12 @@ class Calculation
|
||||
$isOperandOrFunction = preg_match($regexpMatchString, substr($formula, $index), $match);
|
||||
|
||||
if ($opCharacter == '-' && !$expectingOperator) { // Is it a negation instead of a minus?
|
||||
$stack->push('Unary Operator', '~'); // Put a negation on the stack
|
||||
// Put a negation on the stack
|
||||
$stack->push('Unary Operator', '~', null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot);
|
||||
++$index; // and drop the negation symbol
|
||||
} elseif ($opCharacter == '%' && $expectingOperator) {
|
||||
$stack->push('Unary Operator', '%'); // Put a percentage on the stack
|
||||
// Put a percentage on the stack
|
||||
$stack->push('Unary Operator', '%', null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot);
|
||||
++$index;
|
||||
} elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (unary plus rather than binary operator plus) can be discarded?
|
||||
++$index; // Drop the redundant plus symbol
|
||||
@@ -3349,7 +3472,10 @@ class Calculation
|
||||
@(self::$operatorAssociativity[$opCharacter] ? self::$operatorPrecedence[$opCharacter] < self::$operatorPrecedence[$o2['value']] : self::$operatorPrecedence[$opCharacter] <= self::$operatorPrecedence[$o2['value']])) {
|
||||
$output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output
|
||||
}
|
||||
$stack->push('Binary Operator', $opCharacter); // Finally put our current operator onto the stack
|
||||
|
||||
// Finally put our current operator onto the stack
|
||||
$stack->push('Binary Operator', $opCharacter, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot);
|
||||
|
||||
++$index;
|
||||
$expectingOperator = false;
|
||||
} elseif ($opCharacter == ')' && $expectingOperator) { // Are we expecting to close a parenthesis?
|
||||
@@ -3361,7 +3487,29 @@ class Calculation
|
||||
$output[] = $o2;
|
||||
}
|
||||
$d = $stack->last(2);
|
||||
if (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $d['value'], $matches)) { // Did this parenthesis just close a function?
|
||||
|
||||
// Branch pruning we decrease the depth whether is it a function
|
||||
// call or a parenthesis
|
||||
if (!empty($pendingStoreKey)) {
|
||||
$parenthesisDepthMap[$pendingStoreKey] -= 1;
|
||||
}
|
||||
|
||||
if (is_array($d) && preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $d['value'], $matches)) { // Did this parenthesis just close a function?
|
||||
if (!empty($pendingStoreKey) && $parenthesisDepthMap[$pendingStoreKey] == -1) {
|
||||
// we are closing an IF(
|
||||
if ($d['value'] != 'IF(') {
|
||||
return $this->raiseFormulaError('Parser bug we should be in an "IF("');
|
||||
}
|
||||
if ($expectingConditionMap[$pendingStoreKey]) {
|
||||
return $this->raiseFormulaError('We should not be expecting a condition');
|
||||
}
|
||||
$expectingThenMap[$pendingStoreKey] = false;
|
||||
$expectingElseMap[$pendingStoreKey] = false;
|
||||
$parenthesisDepthMap[$pendingStoreKey] -= 1;
|
||||
array_pop($pendingStoreKeysStack);
|
||||
unset($pendingStoreKey);
|
||||
}
|
||||
|
||||
$functionName = $matches[1]; // Get the function name
|
||||
$d = $stack->pop();
|
||||
$argumentCount = $d['value']; // See how many arguments there were (argument count is the next value stored on the stack)
|
||||
@@ -3422,6 +3570,20 @@ class Calculation
|
||||
}
|
||||
++$index;
|
||||
} elseif ($opCharacter == ',') { // Is this the separator for function arguments?
|
||||
if (!empty($pendingStoreKey) &&
|
||||
$parenthesisDepthMap[$pendingStoreKey] == 0
|
||||
) {
|
||||
// We must go to the IF next argument
|
||||
if ($expectingConditionMap[$pendingStoreKey]) {
|
||||
$expectingConditionMap[$pendingStoreKey] = false;
|
||||
$expectingThenMap[$pendingStoreKey] = true;
|
||||
} elseif ($expectingThenMap[$pendingStoreKey]) {
|
||||
$expectingThenMap[$pendingStoreKey] = false;
|
||||
$expectingElseMap[$pendingStoreKey] = true;
|
||||
} elseif ($expectingElseMap[$pendingStoreKey]) {
|
||||
return $this->raiseFormulaError('Reaching fourth argument of an IF');
|
||||
}
|
||||
}
|
||||
while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last (
|
||||
if ($o2 === null) {
|
||||
return $this->raiseFormulaError('Formula Error: Unexpected ,');
|
||||
@@ -3439,13 +3601,19 @@ class Calculation
|
||||
return $this->raiseFormulaError('Formula Error: Unexpected ,');
|
||||
}
|
||||
$d = $stack->pop();
|
||||
$stack->push($d['type'], ++$d['value'], $d['reference']); // increment the argument count
|
||||
$stack->push('Brace', '('); // put the ( back on, we'll need to pop back to it again
|
||||
$itemStoreKey = $d['storeKey'] ?? null;
|
||||
$itemOnlyIf = $d['onlyIf'] ?? null;
|
||||
$itemOnlyIfNot = $d['onlyIfNot'] ?? null;
|
||||
$stack->push($d['type'], ++$d['value'], $d['reference'], $itemStoreKey, $itemOnlyIf, $itemOnlyIfNot); // increment the argument count
|
||||
$stack->push('Brace', '(', null, $itemStoreKey, $itemOnlyIf, $itemOnlyIfNot); // put the ( back on, we'll need to pop back to it again
|
||||
$expectingOperator = false;
|
||||
$expectingOperand = true;
|
||||
++$index;
|
||||
} elseif ($opCharacter == '(' && !$expectingOperator) {
|
||||
$stack->push('Brace', '(');
|
||||
if (!empty($pendingStoreKey)) { // Branch pruning: we go deeper
|
||||
$parenthesisDepthMap[$pendingStoreKey] += 1;
|
||||
}
|
||||
$stack->push('Brace', '(', null, $currentCondition, $currentOnlyIf, $currentOnlyIf);
|
||||
++$index;
|
||||
} elseif ($isOperandOrFunction && !$expectingOperator) { // do we now have a function/variable/number?
|
||||
$expectingOperator = true;
|
||||
@@ -3456,13 +3624,28 @@ class Calculation
|
||||
if (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $val, $matches)) {
|
||||
$val = preg_replace('/\s/u', '', $val);
|
||||
if (isset(self::$phpSpreadsheetFunctions[strtoupper($matches[1])]) || isset(self::$controlFunctions[strtoupper($matches[1])])) { // it's a function
|
||||
$stack->push('Function', strtoupper($val));
|
||||
$valToUpper = strtoupper($val);
|
||||
// here $matches[1] will contain values like "IF"
|
||||
// and $val "IF("
|
||||
if ($this->branchPruningEnabled && ($valToUpper == 'IF(')) { // we handle a new if
|
||||
$pendingStoreKey = $this->getUnusedBranchStoreKey();
|
||||
$pendingStoreKeysStack[] = $pendingStoreKey;
|
||||
$expectingConditionMap[$pendingStoreKey] = true;
|
||||
$parenthesisDepthMap[$pendingStoreKey] = 0;
|
||||
} else { // this is not a if but we good deeper
|
||||
if (!empty($pendingStoreKey) && array_key_exists($pendingStoreKey, $parenthesisDepthMap)) {
|
||||
$parenthesisDepthMap[$pendingStoreKey] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
$stack->push('Function', $valToUpper, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot);
|
||||
// tests if the function is closed right after opening
|
||||
$ax = preg_match('/^\s*(\s*\))/ui', substr($formula, $index + $length), $amatch);
|
||||
if ($ax) {
|
||||
$stack->push('Operand Count for Function ' . strtoupper($val) . ')', 0);
|
||||
$stack->push('Operand Count for Function ' . $valToUpper . ')', 0, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot);
|
||||
$expectingOperator = true;
|
||||
} else {
|
||||
$stack->push('Operand Count for Function ' . strtoupper($val) . ')', 1);
|
||||
$stack->push('Operand Count for Function ' . $valToUpper . ')', 1, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot);
|
||||
$expectingOperator = false;
|
||||
}
|
||||
$stack->push('Brace', '(');
|
||||
@@ -3475,7 +3658,7 @@ class Calculation
|
||||
|
||||
// If the last entry on the stack was a : operator, then we have a cell range reference
|
||||
$testPrevOp = $stack->last(1);
|
||||
if ($testPrevOp['value'] == ':') {
|
||||
if ($testPrevOp !== null && $testPrevOp['value'] == ':') {
|
||||
// If we have a worksheet reference, then we're playing with a 3D reference
|
||||
if ($matches[2] == '') {
|
||||
// Otherwise, we 'inherit' the worksheet reference from the start cell reference
|
||||
@@ -3490,32 +3673,39 @@ class Calculation
|
||||
}
|
||||
}
|
||||
|
||||
$output[] = ['type' => 'Cell Reference', 'value' => $val, 'reference' => $val];
|
||||
$outputItem = $stack->getStackItem('Cell Reference', $val, $val, $currentCondition, $currentOnlyIf, $currentOnlyIfNot);
|
||||
|
||||
$output[] = $outputItem;
|
||||
} else { // it's a variable, constant, string, number or boolean
|
||||
// If the last entry on the stack was a : operator, then we may have a row or column range reference
|
||||
$testPrevOp = $stack->last(1);
|
||||
if ($testPrevOp['value'] == ':') {
|
||||
if ($testPrevOp !== null && $testPrevOp['value'] === ':') {
|
||||
$startRowColRef = $output[count($output) - 1]['value'];
|
||||
list($rangeWS1, $startRowColRef) = Worksheet::extractSheetTitle($startRowColRef, true);
|
||||
[$rangeWS1, $startRowColRef] = Worksheet::extractSheetTitle($startRowColRef, true);
|
||||
$rangeSheetRef = $rangeWS1;
|
||||
if ($rangeWS1 != '') {
|
||||
$rangeWS1 .= '!';
|
||||
}
|
||||
list($rangeWS2, $val) = Worksheet::extractSheetTitle($val, true);
|
||||
[$rangeWS2, $val] = Worksheet::extractSheetTitle($val, true);
|
||||
if ($rangeWS2 != '') {
|
||||
$rangeWS2 .= '!';
|
||||
} else {
|
||||
$rangeWS2 = $rangeWS1;
|
||||
}
|
||||
$refSheet = $pCellParent;
|
||||
if ($pCellParent !== null && $rangeSheetRef !== $pCellParent->getTitle()) {
|
||||
$refSheet = $pCellParent->getParent()->getSheetByName($rangeSheetRef);
|
||||
}
|
||||
if ((is_int($startRowColRef)) && (ctype_digit($val)) &&
|
||||
($startRowColRef <= 1048576) && ($val <= 1048576)) {
|
||||
// Row range
|
||||
$endRowColRef = ($pCellParent !== null) ? $pCellParent->getHighestColumn() : 'XFD'; // Max 16,384 columns for Excel2007
|
||||
$endRowColRef = ($refSheet !== null) ? $refSheet->getHighestColumn() : 'XFD'; // Max 16,384 columns for Excel2007
|
||||
$output[count($output) - 1]['value'] = $rangeWS1 . 'A' . $startRowColRef;
|
||||
$val = $rangeWS2 . $endRowColRef . $val;
|
||||
} elseif ((ctype_alpha($startRowColRef)) && (ctype_alpha($val)) &&
|
||||
(strlen($startRowColRef) <= 3) && (strlen($val) <= 3)) {
|
||||
// Column range
|
||||
$endRowColRef = ($pCellParent !== null) ? $pCellParent->getHighestRow() : 1048576; // Max 1,048,576 rows for Excel2007
|
||||
$endRowColRef = ($refSheet !== null) ? $refSheet->getHighestRow() : 1048576; // Max 1,048,576 rows for Excel2007
|
||||
$output[count($output) - 1]['value'] = $rangeWS1 . strtoupper($startRowColRef) . '1';
|
||||
$val = $rangeWS2 . $val . $endRowColRef;
|
||||
}
|
||||
@@ -3537,7 +3727,7 @@ class Calculation
|
||||
} elseif (($localeConstant = array_search(trim(strtoupper($val)), self::$localeBoolean)) !== false) {
|
||||
$val = self::$excelConstants[$localeConstant];
|
||||
}
|
||||
$details = ['type' => 'Value', 'value' => $val, 'reference' => null];
|
||||
$details = $stack->getStackItem('Value', $val, null, $currentCondition, $currentOnlyIf, $currentOnlyIfNot);
|
||||
if ($localeConstant) {
|
||||
$details['localeValue'] = $localeConstant;
|
||||
}
|
||||
@@ -3557,7 +3747,7 @@ class Calculation
|
||||
} elseif (isset(self::$operators[$opCharacter]) && !$expectingOperator) {
|
||||
return $this->raiseFormulaError("Formula Error: Unexpected operator '$opCharacter'");
|
||||
} else { // I don't even want to know what you did to get here
|
||||
return $this->raiseFormulaError('Formula Error: An unexpected error occured');
|
||||
return $this->raiseFormulaError('Formula Error: An unexpected error occurred');
|
||||
}
|
||||
// Test for end of formula string
|
||||
if ($index == strlen($formula)) {
|
||||
@@ -3640,9 +3830,85 @@ class Calculation
|
||||
$pCellParent = ($pCell !== null) ? $pCell->getParent() : null;
|
||||
$stack = new Stack();
|
||||
|
||||
// Stores branches that have been pruned
|
||||
$fakedForBranchPruning = [];
|
||||
// help us to know when pruning ['branchTestId' => true/false]
|
||||
$branchStore = [];
|
||||
|
||||
// Loop through each token in turn
|
||||
foreach ($tokens as $tokenData) {
|
||||
$token = $tokenData['value'];
|
||||
|
||||
// Branch pruning: skip useless resolutions
|
||||
$storeKey = $tokenData['storeKey'] ?? null;
|
||||
if ($this->branchPruningEnabled && isset($tokenData['onlyIf'])) {
|
||||
$onlyIfStoreKey = $tokenData['onlyIf'];
|
||||
$storeValue = $branchStore[$onlyIfStoreKey] ?? null;
|
||||
$storeValueAsBool = ($storeValue === null) ?
|
||||
true : (bool) Functions::flattenSingleValue($storeValue);
|
||||
if (is_array($storeValue)) {
|
||||
$wrappedItem = end($storeValue);
|
||||
$storeValue = end($wrappedItem);
|
||||
}
|
||||
|
||||
if (isset($storeValue)
|
||||
&& (
|
||||
!$storeValueAsBool
|
||||
|| Functions::isError($storeValue)
|
||||
|| ($storeValue === 'Pruned branch')
|
||||
)
|
||||
) {
|
||||
// If branching value is not true, we don't need to compute
|
||||
if (!isset($fakedForBranchPruning['onlyIf-' . $onlyIfStoreKey])) {
|
||||
$stack->push('Value', 'Pruned branch (only if ' . $onlyIfStoreKey . ') ' . $token);
|
||||
$fakedForBranchPruning['onlyIf-' . $onlyIfStoreKey] = true;
|
||||
}
|
||||
|
||||
if (isset($storeKey)) {
|
||||
// We are processing an if condition
|
||||
// We cascade the pruning to the depending branches
|
||||
$branchStore[$storeKey] = 'Pruned branch';
|
||||
$fakedForBranchPruning['onlyIfNot-' . $storeKey] = true;
|
||||
$fakedForBranchPruning['onlyIf-' . $storeKey] = true;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->branchPruningEnabled && isset($tokenData['onlyIfNot'])) {
|
||||
$onlyIfNotStoreKey = $tokenData['onlyIfNot'];
|
||||
$storeValue = $branchStore[$onlyIfNotStoreKey] ?? null;
|
||||
$storeValueAsBool = ($storeValue === null) ?
|
||||
true : (bool) Functions::flattenSingleValue($storeValue);
|
||||
if (is_array($storeValue)) {
|
||||
$wrappedItem = end($storeValue);
|
||||
$storeValue = end($wrappedItem);
|
||||
}
|
||||
if (isset($storeValue)
|
||||
&& (
|
||||
$storeValueAsBool
|
||||
|| Functions::isError($storeValue)
|
||||
|| ($storeValue === 'Pruned branch'))
|
||||
) {
|
||||
// If branching value is true, we don't need to compute
|
||||
if (!isset($fakedForBranchPruning['onlyIfNot-' . $onlyIfNotStoreKey])) {
|
||||
$stack->push('Value', 'Pruned branch (only if not ' . $onlyIfNotStoreKey . ') ' . $token);
|
||||
$fakedForBranchPruning['onlyIfNot-' . $onlyIfNotStoreKey] = true;
|
||||
}
|
||||
|
||||
if (isset($storeKey)) {
|
||||
// We are processing an if condition
|
||||
// We cascade the pruning to the depending branches
|
||||
$branchStore[$storeKey] = 'Pruned branch';
|
||||
$fakedForBranchPruning['onlyIfNot-' . $storeKey] = true;
|
||||
$fakedForBranchPruning['onlyIf-' . $storeKey] = true;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// if the token is a binary operator, pop the top two values off the stack, do the operation, and push the result back on the stack
|
||||
if (isset(self::$binaryOperators[$token])) {
|
||||
// We must have two operands, error if we don't
|
||||
@@ -3672,18 +3938,21 @@ class Calculation
|
||||
case '<=': // Less than or Equal to
|
||||
case '=': // Equality
|
||||
case '<>': // Inequality
|
||||
$this->executeBinaryComparisonOperation($cellID, $operand1, $operand2, $token, $stack);
|
||||
$result = $this->executeBinaryComparisonOperation($cellID, $operand1, $operand2, $token, $stack);
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = $result;
|
||||
}
|
||||
|
||||
break;
|
||||
// Binary Operators
|
||||
case ':': // Range
|
||||
if (strpos($operand1Data['reference'], '!') !== false) {
|
||||
list($sheet1, $operand1Data['reference']) = Worksheet::extractSheetTitle($operand1Data['reference'], true);
|
||||
[$sheet1, $operand1Data['reference']] = Worksheet::extractSheetTitle($operand1Data['reference'], true);
|
||||
} else {
|
||||
$sheet1 = ($pCellParent !== null) ? $pCellWorksheet->getTitle() : '';
|
||||
}
|
||||
|
||||
list($sheet2, $operand2Data['reference']) = Worksheet::extractSheetTitle($operand2Data['reference'], true);
|
||||
[$sheet2, $operand2Data['reference']] = Worksheet::extractSheetTitle($operand2Data['reference'], true);
|
||||
if (empty($sheet2)) {
|
||||
$sheet2 = $sheet1;
|
||||
}
|
||||
@@ -3728,23 +3997,38 @@ class Calculation
|
||||
|
||||
break;
|
||||
case '+': // Addition
|
||||
$this->executeNumericBinaryOperation($operand1, $operand2, $token, 'plusEquals', $stack);
|
||||
$result = $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'plusEquals', $stack);
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = $result;
|
||||
}
|
||||
|
||||
break;
|
||||
case '-': // Subtraction
|
||||
$this->executeNumericBinaryOperation($operand1, $operand2, $token, 'minusEquals', $stack);
|
||||
$result = $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'minusEquals', $stack);
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = $result;
|
||||
}
|
||||
|
||||
break;
|
||||
case '*': // Multiplication
|
||||
$this->executeNumericBinaryOperation($operand1, $operand2, $token, 'arrayTimesEquals', $stack);
|
||||
$result = $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'arrayTimesEquals', $stack);
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = $result;
|
||||
}
|
||||
|
||||
break;
|
||||
case '/': // Division
|
||||
$this->executeNumericBinaryOperation($operand1, $operand2, $token, 'arrayRightDivide', $stack);
|
||||
$result = $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'arrayRightDivide', $stack);
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = $result;
|
||||
}
|
||||
|
||||
break;
|
||||
case '^': // Exponential
|
||||
$this->executeNumericBinaryOperation($operand1, $operand2, $token, 'power', $stack);
|
||||
$result = $this->executeNumericBinaryOperation($operand1, $operand2, $token, 'power', $stack);
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = $result;
|
||||
}
|
||||
|
||||
break;
|
||||
case '&': // Concatenation
|
||||
@@ -3777,6 +4061,10 @@ class Calculation
|
||||
$this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($result));
|
||||
$stack->push('Value', $result);
|
||||
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = $result;
|
||||
}
|
||||
|
||||
break;
|
||||
case '|': // Intersect
|
||||
$rowIntersect = array_intersect_key($operand1, $operand2);
|
||||
@@ -3821,6 +4109,9 @@ class Calculation
|
||||
}
|
||||
$this->debugLog->writeDebugLog('Evaluation Result is ', $this->showTypeDetails($result));
|
||||
$stack->push('Value', $result);
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = $result;
|
||||
}
|
||||
} else {
|
||||
$this->executeNumericBinaryOperation($multiplier, $arg, '*', 'arrayTimesEquals', $stack);
|
||||
}
|
||||
@@ -3894,9 +4185,16 @@ class Calculation
|
||||
}
|
||||
}
|
||||
$stack->push('Value', $cellValue, $cellRef);
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = $cellValue;
|
||||
}
|
||||
|
||||
// if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on
|
||||
// if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on
|
||||
} elseif (preg_match('/^' . self::CALCULATION_REGEXP_FUNCTION . '$/i', $token, $matches)) {
|
||||
if ($pCellParent) {
|
||||
$pCell->attach($pCellParent);
|
||||
}
|
||||
|
||||
$functionName = $matches[1];
|
||||
$argCount = $stack->pop();
|
||||
$argCount = $argCount['value'];
|
||||
@@ -3939,6 +4237,7 @@ class Calculation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse the order of the arguments
|
||||
krsort($args);
|
||||
|
||||
@@ -3963,22 +4262,32 @@ class Calculation
|
||||
}
|
||||
unset($arg);
|
||||
}
|
||||
|
||||
$result = call_user_func_array($functionCall, $args);
|
||||
|
||||
if ($functionName != 'MKMATRIX') {
|
||||
$this->debugLog->writeDebugLog('Evaluation Result for ', self::localeFunc($functionName), '() function call is ', $this->showTypeDetails($result));
|
||||
}
|
||||
$stack->push('Value', self::wrapResult($result));
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = $result;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// if the token is a number, boolean, string or an Excel error, push it onto the stack
|
||||
if (isset(self::$excelConstants[strtoupper($token)])) {
|
||||
$excelConstant = strtoupper($token);
|
||||
$stack->push('Constant Value', self::$excelConstants[$excelConstant]);
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = self::$excelConstants[$excelConstant];
|
||||
}
|
||||
$this->debugLog->writeDebugLog('Evaluating Constant ', $excelConstant, ' as ', $this->showTypeDetails(self::$excelConstants[$excelConstant]));
|
||||
} elseif ((is_numeric($token)) || ($token === null) || (is_bool($token)) || ($token == '') || ($token[0] == '"') || ($token[0] == '#')) {
|
||||
$stack->push('Value', $token);
|
||||
// if the token is a named range, push the named range name onto the stack
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = $token;
|
||||
}
|
||||
// if the token is a named range, push the named range name onto the stack
|
||||
} elseif (preg_match('/^' . self::CALCULATION_REGEXP_NAMEDRANGE . '$/i', $token, $matches)) {
|
||||
$namedRange = $matches[6];
|
||||
$this->debugLog->writeDebugLog('Evaluating Named Range ', $namedRange);
|
||||
@@ -3987,6 +4296,9 @@ class Calculation
|
||||
$pCell->attach($pCellParent);
|
||||
$this->debugLog->writeDebugLog('Evaluation Result for named range ', $namedRange, ' is ', $this->showTypeDetails($cellValue));
|
||||
$stack->push('Named Range', $cellValue, $namedRange);
|
||||
if (isset($storeKey)) {
|
||||
$branchStore[$storeKey] = $cellValue;
|
||||
}
|
||||
} else {
|
||||
return $this->raiseFormulaError("undefined variable '$token'");
|
||||
}
|
||||
@@ -4048,7 +4360,7 @@ class Calculation
|
||||
* @param Stack $stack
|
||||
* @param bool $recursingArrays
|
||||
*
|
||||
* @return bool
|
||||
* @return mixed
|
||||
*/
|
||||
private function executeBinaryComparisonOperation($cellID, $operand1, $operand2, $operation, Stack &$stack, $recursingArrays = false)
|
||||
{
|
||||
@@ -4085,7 +4397,7 @@ class Calculation
|
||||
// And push the result onto the stack
|
||||
$stack->push('Array', $result);
|
||||
|
||||
return true;
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Simple validate the two operands if they are string values
|
||||
@@ -4175,7 +4487,7 @@ class Calculation
|
||||
// And push the result onto the stack
|
||||
$stack->push('Value', $result);
|
||||
|
||||
return true;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4201,7 +4513,7 @@ class Calculation
|
||||
* @param string $matrixFunction
|
||||
* @param mixed $stack
|
||||
*
|
||||
* @return bool
|
||||
* @return bool|mixed
|
||||
*/
|
||||
private function executeNumericBinaryOperation($operand1, $operand2, $operation, $matrixFunction, &$stack)
|
||||
{
|
||||
@@ -4279,7 +4591,7 @@ class Calculation
|
||||
// And push the result onto the stack
|
||||
$stack->push('Value', $result);
|
||||
|
||||
return true;
|
||||
return $result;
|
||||
}
|
||||
|
||||
// trigger an error, but nicely, if need be
|
||||
@@ -4312,7 +4624,7 @@ class Calculation
|
||||
if ($pSheet !== null) {
|
||||
$pSheetName = $pSheet->getTitle();
|
||||
if (strpos($pRange, '!') !== false) {
|
||||
list($pSheetName, $pRange) = Worksheet::extractSheetTitle($pRange, true);
|
||||
[$pSheetName, $pRange] = Worksheet::extractSheetTitle($pRange, true);
|
||||
$pSheet = $this->spreadsheet->getSheetByName($pSheetName);
|
||||
}
|
||||
|
||||
@@ -4365,7 +4677,7 @@ class Calculation
|
||||
if ($pSheet !== null) {
|
||||
$pSheetName = $pSheet->getTitle();
|
||||
if (strpos($pRange, '!') !== false) {
|
||||
list($pSheetName, $pRange) = Worksheet::extractSheetTitle($pRange, true);
|
||||
[$pSheetName, $pRange] = Worksheet::extractSheetTitle($pRange, true);
|
||||
$pSheet = $this->spreadsheet->getSheetByName($pSheetName);
|
||||
}
|
||||
|
||||
@@ -4389,7 +4701,7 @@ class Calculation
|
||||
$aReferences = Coordinate::extractAllCellReferencesInRange($pRange);
|
||||
if (!isset($aReferences[1])) {
|
||||
// Single cell (or single column or row) in range
|
||||
list($currentCol, $currentRow) = Coordinate::coordinateFromString($aReferences[0]);
|
||||
[$currentCol, $currentRow] = Coordinate::coordinateFromString($aReferences[0]);
|
||||
if ($pSheet->cellExists($aReferences[0])) {
|
||||
$returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog);
|
||||
} else {
|
||||
@@ -4399,7 +4711,7 @@ class Calculation
|
||||
// Extract cell data for all cells in the range
|
||||
foreach ($aReferences as $reference) {
|
||||
// Extract range
|
||||
list($currentCol, $currentRow) = Coordinate::coordinateFromString($reference);
|
||||
[$currentCol, $currentRow] = Coordinate::coordinateFromString($reference);
|
||||
if ($pSheet->cellExists($reference)) {
|
||||
$returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog);
|
||||
} else {
|
||||
@@ -4483,4 +4795,26 @@ class Calculation
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
private function getUnusedBranchStoreKey()
|
||||
{
|
||||
$storeKeyValue = 'storeKey-' . $this->branchStoreKeyCounter;
|
||||
++$this->branchStoreKeyCounter;
|
||||
|
||||
return $storeKeyValue;
|
||||
}
|
||||
|
||||
private function getTokensAsString($tokens)
|
||||
{
|
||||
$tokensStr = array_map(function ($token) {
|
||||
$value = $token['value'] ?? 'no value';
|
||||
while (is_array($value)) {
|
||||
$value = array_pop($value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}, $tokens);
|
||||
|
||||
return '[ ' . implode(' | ', $tokensStr) . ' ]';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ class Database
|
||||
* the column label in which you specify a condition for the
|
||||
* column.
|
||||
*
|
||||
* @return float
|
||||
* @return float|string
|
||||
*/
|
||||
public static function DAVERAGE($database, $field, $criteria)
|
||||
{
|
||||
@@ -452,7 +452,7 @@ class Database
|
||||
* the column label in which you specify a condition for the
|
||||
* column.
|
||||
*
|
||||
* @return float
|
||||
* @return float|string
|
||||
*/
|
||||
public static function DSTDEV($database, $field, $criteria)
|
||||
{
|
||||
@@ -493,7 +493,7 @@ class Database
|
||||
* the column label in which you specify a condition for the
|
||||
* column.
|
||||
*
|
||||
* @return float
|
||||
* @return float|string
|
||||
*/
|
||||
public static function DSTDEVP($database, $field, $criteria)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ class DateTime
|
||||
*/
|
||||
public static function isLeapYear($year)
|
||||
{
|
||||
return (($year % 4) == 0) && (($year % 100) != 0) || (($year % 400) == 0);
|
||||
return (($year % 4) === 0) && (($year % 100) !== 0) || (($year % 400) === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,11 +156,11 @@ class DateTime
|
||||
$retValue = (float) Date::PHPToExcel(time());
|
||||
|
||||
break;
|
||||
case Functions::RETURNDATE_PHP_NUMERIC:
|
||||
case Functions::RETURNDATE_UNIX_TIMESTAMP:
|
||||
$retValue = (int) time();
|
||||
|
||||
break;
|
||||
case Functions::RETURNDATE_PHP_OBJECT:
|
||||
case Functions::RETURNDATE_PHP_DATETIME_OBJECT:
|
||||
$retValue = new \DateTime();
|
||||
|
||||
break;
|
||||
@@ -200,11 +200,11 @@ class DateTime
|
||||
$retValue = (float) $excelDateTime;
|
||||
|
||||
break;
|
||||
case Functions::RETURNDATE_PHP_NUMERIC:
|
||||
case Functions::RETURNDATE_UNIX_TIMESTAMP:
|
||||
$retValue = (int) Date::excelToTimestamp($excelDateTime);
|
||||
|
||||
break;
|
||||
case Functions::RETURNDATE_PHP_OBJECT:
|
||||
case Functions::RETURNDATE_PHP_DATETIME_OBJECT:
|
||||
$retValue = Date::excelToDateTimeObject($excelDateTime);
|
||||
|
||||
break;
|
||||
@@ -325,9 +325,9 @@ class DateTime
|
||||
switch (Functions::getReturnDateType()) {
|
||||
case Functions::RETURNDATE_EXCEL:
|
||||
return (float) $excelDateValue;
|
||||
case Functions::RETURNDATE_PHP_NUMERIC:
|
||||
case Functions::RETURNDATE_UNIX_TIMESTAMP:
|
||||
return (int) Date::excelToTimestamp($excelDateValue);
|
||||
case Functions::RETURNDATE_PHP_OBJECT:
|
||||
case Functions::RETURNDATE_PHP_DATETIME_OBJECT:
|
||||
return Date::excelToDateTimeObject($excelDateValue);
|
||||
}
|
||||
}
|
||||
@@ -420,9 +420,9 @@ class DateTime
|
||||
}
|
||||
|
||||
return (float) Date::formattedPHPToExcel($calendar, 1, $date, $hour, $minute, $second);
|
||||
case Functions::RETURNDATE_PHP_NUMERIC:
|
||||
case Functions::RETURNDATE_UNIX_TIMESTAMP:
|
||||
return (int) Date::excelToTimestamp(Date::formattedPHPToExcel(1970, 1, 1, $hour, $minute, $second)); // -2147468400; // -2147472000 + 3600
|
||||
case Functions::RETURNDATE_PHP_OBJECT:
|
||||
case Functions::RETURNDATE_PHP_DATETIME_OBJECT:
|
||||
$dayAdjust = 0;
|
||||
if ($hour < 0) {
|
||||
$dayAdjust = floor($hour / 24);
|
||||
@@ -472,7 +472,6 @@ class DateTime
|
||||
*/
|
||||
public static function DATEVALUE($dateValue = 1)
|
||||
{
|
||||
$dateValueOrig = $dateValue;
|
||||
$dateValue = trim(Functions::flattenSingleValue($dateValue), '"');
|
||||
// Strip any ordinals because they're allowed in Excel (English only)
|
||||
$dateValue = preg_replace('/(\d)(st|nd|rd|th)([ -\/])/Ui', '$1$3', $dateValue);
|
||||
@@ -492,7 +491,7 @@ class DateTime
|
||||
$yearFound = true;
|
||||
}
|
||||
}
|
||||
if ((count($t1) == 1) && (strpos($t, ':') != false)) {
|
||||
if ((count($t1) == 1) && (strpos($t, ':') !== false)) {
|
||||
// We've been fed a time value without any date
|
||||
return 0.0;
|
||||
} elseif (count($t1) == 2) {
|
||||
@@ -569,9 +568,9 @@ class DateTime
|
||||
switch (Functions::getReturnDateType()) {
|
||||
case Functions::RETURNDATE_EXCEL:
|
||||
return (float) $excelDateValue;
|
||||
case Functions::RETURNDATE_PHP_NUMERIC:
|
||||
case Functions::RETURNDATE_UNIX_TIMESTAMP:
|
||||
return (int) Date::excelToTimestamp($excelDateValue);
|
||||
case Functions::RETURNDATE_PHP_OBJECT:
|
||||
case Functions::RETURNDATE_PHP_DATETIME_OBJECT:
|
||||
return new \DateTime($PHPDateArray['year'] . '-' . $PHPDateArray['month'] . '-' . $PHPDateArray['day'] . ' 00:00:00');
|
||||
}
|
||||
}
|
||||
@@ -631,9 +630,9 @@ class DateTime
|
||||
switch (Functions::getReturnDateType()) {
|
||||
case Functions::RETURNDATE_EXCEL:
|
||||
return (float) $excelDateValue;
|
||||
case Functions::RETURNDATE_PHP_NUMERIC:
|
||||
case Functions::RETURNDATE_UNIX_TIMESTAMP:
|
||||
return (int) $phpDateValue = Date::excelToTimestamp($excelDateValue + 25569) - 3600;
|
||||
case Functions::RETURNDATE_PHP_OBJECT:
|
||||
case Functions::RETURNDATE_PHP_DATETIME_OBJECT:
|
||||
return new \DateTime('1900-01-01 ' . $PHPDateArray['hour'] . ':' . $PHPDateArray['minute'] . ':' . $PHPDateArray['second']);
|
||||
}
|
||||
}
|
||||
@@ -683,7 +682,6 @@ class DateTime
|
||||
$endMonths = $PHPEndDateObject->format('n');
|
||||
$endYears = $PHPEndDateObject->format('Y');
|
||||
|
||||
$retVal = Functions::NAN();
|
||||
switch ($unit) {
|
||||
case 'D':
|
||||
$retVal = (int) $difference;
|
||||
@@ -880,6 +878,8 @@ class DateTime
|
||||
*
|
||||
* Excel Function:
|
||||
* YEARFRAC(startDate,endDate[,method])
|
||||
* See https://lists.oasis-open.org/archives/office-formula/200806/msg00039.html
|
||||
* for description of algorithm used in Excel
|
||||
*
|
||||
* @category Date/Time Functions
|
||||
*
|
||||
@@ -894,7 +894,7 @@ class DateTime
|
||||
* 3 Actual/365
|
||||
* 4 European 30/360
|
||||
*
|
||||
* @return float fraction of the year
|
||||
* @return float|string fraction of the year, or a string containing an error
|
||||
*/
|
||||
public static function YEARFRAC($startDate = 0, $endDate = 0, $method = 0)
|
||||
{
|
||||
@@ -908,6 +908,11 @@ class DateTime
|
||||
if (is_string($endDate = self::getDateValue($endDate))) {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
if ($startDate > $endDate) {
|
||||
$temp = $startDate;
|
||||
$startDate = $endDate;
|
||||
$endDate = $temp;
|
||||
}
|
||||
|
||||
if (((is_numeric($method)) && (!is_string($method))) || ($method == '')) {
|
||||
switch ($method) {
|
||||
@@ -918,46 +923,43 @@ class DateTime
|
||||
$startYear = self::YEAR($startDate);
|
||||
$endYear = self::YEAR($endDate);
|
||||
$years = $endYear - $startYear + 1;
|
||||
$leapDays = 0;
|
||||
$startMonth = self::MONTHOFYEAR($startDate);
|
||||
$startDay = self::DAYOFMONTH($startDate);
|
||||
$endMonth = self::MONTHOFYEAR($endDate);
|
||||
$endDay = self::DAYOFMONTH($endDate);
|
||||
$startMonthDay = 100 * $startMonth + $startDay;
|
||||
$endMonthDay = 100 * $endMonth + $endDay;
|
||||
if ($years == 1) {
|
||||
if (self::isLeapYear($endYear)) {
|
||||
$startMonth = self::MONTHOFYEAR($startDate);
|
||||
$endMonth = self::MONTHOFYEAR($endDate);
|
||||
$endDay = self::DAYOFMONTH($endDate);
|
||||
if (($startMonth < 3) ||
|
||||
(($endMonth * 100 + $endDay) >= (2 * 100 + 29))) {
|
||||
$leapDays += 1;
|
||||
$tmpCalcAnnualBasis = 366;
|
||||
} else {
|
||||
$tmpCalcAnnualBasis = 365;
|
||||
}
|
||||
} elseif ($years == 2 && $startMonthDay >= $endMonthDay) {
|
||||
if (self::isLeapYear($startYear)) {
|
||||
if ($startMonthDay <= 229) {
|
||||
$tmpCalcAnnualBasis = 366;
|
||||
} else {
|
||||
$tmpCalcAnnualBasis = 365;
|
||||
}
|
||||
} elseif (self::isLeapYear($endYear)) {
|
||||
if ($endMonthDay >= 229) {
|
||||
$tmpCalcAnnualBasis = 366;
|
||||
} else {
|
||||
$tmpCalcAnnualBasis = 365;
|
||||
}
|
||||
} else {
|
||||
$tmpCalcAnnualBasis = 365;
|
||||
}
|
||||
} else {
|
||||
$tmpCalcAnnualBasis = 0;
|
||||
for ($year = $startYear; $year <= $endYear; ++$year) {
|
||||
if ($year == $startYear) {
|
||||
$startMonth = self::MONTHOFYEAR($startDate);
|
||||
$startDay = self::DAYOFMONTH($startDate);
|
||||
if ($startMonth < 3) {
|
||||
$leapDays += (self::isLeapYear($year)) ? 1 : 0;
|
||||
}
|
||||
} elseif ($year == $endYear) {
|
||||
$endMonth = self::MONTHOFYEAR($endDate);
|
||||
$endDay = self::DAYOFMONTH($endDate);
|
||||
if (($endMonth * 100 + $endDay) >= (2 * 100 + 29)) {
|
||||
$leapDays += (self::isLeapYear($year)) ? 1 : 0;
|
||||
}
|
||||
} else {
|
||||
$leapDays += (self::isLeapYear($year)) ? 1 : 0;
|
||||
}
|
||||
$tmpCalcAnnualBasis += self::isLeapYear($year) ? 366 : 365;
|
||||
}
|
||||
if ($years == 2) {
|
||||
if (($leapDays == 0) && (self::isLeapYear($startYear)) && ($days > 365)) {
|
||||
$leapDays = 1;
|
||||
} elseif ($days < 366) {
|
||||
$years = 1;
|
||||
}
|
||||
}
|
||||
$leapDays /= $years;
|
||||
$tmpCalcAnnualBasis /= $years;
|
||||
}
|
||||
|
||||
return $days / (365 + $leapDays);
|
||||
return $days / $tmpCalcAnnualBasis;
|
||||
case 2:
|
||||
return self::DATEDIF($startDate, $endDate) / 360;
|
||||
case 3:
|
||||
@@ -1154,9 +1156,9 @@ class DateTime
|
||||
switch (Functions::getReturnDateType()) {
|
||||
case Functions::RETURNDATE_EXCEL:
|
||||
return (float) $endDate;
|
||||
case Functions::RETURNDATE_PHP_NUMERIC:
|
||||
case Functions::RETURNDATE_UNIX_TIMESTAMP:
|
||||
return (int) Date::excelToTimestamp($endDate);
|
||||
case Functions::RETURNDATE_PHP_OBJECT:
|
||||
case Functions::RETURNDATE_PHP_DATETIME_OBJECT:
|
||||
return Date::excelToDateTimeObject($endDate);
|
||||
}
|
||||
}
|
||||
@@ -1239,7 +1241,7 @@ class DateTime
|
||||
|
||||
// Execute function
|
||||
$PHPDateObject = Date::excelToDateTimeObject($dateValue);
|
||||
$DoW = $PHPDateObject->format('w');
|
||||
$DoW = (int) $PHPDateObject->format('w');
|
||||
|
||||
$firstDay = 1;
|
||||
switch ($style) {
|
||||
@@ -1248,13 +1250,13 @@ class DateTime
|
||||
|
||||
break;
|
||||
case 2:
|
||||
if ($DoW == 0) {
|
||||
if ($DoW === 0) {
|
||||
$DoW = 7;
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
if ($DoW == 0) {
|
||||
if ($DoW === 0) {
|
||||
$DoW = 7;
|
||||
}
|
||||
$firstDay = 0;
|
||||
@@ -1272,9 +1274,39 @@ class DateTime
|
||||
}
|
||||
}
|
||||
|
||||
return (int) $DoW;
|
||||
return $DoW;
|
||||
}
|
||||
|
||||
const STARTWEEK_SUNDAY = 1;
|
||||
const STARTWEEK_MONDAY = 2;
|
||||
const STARTWEEK_MONDAY_ALT = 11;
|
||||
const STARTWEEK_TUESDAY = 12;
|
||||
const STARTWEEK_WEDNESDAY = 13;
|
||||
const STARTWEEK_THURSDAY = 14;
|
||||
const STARTWEEK_FRIDAY = 15;
|
||||
const STARTWEEK_SATURDAY = 16;
|
||||
const STARTWEEK_SUNDAY_ALT = 17;
|
||||
const DOW_SUNDAY = 1;
|
||||
const DOW_MONDAY = 2;
|
||||
const DOW_TUESDAY = 3;
|
||||
const DOW_WEDNESDAY = 4;
|
||||
const DOW_THURSDAY = 5;
|
||||
const DOW_FRIDAY = 6;
|
||||
const DOW_SATURDAY = 7;
|
||||
const STARTWEEK_MONDAY_ISO = 21;
|
||||
const METHODARR = [
|
||||
self::STARTWEEK_SUNDAY => self::DOW_SUNDAY,
|
||||
self::DOW_MONDAY,
|
||||
self::STARTWEEK_MONDAY_ALT => self::DOW_MONDAY,
|
||||
self::DOW_TUESDAY,
|
||||
self::DOW_WEDNESDAY,
|
||||
self::DOW_THURSDAY,
|
||||
self::DOW_FRIDAY,
|
||||
self::DOW_SATURDAY,
|
||||
self::DOW_SUNDAY,
|
||||
self::STARTWEEK_MONDAY_ISO => self::STARTWEEK_MONDAY_ISO,
|
||||
];
|
||||
|
||||
/**
|
||||
* WEEKNUM.
|
||||
*
|
||||
@@ -1293,41 +1325,51 @@ class DateTime
|
||||
* @param int $method Week begins on Sunday or Monday
|
||||
* 1 or omitted Week begins on Sunday.
|
||||
* 2 Week begins on Monday.
|
||||
* 11 Week begins on Monday.
|
||||
* 12 Week begins on Tuesday.
|
||||
* 13 Week begins on Wednesday.
|
||||
* 14 Week begins on Thursday.
|
||||
* 15 Week begins on Friday.
|
||||
* 16 Week begins on Saturday.
|
||||
* 17 Week begins on Sunday.
|
||||
* 21 ISO (Jan. 4 is week 1, begins on Monday).
|
||||
*
|
||||
* @return int|string Week Number
|
||||
*/
|
||||
public static function WEEKNUM($dateValue = 1, $method = 1)
|
||||
public static function WEEKNUM($dateValue = 1, $method = self::STARTWEEK_SUNDAY)
|
||||
{
|
||||
$dateValue = Functions::flattenSingleValue($dateValue);
|
||||
$method = Functions::flattenSingleValue($method);
|
||||
|
||||
if (!is_numeric($method)) {
|
||||
return Functions::VALUE();
|
||||
} elseif (($method < 1) || ($method > 2)) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
$method = floor($method);
|
||||
$method = (int) $method;
|
||||
if (!array_key_exists($method, self::METHODARR)) {
|
||||
return Functions::NaN();
|
||||
}
|
||||
$method = self::METHODARR[$method];
|
||||
|
||||
if ($dateValue === null) {
|
||||
$dateValue = 1;
|
||||
} elseif (is_string($dateValue = self::getDateValue($dateValue))) {
|
||||
$dateValue = self::getDateValue($dateValue);
|
||||
if (is_string($dateValue)) {
|
||||
return Functions::VALUE();
|
||||
} elseif ($dateValue < 0.0) {
|
||||
}
|
||||
if ($dateValue < 0.0) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
// Execute function
|
||||
$PHPDateObject = Date::excelToDateTimeObject($dateValue);
|
||||
if ($method == self::STARTWEEK_MONDAY_ISO) {
|
||||
return (int) $PHPDateObject->format('W');
|
||||
}
|
||||
$dayOfYear = $PHPDateObject->format('z');
|
||||
$PHPDateObject->modify('-' . $dayOfYear . ' days');
|
||||
$firstDayOfFirstWeek = $PHPDateObject->format('w');
|
||||
$daysInFirstWeek = (6 - $firstDayOfFirstWeek + $method) % 7;
|
||||
$interval = $dayOfYear - $daysInFirstWeek;
|
||||
$weekOfYear = floor($interval / 7) + 1;
|
||||
|
||||
if ($daysInFirstWeek) {
|
||||
++$weekOfYear;
|
||||
}
|
||||
$daysInFirstWeek += 7 * !$daysInFirstWeek;
|
||||
$endFirstWeek = $daysInFirstWeek - 1;
|
||||
$weekOfYear = floor(($dayOfYear - $endFirstWeek + 13) / 7);
|
||||
|
||||
return (int) $weekOfYear;
|
||||
}
|
||||
@@ -1591,9 +1633,9 @@ class DateTime
|
||||
switch (Functions::getReturnDateType()) {
|
||||
case Functions::RETURNDATE_EXCEL:
|
||||
return (float) Date::PHPToExcel($PHPDateObject);
|
||||
case Functions::RETURNDATE_PHP_NUMERIC:
|
||||
case Functions::RETURNDATE_UNIX_TIMESTAMP:
|
||||
return (int) Date::excelToTimestamp(Date::PHPToExcel($PHPDateObject));
|
||||
case Functions::RETURNDATE_PHP_OBJECT:
|
||||
case Functions::RETURNDATE_PHP_DATETIME_OBJECT:
|
||||
return $PHPDateObject;
|
||||
}
|
||||
}
|
||||
@@ -1640,9 +1682,9 @@ class DateTime
|
||||
switch (Functions::getReturnDateType()) {
|
||||
case Functions::RETURNDATE_EXCEL:
|
||||
return (float) Date::PHPToExcel($PHPDateObject);
|
||||
case Functions::RETURNDATE_PHP_NUMERIC:
|
||||
case Functions::RETURNDATE_UNIX_TIMESTAMP:
|
||||
return (int) Date::excelToTimestamp(Date::PHPToExcel($PHPDateObject));
|
||||
case Functions::RETURNDATE_PHP_OBJECT:
|
||||
case Functions::RETURNDATE_PHP_DATETIME_OBJECT:
|
||||
return $PHPDateObject;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,7 +785,7 @@ class Engineering
|
||||
* If $ord is nonnumeric, BESSELI returns the #VALUE! error value.
|
||||
* If $ord < 0, BESSELI returns the #NUM! error value.
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function BESSELI($x, $ord)
|
||||
{
|
||||
@@ -839,7 +839,7 @@ class Engineering
|
||||
* If $ord is nonnumeric, BESSELJ returns the #VALUE! error value.
|
||||
* If $ord < 0, BESSELJ returns the #NUM! error value.
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function BESSELJ($x, $ord)
|
||||
{
|
||||
@@ -932,7 +932,7 @@ class Engineering
|
||||
* If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
|
||||
* If $ord < 0, BESSELK returns the #NUM! error value.
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function BESSELK($x, $ord)
|
||||
{
|
||||
@@ -1021,7 +1021,7 @@ class Engineering
|
||||
* If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
|
||||
* If $ord < 0, BESSELK returns the #NUM! error value.
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function BESSELY($x, $ord)
|
||||
{
|
||||
@@ -2713,7 +2713,7 @@ class Engineering
|
||||
* @param string $fromUOM the units for value
|
||||
* @param string $toUOM the units for the result
|
||||
*
|
||||
* @return float
|
||||
* @return float|string
|
||||
*/
|
||||
public static function CONVERTUOM($value, $fromUOM, $toUOM)
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ class Financial
|
||||
* 3 365
|
||||
* 4 European 360
|
||||
*
|
||||
* @return int
|
||||
* @return int|string Result, or a string containing an error
|
||||
*/
|
||||
private static function daysPerYear($year, $basis = 0)
|
||||
{
|
||||
@@ -144,7 +144,7 @@ class Financial
|
||||
* 3 Actual/365
|
||||
* 4 European 30/360
|
||||
*
|
||||
* @return float|string
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function ACCRINT($issue, $firstinterest, $settlement, $rate, $par = 1000, $frequency = 1, $basis = 0)
|
||||
{
|
||||
@@ -197,7 +197,7 @@ class Financial
|
||||
* 3 Actual/365
|
||||
* 4 European 30/360
|
||||
*
|
||||
* @return float|string
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function ACCRINTM($issue, $settlement, $rate, $par = 1000, $basis = 0)
|
||||
{
|
||||
@@ -417,7 +417,7 @@ class Financial
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
if (($settlement > $maturity) ||
|
||||
if (($settlement >= $maturity) ||
|
||||
(!self::isValidFrequency($frequency)) ||
|
||||
(($basis < 0) || ($basis > 4))) {
|
||||
return Functions::NAN();
|
||||
@@ -476,7 +476,7 @@ class Financial
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
if (($settlement > $maturity) ||
|
||||
if (($settlement >= $maturity) ||
|
||||
(!self::isValidFrequency($frequency)) ||
|
||||
(($basis < 0) || ($basis > 4))) {
|
||||
return Functions::NAN();
|
||||
@@ -550,7 +550,7 @@ class Financial
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
if (($settlement > $maturity) ||
|
||||
if (($settlement >= $maturity) ||
|
||||
(!self::isValidFrequency($frequency)) ||
|
||||
(($basis < 0) || ($basis > 4))) {
|
||||
return Functions::NAN();
|
||||
@@ -610,7 +610,7 @@ class Financial
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
if (($settlement > $maturity) ||
|
||||
if (($settlement >= $maturity) ||
|
||||
(!self::isValidFrequency($frequency)) ||
|
||||
(($basis < 0) || ($basis > 4))) {
|
||||
return Functions::NAN();
|
||||
@@ -667,26 +667,22 @@ class Financial
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
if (($settlement > $maturity) ||
|
||||
if (($settlement >= $maturity) ||
|
||||
(!self::isValidFrequency($frequency)) ||
|
||||
(($basis < 0) || ($basis > 4))) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
$settlement = self::couponFirstPeriodDate($settlement, $maturity, $frequency, true);
|
||||
$daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis) * 365;
|
||||
$daysPerYear = self::daysPerYear(DateTime::YEAR($settlement), $basis);
|
||||
$daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis) * $daysPerYear;
|
||||
|
||||
switch ($frequency) {
|
||||
case 1: // annual payments
|
||||
return ceil($daysBetweenSettlementAndMaturity / 360);
|
||||
case 2: // half-yearly
|
||||
return ceil($daysBetweenSettlementAndMaturity / 180);
|
||||
case 4: // quarterly
|
||||
return ceil($daysBetweenSettlementAndMaturity / 90);
|
||||
case 6: // bimonthly
|
||||
return ceil($daysBetweenSettlementAndMaturity / 60);
|
||||
case 12: // monthly
|
||||
return ceil($daysBetweenSettlementAndMaturity / 30);
|
||||
return ceil($daysBetweenSettlementAndMaturity / $daysPerYear * $frequency);
|
||||
}
|
||||
|
||||
return Functions::VALUE();
|
||||
@@ -740,7 +736,7 @@ class Financial
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
if (($settlement > $maturity) ||
|
||||
if (($settlement >= $maturity) ||
|
||||
(!self::isValidFrequency($frequency)) ||
|
||||
(($basis < 0) || ($basis > 4))) {
|
||||
return Functions::NAN();
|
||||
@@ -1428,7 +1424,7 @@ class Financial
|
||||
* @param float $finance_rate The interest rate you pay on the money used in the cash flows
|
||||
* @param float $reinvestment_rate The interest rate you receive on the cash flows as you reinvest them
|
||||
*
|
||||
* @return float|string
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function MIRR($values, $finance_rate, $reinvestment_rate)
|
||||
{
|
||||
@@ -1470,7 +1466,7 @@ class Financial
|
||||
* @param float $effect_rate Effective interest rate
|
||||
* @param int $npery Number of compounding payments per year
|
||||
*
|
||||
* @return float|string
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function NOMINAL($effect_rate = 0, $npery = 0)
|
||||
{
|
||||
@@ -1497,7 +1493,7 @@ class Financial
|
||||
* @param float $fv Future Value
|
||||
* @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
|
||||
*
|
||||
* @return float|string
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function NPER($rate = 0, $pmt = 0, $pv = 0, $fv = 0, $type = 0)
|
||||
{
|
||||
@@ -1565,7 +1561,7 @@ class Financial
|
||||
* @param float $pv Present Value
|
||||
* @param float $fv Future Value
|
||||
*
|
||||
* @return float|string
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function PDURATION($rate = 0, $pv = 0, $fv = 0)
|
||||
{
|
||||
@@ -1594,7 +1590,7 @@ class Financial
|
||||
* @param float $fv Future Value
|
||||
* @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function PMT($rate = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0)
|
||||
{
|
||||
@@ -1629,7 +1625,7 @@ class Financial
|
||||
* @param float $fv Future Value
|
||||
* @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function PPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0)
|
||||
{
|
||||
@@ -1713,7 +1709,7 @@ class Financial
|
||||
* 3 Actual/365
|
||||
* 4 European 30/360
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function PRICEDISC($settlement, $maturity, $discount, $redemption, $basis = 0)
|
||||
{
|
||||
@@ -1759,7 +1755,7 @@ class Financial
|
||||
* 3 Actual/365
|
||||
* 4 European 30/360
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function PRICEMAT($settlement, $maturity, $issue, $rate, $yield, $basis = 0)
|
||||
{
|
||||
@@ -1817,7 +1813,7 @@ class Financial
|
||||
* @param float $fv Future Value
|
||||
* @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function PV($rate = 0, $nper = 0, $pmt = 0, $fv = 0, $type = 0)
|
||||
{
|
||||
@@ -1933,7 +1929,7 @@ class Financial
|
||||
* 3 Actual/365
|
||||
* 4 European 30/360
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function RECEIVED($settlement, $maturity, $investment, $discount, $basis = 0)
|
||||
{
|
||||
@@ -1969,7 +1965,7 @@ class Financial
|
||||
* @param float $pv Present Value
|
||||
* @param float $fv Future Value
|
||||
*
|
||||
* @return float|string
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function RRI($nper = 0, $pv = 0, $fv = 0)
|
||||
{
|
||||
@@ -1996,7 +1992,7 @@ class Financial
|
||||
* @param mixed $salvage Value at the end of the depreciation
|
||||
* @param mixed $life Number of periods over which the asset is depreciated
|
||||
*
|
||||
* @return float|string
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function SLN($cost, $salvage, $life)
|
||||
{
|
||||
@@ -2026,7 +2022,7 @@ class Financial
|
||||
* @param mixed $life Number of periods over which the asset is depreciated
|
||||
* @param mixed $period Period
|
||||
*
|
||||
* @return float|string
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function SYD($cost, $salvage, $life, $period)
|
||||
{
|
||||
@@ -2058,7 +2054,7 @@ class Financial
|
||||
* The maturity date is the date when the Treasury bill expires.
|
||||
* @param int $discount The Treasury bill's discount rate
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function TBILLEQ($settlement, $maturity, $discount)
|
||||
{
|
||||
@@ -2097,7 +2093,7 @@ class Financial
|
||||
* The maturity date is the date when the Treasury bill expires.
|
||||
* @param int $discount The Treasury bill's discount rate
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function TBILLPRICE($settlement, $maturity, $discount)
|
||||
{
|
||||
@@ -2152,7 +2148,7 @@ class Financial
|
||||
* The maturity date is the date when the Treasury bill expires.
|
||||
* @param int $price The Treasury bill's price per $100 face value
|
||||
*
|
||||
* @return float
|
||||
* @return float|mixed|string
|
||||
*/
|
||||
public static function TBILLYIELD($settlement, $maturity, $price)
|
||||
{
|
||||
@@ -2187,6 +2183,23 @@ class Financial
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
/**
|
||||
* XIRR.
|
||||
*
|
||||
* Returns the internal rate of return for a schedule of cash flows that is not necessarily periodic.
|
||||
*
|
||||
* Excel Function:
|
||||
* =XIRR(values,dates,guess)
|
||||
*
|
||||
* @param float[] $values A series of cash flow payments
|
||||
* The series of values must contain at least one positive value & one negative value
|
||||
* @param mixed[] $dates A series of payment dates
|
||||
* The first payment date indicates the beginning of the schedule of payments
|
||||
* All other dates must be later than this date, but they may occur in any order
|
||||
* @param float $guess An optional guess at the expected answer
|
||||
*
|
||||
* @return float|mixed|string
|
||||
*/
|
||||
public static function XIRR($values, $dates, $guess = 0.1)
|
||||
{
|
||||
if ((!is_array($values)) && (!is_array($dates))) {
|
||||
@@ -2199,11 +2212,28 @@ class Financial
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
$datesCount = count($dates);
|
||||
for ($i = 0; $i < $datesCount; ++$i) {
|
||||
$dates[$i] = DateTime::getDateValue($dates[$i]);
|
||||
if (!is_numeric($dates[$i])) {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
}
|
||||
if (min($dates) != $dates[0]) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
// create an initial range, with a root somewhere between 0 and guess
|
||||
$x1 = 0.0;
|
||||
$x2 = $guess;
|
||||
$f1 = self::XNPV($x1, $values, $dates);
|
||||
if (!is_numeric($f1)) {
|
||||
return $f1;
|
||||
}
|
||||
$f2 = self::XNPV($x2, $values, $dates);
|
||||
if (!is_numeric($f2)) {
|
||||
return $f2;
|
||||
}
|
||||
for ($i = 0; $i < self::FINANCIAL_MAX_ITERATIONS; ++$i) {
|
||||
if (($f1 * $f2) < 0.0) {
|
||||
break;
|
||||
@@ -2214,7 +2244,7 @@ class Financial
|
||||
}
|
||||
}
|
||||
if (($f1 * $f2) > 0.0) {
|
||||
return Functions::VALUE();
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
$f = self::XNPV($x1, $values, $dates);
|
||||
@@ -2251,15 +2281,15 @@ class Financial
|
||||
* =XNPV(rate,values,dates)
|
||||
*
|
||||
* @param float $rate the discount rate to apply to the cash flows
|
||||
* @param array of float $values A series of cash flows that corresponds to a schedule of payments in dates.
|
||||
* @param float[] $values A series of cash flows that corresponds to a schedule of payments in dates.
|
||||
* The first payment is optional and corresponds to a cost or payment that occurs at the beginning of the investment.
|
||||
* If the first value is a cost or payment, it must be a negative value. All succeeding payments are discounted based on a 365-day year.
|
||||
* The series of values must contain at least one positive value and one negative value.
|
||||
* @param array of mixed $dates A schedule of payment dates that corresponds to the cash flow payments.
|
||||
* @param mixed[] $dates A schedule of payment dates that corresponds to the cash flow payments.
|
||||
* The first payment date indicates the beginning of the schedule of payments.
|
||||
* All other dates must be later than this date, but they may occur in any order.
|
||||
*
|
||||
* @return float
|
||||
* @return float|mixed|string
|
||||
*/
|
||||
public static function XNPV($rate, $values, $dates)
|
||||
{
|
||||
@@ -2277,7 +2307,7 @@ class Financial
|
||||
return Functions::NAN();
|
||||
}
|
||||
if ((min($values) > 0) || (max($values) < 0)) {
|
||||
return Functions::VALUE();
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
$xnpv = 0.0;
|
||||
@@ -2309,7 +2339,7 @@ class Financial
|
||||
* 3 Actual/365
|
||||
* 4 European 30/360
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function YIELDDISC($settlement, $maturity, $price, $redemption, $basis = 0)
|
||||
{
|
||||
@@ -2360,7 +2390,7 @@ class Financial
|
||||
* 3 Actual/365
|
||||
* 4 European 30/360
|
||||
*
|
||||
* @return float
|
||||
* @return float|string Result, or a string containing an error
|
||||
*/
|
||||
public static function YIELDMAT($settlement, $maturity, $issue, $rate, $price, $basis = 0)
|
||||
{
|
||||
|
||||
@@ -17,8 +17,11 @@ class Functions
|
||||
const COMPATIBILITY_EXCEL = 'Excel';
|
||||
const COMPATIBILITY_GNUMERIC = 'Gnumeric';
|
||||
const COMPATIBILITY_OPENOFFICE = 'OpenOfficeCalc';
|
||||
|
||||
const RETURNDATE_PHP_NUMERIC = 'P';
|
||||
const RETURNDATE_UNIX_TIMESTAMP = 'P';
|
||||
const RETURNDATE_PHP_OBJECT = 'O';
|
||||
const RETURNDATE_PHP_DATETIME_OBJECT = 'O';
|
||||
const RETURNDATE_EXCEL = 'E';
|
||||
|
||||
/**
|
||||
@@ -101,16 +104,16 @@ class Functions
|
||||
*
|
||||
* @param string $returnDateType Return Date Format
|
||||
* Permitted values are:
|
||||
* Functions::RETURNDATE_PHP_NUMERIC 'P'
|
||||
* Functions::RETURNDATE_PHP_OBJECT 'O'
|
||||
* Functions::RETURNDATE_UNIX_TIMESTAMP 'P'
|
||||
* Functions::RETURNDATE_PHP_DATETIME_OBJECT 'O'
|
||||
* Functions::RETURNDATE_EXCEL 'E'
|
||||
*
|
||||
* @return bool Success or failure
|
||||
*/
|
||||
public static function setReturnDateType($returnDateType)
|
||||
{
|
||||
if (($returnDateType == self::RETURNDATE_PHP_NUMERIC) ||
|
||||
($returnDateType == self::RETURNDATE_PHP_OBJECT) ||
|
||||
if (($returnDateType == self::RETURNDATE_UNIX_TIMESTAMP) ||
|
||||
($returnDateType == self::RETURNDATE_PHP_DATETIME_OBJECT) ||
|
||||
($returnDateType == self::RETURNDATE_EXCEL)
|
||||
) {
|
||||
self::$returnDateType = $returnDateType;
|
||||
@@ -128,8 +131,8 @@ class Functions
|
||||
*
|
||||
* @return string Return Date Format
|
||||
* Possible Return values are:
|
||||
* Functions::RETURNDATE_PHP_NUMERIC 'P'
|
||||
* Functions::RETURNDATE_PHP_OBJECT 'O'
|
||||
* Functions::RETURNDATE_UNIX_TIMESTAMP 'P'
|
||||
* Functions::RETURNDATE_PHP_DATETIME_OBJECT 'O'
|
||||
* Functions::RETURNDATE_EXCEL 'E'
|
||||
*/
|
||||
public static function getReturnDateType()
|
||||
@@ -267,25 +270,29 @@ class Functions
|
||||
public static function ifCondition($condition)
|
||||
{
|
||||
$condition = self::flattenSingleValue($condition);
|
||||
if (!isset($condition[0]) && !is_numeric($condition)) {
|
||||
|
||||
if ($condition === '') {
|
||||
$condition = '=""';
|
||||
}
|
||||
if (!in_array($condition[0], ['>', '<', '='])) {
|
||||
|
||||
if (!is_string($condition) || !in_array($condition[0], ['>', '<', '='])) {
|
||||
if (!is_numeric($condition)) {
|
||||
$condition = Calculation::wrapResult(strtoupper($condition));
|
||||
}
|
||||
|
||||
return '=' . $condition;
|
||||
return str_replace('""""', '""', '=' . $condition);
|
||||
}
|
||||
preg_match('/(=|<[>=]?|>=?)(.*)/', $condition, $matches);
|
||||
list(, $operator, $operand) = $matches;
|
||||
[, $operator, $operand] = $matches;
|
||||
|
||||
if (!is_numeric($operand)) {
|
||||
if (is_numeric(trim($operand, '"'))) {
|
||||
$operand = trim($operand, '"');
|
||||
} elseif (!is_numeric($operand)) {
|
||||
$operand = str_replace('"', '""', $operand);
|
||||
$operand = Calculation::wrapResult(strtoupper($operand));
|
||||
}
|
||||
|
||||
return $operator . $operand;
|
||||
return str_replace('""""', '""', $operator . $operand);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -639,7 +646,7 @@ class Functions
|
||||
public static function flattenSingleValue($value = '')
|
||||
{
|
||||
while (is_array($value)) {
|
||||
$value = array_pop($value);
|
||||
$value = array_shift($value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
||||
@@ -266,6 +266,10 @@ class Logical
|
||||
*/
|
||||
public static function statementIf($condition = true, $returnIfTrue = 0, $returnIfFalse = false)
|
||||
{
|
||||
if (Functions::isError($condition)) {
|
||||
return $condition;
|
||||
}
|
||||
|
||||
$condition = ($condition === null) ? true : (bool) Functions::flattenSingleValue($condition);
|
||||
$returnIfTrue = ($returnIfTrue === null) ? 0 : Functions::flattenSingleValue($returnIfTrue);
|
||||
$returnIfFalse = ($returnIfFalse === null) ? false : Functions::flattenSingleValue($returnIfFalse);
|
||||
@@ -347,4 +351,25 @@ class Logical
|
||||
|
||||
return self::statementIf(Functions::isError($testValue), $errorpart, $testValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* IFNA.
|
||||
*
|
||||
* Excel Function:
|
||||
* =IFNA(testValue,napart)
|
||||
*
|
||||
* @category Logical Functions
|
||||
*
|
||||
* @param mixed $testValue Value to check, is also the value returned when not an NA
|
||||
* @param mixed $napart Value to return when testValue is an NA condition
|
||||
*
|
||||
* @return mixed The value of errorpart or testValue determined by error condition
|
||||
*/
|
||||
public static function IFNA($testValue = '', $napart = '')
|
||||
{
|
||||
$testValue = ($testValue === null) ? '' : Functions::flattenSingleValue($testValue);
|
||||
$napart = ($napart === null) ? '' : Functions::flattenSingleValue($napart);
|
||||
|
||||
return self::statementIf(Functions::isNa($testValue), $napart, $testValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,9 +98,9 @@ class LookupRef
|
||||
return (int) Coordinate::columnIndexFromString($columnKey);
|
||||
}
|
||||
} else {
|
||||
list($sheet, $cellAddress) = Worksheet::extractSheetTitle($cellAddress, true);
|
||||
[$sheet, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true);
|
||||
if (strpos($cellAddress, ':') !== false) {
|
||||
list($startAddress, $endAddress) = explode(':', $cellAddress);
|
||||
[$startAddress, $endAddress] = explode(':', $cellAddress);
|
||||
$startAddress = preg_replace('/[^a-z]/i', '', $startAddress);
|
||||
$endAddress = preg_replace('/[^a-z]/i', '', $endAddress);
|
||||
$returnValue = [];
|
||||
@@ -138,7 +138,7 @@ class LookupRef
|
||||
|
||||
reset($cellAddress);
|
||||
$isMatrix = (is_numeric(key($cellAddress)));
|
||||
list($columns, $rows) = Calculation::getMatrixDimensions($cellAddress);
|
||||
[$columns, $rows] = Calculation::getMatrixDimensions($cellAddress);
|
||||
|
||||
if ($isMatrix) {
|
||||
return $rows;
|
||||
@@ -175,9 +175,9 @@ class LookupRef
|
||||
}
|
||||
}
|
||||
} else {
|
||||
list($sheet, $cellAddress) = Worksheet::extractSheetTitle($cellAddress, true);
|
||||
[$sheet, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true);
|
||||
if (strpos($cellAddress, ':') !== false) {
|
||||
list($startAddress, $endAddress) = explode(':', $cellAddress);
|
||||
[$startAddress, $endAddress] = explode(':', $cellAddress);
|
||||
$startAddress = preg_replace('/\D/', '', $startAddress);
|
||||
$endAddress = preg_replace('/\D/', '', $endAddress);
|
||||
$returnValue = [];
|
||||
@@ -187,7 +187,7 @@ class LookupRef
|
||||
|
||||
return $returnValue;
|
||||
}
|
||||
list($cellAddress) = explode(':', $cellAddress);
|
||||
[$cellAddress] = explode(':', $cellAddress);
|
||||
|
||||
return (int) preg_replace('/\D/', '', $cellAddress);
|
||||
}
|
||||
@@ -215,7 +215,7 @@ class LookupRef
|
||||
|
||||
reset($cellAddress);
|
||||
$isMatrix = (is_numeric(key($cellAddress)));
|
||||
list($columns, $rows) = Calculation::getMatrixDimensions($cellAddress);
|
||||
[$columns, $rows] = Calculation::getMatrixDimensions($cellAddress);
|
||||
|
||||
if ($isMatrix) {
|
||||
return $columns;
|
||||
@@ -285,7 +285,7 @@ class LookupRef
|
||||
$cellAddress1 = $cellAddress;
|
||||
$cellAddress2 = null;
|
||||
if (strpos($cellAddress, ':') !== false) {
|
||||
list($cellAddress1, $cellAddress2) = explode(':', $cellAddress);
|
||||
[$cellAddress1, $cellAddress2] = explode(':', $cellAddress);
|
||||
}
|
||||
|
||||
if ((!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellAddress1, $matches)) ||
|
||||
@@ -295,7 +295,7 @@ class LookupRef
|
||||
}
|
||||
|
||||
if (strpos($cellAddress, '!') !== false) {
|
||||
list($sheetName, $cellAddress) = Worksheet::extractSheetTitle($cellAddress, true);
|
||||
[$sheetName, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true);
|
||||
$sheetName = trim($sheetName, "'");
|
||||
$pSheet = $pCell->getWorksheet()->getParent()->getSheetByName($sheetName);
|
||||
} else {
|
||||
@@ -306,7 +306,7 @@ class LookupRef
|
||||
}
|
||||
|
||||
if (strpos($cellAddress, '!') !== false) {
|
||||
list($sheetName, $cellAddress) = Worksheet::extractSheetTitle($cellAddress, true);
|
||||
[$sheetName, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true);
|
||||
$sheetName = trim($sheetName, "'");
|
||||
$pSheet = $pCell->getWorksheet()->getParent()->getSheetByName($sheetName);
|
||||
} else {
|
||||
@@ -359,16 +359,16 @@ class LookupRef
|
||||
|
||||
$sheetName = null;
|
||||
if (strpos($cellAddress, '!')) {
|
||||
list($sheetName, $cellAddress) = Worksheet::extractSheetTitle($cellAddress, true);
|
||||
[$sheetName, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true);
|
||||
$sheetName = trim($sheetName, "'");
|
||||
}
|
||||
if (strpos($cellAddress, ':')) {
|
||||
list($startCell, $endCell) = explode(':', $cellAddress);
|
||||
[$startCell, $endCell] = explode(':', $cellAddress);
|
||||
} else {
|
||||
$startCell = $endCell = $cellAddress;
|
||||
}
|
||||
list($startCellColumn, $startCellRow) = Coordinate::coordinateFromString($startCell);
|
||||
list($endCellColumn, $endCellRow) = Coordinate::coordinateFromString($endCell);
|
||||
[$startCellColumn, $startCellRow] = Coordinate::coordinateFromString($startCell);
|
||||
[$endCellColumn, $endCellRow] = Coordinate::coordinateFromString($endCell);
|
||||
|
||||
$startCellRow += $rows;
|
||||
$startCellColumn = Coordinate::columnIndexFromString($startCellColumn) - 1;
|
||||
@@ -464,9 +464,10 @@ class LookupRef
|
||||
*
|
||||
* @param mixed $lookupValue The value that you want to match in lookup_array
|
||||
* @param mixed $lookupArray The range of cells being searched
|
||||
* @param mixed $matchType The number -1, 0, or 1. -1 means above, 0 means exact match, 1 means below. If match_type is 1 or -1, the list has to be ordered.
|
||||
* @param mixed $matchType The number -1, 0, or 1. -1 means above, 0 means exact match, 1 means below.
|
||||
* If match_type is 1 or -1, the list has to be ordered.
|
||||
*
|
||||
* @return int The relative position of the found item
|
||||
* @return int|string The relative position of the found item
|
||||
*/
|
||||
public static function MATCH($lookupValue, $lookupArray, $matchType = 1)
|
||||
{
|
||||
@@ -474,9 +475,10 @@ class LookupRef
|
||||
$lookupValue = Functions::flattenSingleValue($lookupValue);
|
||||
$matchType = ($matchType === null) ? 1 : (int) Functions::flattenSingleValue($matchType);
|
||||
|
||||
$initialLookupValue = $lookupValue;
|
||||
// MATCH is not case sensitive
|
||||
$lookupValue = StringHelper::strToLower($lookupValue);
|
||||
// MATCH is not case sensitive, so we convert lookup value to be lower cased in case it's string type.
|
||||
if (is_string($lookupValue)) {
|
||||
$lookupValue = StringHelper::strToLower($lookupValue);
|
||||
}
|
||||
|
||||
// Lookup_value type has to be number, text, or logical values
|
||||
if ((!is_numeric($lookupValue)) && (!is_string($lookupValue)) && (!is_bool($lookupValue))) {
|
||||
@@ -522,16 +524,54 @@ class LookupRef
|
||||
// find the match
|
||||
// **
|
||||
|
||||
if ($matchType == 0 || $matchType == 1) {
|
||||
if ($matchType === 0 || $matchType === 1) {
|
||||
foreach ($lookupArray as $i => $lookupArrayValue) {
|
||||
$onlyNumeric = is_numeric($lookupArrayValue) && is_numeric($lookupValue);
|
||||
$onlyNumericExactMatch = $onlyNumeric && $lookupArrayValue == $lookupValue;
|
||||
$nonOnlyNumericExactMatch = !$onlyNumeric && $lookupArrayValue === $lookupValue;
|
||||
$exactMatch = $onlyNumericExactMatch || $nonOnlyNumericExactMatch;
|
||||
if (($matchType == 0) && $exactMatch) {
|
||||
// exact match
|
||||
return $i + 1;
|
||||
} elseif (($matchType == 1) && ($lookupArrayValue <= $lookupValue)) {
|
||||
$typeMatch = gettype($lookupValue) === gettype($lookupArrayValue);
|
||||
$exactTypeMatch = $typeMatch && $lookupArrayValue === $lookupValue;
|
||||
$nonOnlyNumericExactMatch = !$typeMatch && $lookupArrayValue === $lookupValue;
|
||||
$exactMatch = $exactTypeMatch || $nonOnlyNumericExactMatch;
|
||||
|
||||
if ($matchType === 0) {
|
||||
if ($typeMatch && is_string($lookupValue) && (bool) preg_match('/([\?\*])/', $lookupValue)) {
|
||||
$splitString = $lookupValue;
|
||||
$chars = array_map(function ($i) use ($splitString) {
|
||||
return mb_substr($splitString, $i, 1);
|
||||
}, range(0, mb_strlen($splitString) - 1));
|
||||
|
||||
$length = count($chars);
|
||||
$pattern = '/^';
|
||||
for ($j = 0; $j < $length; ++$j) {
|
||||
if ($chars[$j] === '~') {
|
||||
if (isset($chars[$j + 1])) {
|
||||
if ($chars[$j + 1] === '*') {
|
||||
$pattern .= preg_quote($chars[$j + 1], '/');
|
||||
++$j;
|
||||
} elseif ($chars[$j + 1] === '?') {
|
||||
$pattern .= preg_quote($chars[$j + 1], '/');
|
||||
++$j;
|
||||
}
|
||||
} else {
|
||||
$pattern .= preg_quote($chars[$j], '/');
|
||||
}
|
||||
} elseif ($chars[$j] === '*') {
|
||||
$pattern .= '.*';
|
||||
} elseif ($chars[$j] === '?') {
|
||||
$pattern .= '.{1}';
|
||||
} else {
|
||||
$pattern .= preg_quote($chars[$j], '/');
|
||||
}
|
||||
}
|
||||
|
||||
$pattern .= '$/';
|
||||
if ((bool) preg_match($pattern, $lookupArrayValue)) {
|
||||
// exact match
|
||||
return $i + 1;
|
||||
}
|
||||
} elseif ($exactMatch) {
|
||||
// exact match
|
||||
return $i + 1;
|
||||
}
|
||||
} elseif (($matchType === 1) && $typeMatch && ($lookupArrayValue <= $lookupValue)) {
|
||||
$i = array_search($i, $keySet);
|
||||
|
||||
// The current value is the (first) match
|
||||
@@ -539,26 +579,26 @@ class LookupRef
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// matchType = -1
|
||||
|
||||
// "Special" case: since the array it's supposed to be ordered in descending order, the
|
||||
// Excel algorithm gives up immediately if the first element is smaller than the searched value
|
||||
if ($lookupArray[0] < $lookupValue) {
|
||||
return Functions::NA();
|
||||
}
|
||||
|
||||
$maxValueKey = null;
|
||||
|
||||
// The basic algorithm is:
|
||||
// Iterate and keep the highest match until the next element is smaller than the searched value.
|
||||
// Return immediately if perfect match is found
|
||||
foreach ($lookupArray as $i => $lookupArrayValue) {
|
||||
if ($lookupArrayValue == $lookupValue) {
|
||||
$typeMatch = gettype($lookupValue) === gettype($lookupArrayValue);
|
||||
$exactTypeMatch = $typeMatch && $lookupArrayValue === $lookupValue;
|
||||
$nonOnlyNumericExactMatch = !$typeMatch && $lookupArrayValue === $lookupValue;
|
||||
$exactMatch = $exactTypeMatch || $nonOnlyNumericExactMatch;
|
||||
|
||||
if ($exactMatch) {
|
||||
// Another "special" case. If a perfect match is found,
|
||||
// the algorithm gives up immediately
|
||||
return $i + 1;
|
||||
} elseif ($lookupArrayValue >= $lookupValue) {
|
||||
} elseif ($typeMatch & $lookupArrayValue >= $lookupValue) {
|
||||
$maxValueKey = $i + 1;
|
||||
} elseif ($typeMatch & $lookupArrayValue < $lookupValue) {
|
||||
//Excel algorithm gives up immediately if the first element is smaller than the searched value
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -794,8 +834,10 @@ class LookupRef
|
||||
$lookupLower = StringHelper::strToLower($lookup_value);
|
||||
$rowDataLower = StringHelper::strToLower($rowData);
|
||||
|
||||
if (($bothNumeric && $rowData > $lookup_value) ||
|
||||
($bothNotNumeric && $rowDataLower > $lookupLower)) {
|
||||
if ($not_exact_match && (
|
||||
($bothNumeric && $rowData > $lookup_value) ||
|
||||
($bothNotNumeric && $rowDataLower > $lookupLower)
|
||||
)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,88 @@ class MathTrig
|
||||
return ($num - ($num % $n)) / $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* ARABIC.
|
||||
*
|
||||
* Converts a Roman numeral to an Arabic numeral.
|
||||
*
|
||||
* Excel Function:
|
||||
* ARABIC(text)
|
||||
*
|
||||
* @category Mathematical and Trigonometric Functions
|
||||
*
|
||||
* @param string $roman
|
||||
*
|
||||
* @return int|string the arabic numberal contrived from the roman numeral
|
||||
*/
|
||||
public static function ARABIC($roman)
|
||||
{
|
||||
// An empty string should return 0
|
||||
$roman = substr(trim(strtoupper((string) Functions::flattenSingleValue($roman))), 0, 255);
|
||||
if ($roman === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Convert the roman numeral to an arabic number
|
||||
$negativeNumber = $roman[0] === '-';
|
||||
if ($negativeNumber) {
|
||||
$roman = substr($roman, 1);
|
||||
}
|
||||
|
||||
try {
|
||||
$arabic = self::calculateArabic(str_split($roman));
|
||||
} catch (\Exception $e) {
|
||||
return Functions::VALUE(); // Invalid character detected
|
||||
}
|
||||
|
||||
if ($negativeNumber) {
|
||||
$arabic *= -1; // The number should be negative
|
||||
}
|
||||
|
||||
return $arabic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively calculate the arabic value of a roman numeral.
|
||||
*
|
||||
* @param array $roman
|
||||
* @param int $sum
|
||||
* @param int $subtract
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected static function calculateArabic(array $roman, &$sum = 0, $subtract = 0)
|
||||
{
|
||||
$lookup = [
|
||||
'M' => 1000,
|
||||
'D' => 500,
|
||||
'C' => 100,
|
||||
'L' => 50,
|
||||
'X' => 10,
|
||||
'V' => 5,
|
||||
'I' => 1,
|
||||
];
|
||||
|
||||
$numeral = array_shift($roman);
|
||||
if (!isset($lookup[$numeral])) {
|
||||
throw new \Exception('Invalid character detected');
|
||||
}
|
||||
|
||||
$arabic = $lookup[$numeral];
|
||||
if (count($roman) > 0 && isset($lookup[$roman[0]]) && $arabic < $lookup[$roman[0]]) {
|
||||
$subtract += $arabic;
|
||||
} else {
|
||||
$sum += ($arabic - $subtract);
|
||||
$subtract = 0;
|
||||
}
|
||||
|
||||
if (count($roman) > 0) {
|
||||
self::calculateArabic($roman, $sum, $subtract);
|
||||
}
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* ATAN2.
|
||||
*
|
||||
@@ -59,7 +141,7 @@ class MathTrig
|
||||
* @param float $xCoordinate the x-coordinate of the point
|
||||
* @param float $yCoordinate the y-coordinate of the point
|
||||
*
|
||||
* @return float the inverse tangent of the specified x- and y-coordinates
|
||||
* @return float|string the inverse tangent of the specified x- and y-coordinates, or a string containing an error
|
||||
*/
|
||||
public static function ATAN2($xCoordinate = null, $yCoordinate = null)
|
||||
{
|
||||
@@ -84,6 +166,49 @@ class MathTrig
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
/**
|
||||
* BASE.
|
||||
*
|
||||
* Converts a number into a text representation with the given radix (base).
|
||||
*
|
||||
* Excel Function:
|
||||
* BASE(Number, Radix [Min_length])
|
||||
*
|
||||
* @category Mathematical and Trigonometric Functions
|
||||
*
|
||||
* @param float $number
|
||||
* @param float $radix
|
||||
* @param int $minLength
|
||||
*
|
||||
* @return string the text representation with the given radix (base)
|
||||
*/
|
||||
public static function BASE($number, $radix, $minLength = null)
|
||||
{
|
||||
$number = Functions::flattenSingleValue($number);
|
||||
$radix = Functions::flattenSingleValue($radix);
|
||||
$minLength = Functions::flattenSingleValue($minLength);
|
||||
|
||||
if (is_numeric($number) && is_numeric($radix) && ($minLength === null || is_numeric($minLength))) {
|
||||
// Truncate to an integer
|
||||
$number = (int) $number;
|
||||
$radix = (int) $radix;
|
||||
$minLength = (int) $minLength;
|
||||
|
||||
if ($number < 0 || $number >= 2 ** 53 || $radix < 2 || $radix > 36) {
|
||||
return Functions::NAN(); // Numeric range constraints
|
||||
}
|
||||
|
||||
$outcome = strtoupper((string) base_convert($number, 10, $radix));
|
||||
if ($minLength !== null) {
|
||||
$outcome = str_pad($outcome, $minLength, '0', STR_PAD_LEFT); // String padding
|
||||
}
|
||||
|
||||
return $outcome;
|
||||
}
|
||||
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
/**
|
||||
* CEILING.
|
||||
*
|
||||
@@ -100,7 +225,7 @@ class MathTrig
|
||||
* @param float $number the number you want to round
|
||||
* @param float $significance the multiple to which you want to round
|
||||
*
|
||||
* @return float Rounded Number
|
||||
* @return float|string Rounded Number, or a string containing an error
|
||||
*/
|
||||
public static function CEILING($number, $significance = null)
|
||||
{
|
||||
@@ -139,7 +264,7 @@ class MathTrig
|
||||
* @param int $numObjs Number of different objects
|
||||
* @param int $numInSet Number of objects in each combination
|
||||
*
|
||||
* @return int Number of combinations
|
||||
* @return int|string Number of combinations, or a string containing an error
|
||||
*/
|
||||
public static function COMBIN($numObjs, $numInSet)
|
||||
{
|
||||
@@ -175,7 +300,7 @@ class MathTrig
|
||||
*
|
||||
* @param float $number Number to round
|
||||
*
|
||||
* @return int Rounded Number
|
||||
* @return int|string Rounded Number, or a string containing an error
|
||||
*/
|
||||
public static function EVEN($number)
|
||||
{
|
||||
@@ -209,7 +334,7 @@ class MathTrig
|
||||
*
|
||||
* @param float $factVal Factorial Value
|
||||
*
|
||||
* @return int Factorial
|
||||
* @return int|string Factorial, or a string containing an error
|
||||
*/
|
||||
public static function FACT($factVal)
|
||||
{
|
||||
@@ -220,10 +345,9 @@ class MathTrig
|
||||
return Functions::NAN();
|
||||
}
|
||||
$factLoop = floor($factVal);
|
||||
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
|
||||
if ($factVal > $factLoop) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
if ((Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) &&
|
||||
($factVal > $factLoop)) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
|
||||
$factorial = 1;
|
||||
@@ -249,7 +373,7 @@ class MathTrig
|
||||
*
|
||||
* @param float $factVal Factorial Value
|
||||
*
|
||||
* @return int Double Factorial
|
||||
* @return int|string Double Factorial, or a string containing an error
|
||||
*/
|
||||
public static function FACTDOUBLE($factVal)
|
||||
{
|
||||
@@ -285,7 +409,7 @@ class MathTrig
|
||||
* @param float $number Number to round
|
||||
* @param float $significance Significance
|
||||
*
|
||||
* @return float Rounded Number
|
||||
* @return float|string Rounded Number, or a string containing an error
|
||||
*/
|
||||
public static function FLOOR($number, $significance = null)
|
||||
{
|
||||
@@ -302,7 +426,9 @@ class MathTrig
|
||||
return Functions::DIV0();
|
||||
} elseif ($number == 0.0) {
|
||||
return 0.0;
|
||||
} elseif (self::SIGN($number) == self::SIGN($significance)) {
|
||||
} elseif (self::SIGN($significance) == 1) {
|
||||
return floor($number / $significance) * $significance;
|
||||
} elseif (self::SIGN($number) == -1 && self::SIGN($significance) == -1) {
|
||||
return floor($number / $significance) * $significance;
|
||||
}
|
||||
|
||||
@@ -312,6 +438,80 @@ class MathTrig
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
/**
|
||||
* FLOOR.MATH.
|
||||
*
|
||||
* Round a number down to the nearest integer or to the nearest multiple of significance.
|
||||
*
|
||||
* Excel Function:
|
||||
* FLOOR.MATH(number[,significance[,mode]])
|
||||
*
|
||||
* @category Mathematical and Trigonometric Functions
|
||||
*
|
||||
* @param float $number Number to round
|
||||
* @param float $significance Significance
|
||||
* @param int $mode direction to round negative numbers
|
||||
*
|
||||
* @return float|string Rounded Number, or a string containing an error
|
||||
*/
|
||||
public static function FLOORMATH($number, $significance = null, $mode = 0)
|
||||
{
|
||||
$number = Functions::flattenSingleValue($number);
|
||||
$significance = Functions::flattenSingleValue($significance);
|
||||
$mode = Functions::flattenSingleValue($mode);
|
||||
|
||||
if (is_numeric($number) && $significance === null) {
|
||||
$significance = $number / abs($number);
|
||||
}
|
||||
|
||||
if (is_numeric($number) && is_numeric($significance) && is_numeric($mode)) {
|
||||
if ($significance == 0.0) {
|
||||
return Functions::DIV0();
|
||||
} elseif ($number == 0.0) {
|
||||
return 0.0;
|
||||
} elseif (self::SIGN($significance) == -1 || (self::SIGN($number) == -1 && !empty($mode))) {
|
||||
return ceil($number / $significance) * $significance;
|
||||
}
|
||||
|
||||
return floor($number / $significance) * $significance;
|
||||
}
|
||||
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
/**
|
||||
* FLOOR.PRECISE.
|
||||
*
|
||||
* Rounds number down, toward zero, to the nearest multiple of significance.
|
||||
*
|
||||
* Excel Function:
|
||||
* FLOOR.PRECISE(number[,significance])
|
||||
*
|
||||
* @category Mathematical and Trigonometric Functions
|
||||
*
|
||||
* @param float $number Number to round
|
||||
* @param float $significance Significance
|
||||
*
|
||||
* @return float|string Rounded Number, or a string containing an error
|
||||
*/
|
||||
public static function FLOORPRECISE($number, $significance = 1)
|
||||
{
|
||||
$number = Functions::flattenSingleValue($number);
|
||||
$significance = Functions::flattenSingleValue($significance);
|
||||
|
||||
if ((is_numeric($number)) && (is_numeric($significance))) {
|
||||
if ($significance == 0.0) {
|
||||
return Functions::DIV0();
|
||||
} elseif ($number == 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return floor($number / abs($significance)) * abs($significance);
|
||||
}
|
||||
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
private static function evaluateGCD($a, $b)
|
||||
{
|
||||
return $b ? self::evaluateGCD($b, $a % $b) : $a;
|
||||
@@ -331,7 +531,7 @@ class MathTrig
|
||||
*
|
||||
* @param mixed ...$args Data values
|
||||
*
|
||||
* @return int Greatest Common Divisor
|
||||
* @return int|mixed|string Greatest Common Divisor, or a string containing an error
|
||||
*/
|
||||
public static function GCD(...$args)
|
||||
{
|
||||
@@ -365,7 +565,7 @@ class MathTrig
|
||||
*
|
||||
* @param float $number Number to cast to an integer
|
||||
*
|
||||
* @return int Integer value
|
||||
* @return int|string Integer value, or a string containing an error
|
||||
*/
|
||||
public static function INT($number)
|
||||
{
|
||||
@@ -398,7 +598,7 @@ class MathTrig
|
||||
*
|
||||
* @param mixed ...$args Data values
|
||||
*
|
||||
* @return int Lowest Common Multiplier
|
||||
* @return int|string Lowest Common Multiplier, or a string containing an error
|
||||
*/
|
||||
public static function LCM(...$args)
|
||||
{
|
||||
@@ -450,7 +650,7 @@ class MathTrig
|
||||
* @param float $number The positive real number for which you want the logarithm
|
||||
* @param float $base The base of the logarithm. If base is omitted, it is assumed to be 10.
|
||||
*
|
||||
* @return float
|
||||
* @return float|string The result, or a string containing an error
|
||||
*/
|
||||
public static function logBase($number = null, $base = 10)
|
||||
{
|
||||
@@ -479,7 +679,7 @@ class MathTrig
|
||||
*
|
||||
* @param array $matrixValues A matrix of values
|
||||
*
|
||||
* @return float
|
||||
* @return float|string The result, or a string containing an error
|
||||
*/
|
||||
public static function MDETERM($matrixValues)
|
||||
{
|
||||
@@ -531,7 +731,7 @@ class MathTrig
|
||||
*
|
||||
* @param array $matrixValues A matrix of values
|
||||
*
|
||||
* @return array
|
||||
* @return array|string The result, or a string containing an error
|
||||
*/
|
||||
public static function MINVERSE($matrixValues)
|
||||
{
|
||||
@@ -581,7 +781,7 @@ class MathTrig
|
||||
* @param array $matrixData1 A matrix of values
|
||||
* @param array $matrixData2 A matrix of values
|
||||
*
|
||||
* @return array
|
||||
* @return array|string The result, or a string containing an error
|
||||
*/
|
||||
public static function MMULT($matrixData1, $matrixData2)
|
||||
{
|
||||
@@ -643,7 +843,7 @@ class MathTrig
|
||||
* @param int $a Dividend
|
||||
* @param int $b Divisor
|
||||
*
|
||||
* @return int Remainder
|
||||
* @return int|string Remainder, or a string containing an error
|
||||
*/
|
||||
public static function MOD($a = 1, $b = 1)
|
||||
{
|
||||
@@ -669,7 +869,7 @@ class MathTrig
|
||||
* @param float $number Number to round
|
||||
* @param int $multiple Multiple to which you want to round $number
|
||||
*
|
||||
* @return float Rounded Number
|
||||
* @return float|string Rounded Number, or a string containing an error
|
||||
*/
|
||||
public static function MROUND($number, $multiple)
|
||||
{
|
||||
@@ -699,7 +899,7 @@ class MathTrig
|
||||
*
|
||||
* @param array of mixed Data Series
|
||||
*
|
||||
* @return float
|
||||
* @return float|string The result, or a string containing an error
|
||||
*/
|
||||
public static function MULTINOMIAL(...$args)
|
||||
{
|
||||
@@ -736,7 +936,7 @@ class MathTrig
|
||||
*
|
||||
* @param float $number Number to round
|
||||
*
|
||||
* @return int Rounded Number
|
||||
* @return int|string Rounded Number, or a string containing an error
|
||||
*/
|
||||
public static function ODD($number)
|
||||
{
|
||||
@@ -771,7 +971,7 @@ class MathTrig
|
||||
* @param float $x
|
||||
* @param float $y
|
||||
*
|
||||
* @return float
|
||||
* @return float|string The result, or a string containing an error
|
||||
*/
|
||||
public static function POWER($x = 0, $y = 2)
|
||||
{
|
||||
@@ -930,7 +1130,7 @@ class MathTrig
|
||||
* @param float $number Number to round
|
||||
* @param int $digits Number of digits to which you want to round $number
|
||||
*
|
||||
* @return float Rounded Number
|
||||
* @return float|string Rounded Number, or a string containing an error
|
||||
*/
|
||||
public static function ROUNDUP($number, $digits)
|
||||
{
|
||||
@@ -938,12 +1138,11 @@ class MathTrig
|
||||
$digits = Functions::flattenSingleValue($digits);
|
||||
|
||||
if ((is_numeric($number)) && (is_numeric($digits))) {
|
||||
$significance = pow(10, (int) $digits);
|
||||
if ($number < 0.0) {
|
||||
return floor($number * $significance) / $significance;
|
||||
return round($number - 0.5 * pow(0.1, $digits), $digits, PHP_ROUND_HALF_DOWN);
|
||||
}
|
||||
|
||||
return ceil($number * $significance) / $significance;
|
||||
return round($number + 0.5 * pow(0.1, $digits), $digits, PHP_ROUND_HALF_DOWN);
|
||||
}
|
||||
|
||||
return Functions::VALUE();
|
||||
@@ -957,7 +1156,7 @@ class MathTrig
|
||||
* @param float $number Number to round
|
||||
* @param int $digits Number of digits to which you want to round $number
|
||||
*
|
||||
* @return float Rounded Number
|
||||
* @return float|string Rounded Number, or a string containing an error
|
||||
*/
|
||||
public static function ROUNDDOWN($number, $digits)
|
||||
{
|
||||
@@ -965,12 +1164,11 @@ class MathTrig
|
||||
$digits = Functions::flattenSingleValue($digits);
|
||||
|
||||
if ((is_numeric($number)) && (is_numeric($digits))) {
|
||||
$significance = pow(10, (int) $digits);
|
||||
if ($number < 0.0) {
|
||||
return ceil($number * $significance) / $significance;
|
||||
return round($number + 0.5 * pow(0.1, $digits), $digits, PHP_ROUND_HALF_UP);
|
||||
}
|
||||
|
||||
return floor($number * $significance) / $significance;
|
||||
return round($number - 0.5 * pow(0.1, $digits), $digits, PHP_ROUND_HALF_UP);
|
||||
}
|
||||
|
||||
return Functions::VALUE();
|
||||
@@ -986,7 +1184,7 @@ class MathTrig
|
||||
* @param float $m Step by which to increase $n for each term in the series
|
||||
* @param array of mixed Data Series
|
||||
*
|
||||
* @return float
|
||||
* @return float|string The result, or a string containing an error
|
||||
*/
|
||||
public static function SERIESSUM(...$args)
|
||||
{
|
||||
@@ -1025,7 +1223,7 @@ class MathTrig
|
||||
*
|
||||
* @param float $number Number to round
|
||||
*
|
||||
* @return int sign value
|
||||
* @return int|string sign value, or a string containing an error
|
||||
*/
|
||||
public static function SIGN($number)
|
||||
{
|
||||
@@ -1052,7 +1250,7 @@ class MathTrig
|
||||
*
|
||||
* @param float $number Number
|
||||
*
|
||||
* @return float Square Root of Number * Pi
|
||||
* @return float|string Square Root of Number * Pi, or a string containing an error
|
||||
*/
|
||||
public static function SQRTPI($number)
|
||||
{
|
||||
@@ -1074,7 +1272,7 @@ class MathTrig
|
||||
return array_filter(
|
||||
$args,
|
||||
function ($index) use ($cellReference) {
|
||||
list(, $row, $column) = explode('.', $index);
|
||||
[, $row, $column] = explode('.', $index);
|
||||
|
||||
return $cellReference->getWorksheet()->getRowDimension($row)->getVisible() &&
|
||||
$cellReference->getWorksheet()->getColumnDimension($column)->getVisible();
|
||||
@@ -1088,7 +1286,7 @@ class MathTrig
|
||||
return array_filter(
|
||||
$args,
|
||||
function ($index) use ($cellReference) {
|
||||
list(, $row, $column) = explode('.', $index);
|
||||
[, $row, $column] = explode('.', $index);
|
||||
if ($cellReference->getWorksheet()->cellExists($column . $row)) {
|
||||
//take this cell out if it contains the SUBTOTAL or AGGREGATE functions in a formula
|
||||
$isFormula = $cellReference->getWorksheet()->getCell($column . $row)->isFormula();
|
||||
@@ -1116,7 +1314,7 @@ class MathTrig
|
||||
* in hidden rows or columns
|
||||
* @param array of mixed Data Series
|
||||
*
|
||||
* @return float
|
||||
* @return float|string
|
||||
*/
|
||||
public static function SUBTOTAL(...$args)
|
||||
{
|
||||
@@ -1306,7 +1504,7 @@ class MathTrig
|
||||
*
|
||||
* @param mixed ...$args Data values
|
||||
*
|
||||
* @return float
|
||||
* @return float|string The result, or a string containing an error
|
||||
*/
|
||||
public static function SUMPRODUCT(...$args)
|
||||
{
|
||||
@@ -1451,7 +1649,7 @@ class MathTrig
|
||||
* @param float $value
|
||||
* @param int $digits
|
||||
*
|
||||
* @return float Truncated value
|
||||
* @return float|string Truncated value, or a string containing an error
|
||||
*/
|
||||
public static function TRUNC($value = 0, $digits = 0)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -52,7 +52,7 @@ class TextData
|
||||
return ($stringValue) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
|
||||
if (self::$invalidChars == null) {
|
||||
if (self::$invalidChars === null) {
|
||||
self::$invalidChars = range(chr(0), chr(31));
|
||||
}
|
||||
|
||||
@@ -84,6 +84,15 @@ class TextData
|
||||
return null;
|
||||
}
|
||||
|
||||
private static function convertBooleanValue($value)
|
||||
{
|
||||
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
return ($value) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
|
||||
/**
|
||||
* ASCIICODE.
|
||||
*
|
||||
@@ -98,11 +107,7 @@ class TextData
|
||||
}
|
||||
$characters = Functions::flattenSingleValue($characters);
|
||||
if (is_bool($characters)) {
|
||||
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
|
||||
$characters = (int) $characters;
|
||||
} else {
|
||||
$characters = ($characters) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
$characters = self::convertBooleanValue($characters);
|
||||
}
|
||||
|
||||
$character = $characters;
|
||||
@@ -126,11 +131,7 @@ class TextData
|
||||
$aArgs = Functions::flattenArray($args);
|
||||
foreach ($aArgs as $arg) {
|
||||
if (is_bool($arg)) {
|
||||
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
|
||||
$arg = (int) $arg;
|
||||
} else {
|
||||
$arg = ($arg) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
$arg = self::convertBooleanValue($arg);
|
||||
}
|
||||
$returnValue .= $arg;
|
||||
}
|
||||
@@ -197,7 +198,7 @@ class TextData
|
||||
}
|
||||
|
||||
if (($offset > 0) && (StringHelper::countCharacters($haystack) > $offset)) {
|
||||
if (StringHelper::countCharacters($needle) == 0) {
|
||||
if (StringHelper::countCharacters($needle) === 0) {
|
||||
return $offset;
|
||||
}
|
||||
|
||||
@@ -232,7 +233,7 @@ class TextData
|
||||
}
|
||||
|
||||
if (($offset > 0) && (StringHelper::countCharacters($haystack) > $offset)) {
|
||||
if (StringHelper::countCharacters($needle) == 0) {
|
||||
if (StringHelper::countCharacters($needle) === 0) {
|
||||
return $offset;
|
||||
}
|
||||
|
||||
@@ -265,14 +266,19 @@ class TextData
|
||||
if (!is_numeric($value) || !is_numeric($decimals)) {
|
||||
return Functions::NAN();
|
||||
}
|
||||
$decimals = floor($decimals);
|
||||
$decimals = (int) floor($decimals);
|
||||
|
||||
$valueResult = round($value, $decimals);
|
||||
if ($decimals < 0) {
|
||||
$decimals = 0;
|
||||
}
|
||||
if (!$no_commas) {
|
||||
$valueResult = number_format($valueResult, $decimals);
|
||||
$valueResult = number_format(
|
||||
$valueResult,
|
||||
$decimals,
|
||||
StringHelper::getDecimalSeparator(),
|
||||
StringHelper::getThousandsSeparator()
|
||||
);
|
||||
}
|
||||
|
||||
return (string) $valueResult;
|
||||
@@ -659,11 +665,7 @@ class TextData
|
||||
if ($ignoreEmpty && trim($arg) == '') {
|
||||
unset($aArgs[$key]);
|
||||
} elseif (is_bool($arg)) {
|
||||
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
|
||||
$arg = (int) $arg;
|
||||
} else {
|
||||
$arg = ($arg) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
$arg = self::convertBooleanValue($arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,14 +36,24 @@ class Stack
|
||||
* @param mixed $type
|
||||
* @param mixed $value
|
||||
* @param mixed $reference
|
||||
* @param null|string $storeKey will store the result under this alias
|
||||
* @param null|string $onlyIf will only run computation if the matching
|
||||
* store key is true
|
||||
* @param null|string $onlyIfNot will only run computation if the matching
|
||||
* store key is false
|
||||
*/
|
||||
public function push($type, $value, $reference = null)
|
||||
{
|
||||
$this->stack[$this->count++] = [
|
||||
'type' => $type,
|
||||
'value' => $value,
|
||||
'reference' => $reference,
|
||||
];
|
||||
public function push(
|
||||
$type,
|
||||
$value,
|
||||
$reference = null,
|
||||
$storeKey = null,
|
||||
$onlyIf = null,
|
||||
$onlyIfNot = null
|
||||
) {
|
||||
$stackItem = $this->getStackItem($type, $value, $reference, $storeKey, $onlyIf, $onlyIfNot);
|
||||
|
||||
$this->stack[$this->count++] = $stackItem;
|
||||
|
||||
if ($type == 'Function') {
|
||||
$localeFunction = Calculation::localeFunc($value);
|
||||
if ($localeFunction != $value) {
|
||||
@@ -52,6 +62,35 @@ class Stack
|
||||
}
|
||||
}
|
||||
|
||||
public function getStackItem(
|
||||
$type,
|
||||
$value,
|
||||
$reference = null,
|
||||
$storeKey = null,
|
||||
$onlyIf = null,
|
||||
$onlyIfNot = null
|
||||
) {
|
||||
$stackItem = [
|
||||
'type' => $type,
|
||||
'value' => $value,
|
||||
'reference' => $reference,
|
||||
];
|
||||
|
||||
if (isset($storeKey)) {
|
||||
$stackItem['storeKey'] = $storeKey;
|
||||
}
|
||||
|
||||
if (isset($onlyIf)) {
|
||||
$stackItem['onlyIf'] = $onlyIf;
|
||||
}
|
||||
|
||||
if (isset($onlyIfNot)) {
|
||||
$stackItem['onlyIfNot'] = $onlyIfNot;
|
||||
}
|
||||
|
||||
return $stackItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop the last entry from the stack.
|
||||
*
|
||||
@@ -90,4 +129,21 @@ class Stack
|
||||
$this->stack = [];
|
||||
$this->count = 0;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
$str = 'Stack: ';
|
||||
foreach ($this->stack as $index => $item) {
|
||||
if ($index > $this->count - 1) {
|
||||
break;
|
||||
}
|
||||
$value = $item['value'] ?? 'no value';
|
||||
while (is_array($value)) {
|
||||
$value = array_pop($value);
|
||||
}
|
||||
$str .= $value . ' |> ';
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ ADDRESS
|
||||
AMORDEGRC
|
||||
AMORLINC
|
||||
AND
|
||||
ARABIC
|
||||
AREAS
|
||||
ASC
|
||||
ASIN
|
||||
@@ -22,6 +23,7 @@ AVERAGEA
|
||||
AVERAGEIF
|
||||
AVERAGEIFS
|
||||
BAHTTEXT
|
||||
BASE
|
||||
BESSELI
|
||||
BESSELJ
|
||||
BESSELK
|
||||
@@ -137,6 +139,8 @@ FISHER
|
||||
FISHERINV
|
||||
FIXED
|
||||
FLOOR
|
||||
FLOOR.MATH
|
||||
FLOOR.PRECISE
|
||||
FORECAST
|
||||
FREQUENCY
|
||||
FTEST
|
||||
@@ -224,6 +228,7 @@ LOWER
|
||||
MATCH
|
||||
MAX
|
||||
MAXA
|
||||
MAXIFS
|
||||
MDETERM
|
||||
MDURATION
|
||||
MEDIAN
|
||||
@@ -231,6 +236,7 @@ MID
|
||||
MIDB
|
||||
MIN
|
||||
MINA
|
||||
MINIFS
|
||||
MINUTE
|
||||
MINVERSE
|
||||
MIRR
|
||||
|
||||
@@ -118,7 +118,7 @@ class AdvancedValueBinder extends DefaultValueBinder implements IValueBinder
|
||||
// Check for time without seconds e.g. '9:45', '09:45'
|
||||
if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) {
|
||||
// Convert value to number
|
||||
list($h, $m) = explode(':', $value);
|
||||
[$h, $m] = explode(':', $value);
|
||||
$days = $h / 24 + $m / 1440;
|
||||
$cell->setValueExplicit($days, DataType::TYPE_NUMERIC);
|
||||
// Set style
|
||||
@@ -131,7 +131,7 @@ class AdvancedValueBinder extends DefaultValueBinder implements IValueBinder
|
||||
// Check for time with seconds '9:45:59', '09:45:59'
|
||||
if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d$/', $value)) {
|
||||
// Convert value to number
|
||||
list($h, $m, $s) = explode(':', $value);
|
||||
[$h, $m, $s] = explode(':', $value);
|
||||
$days = $h / 24 + $m / 1440 + $s / 86400;
|
||||
// Convert value to number
|
||||
$cell->setValueExplicit($days, DataType::TYPE_NUMERIC);
|
||||
|
||||
@@ -67,7 +67,7 @@ class Cell
|
||||
/**
|
||||
* Update the cell into the cell collection.
|
||||
*
|
||||
* @return self
|
||||
* @return $this
|
||||
*/
|
||||
public function updateInCollection()
|
||||
{
|
||||
@@ -177,7 +177,7 @@ class Cell
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Cell
|
||||
* @return $this
|
||||
*/
|
||||
public function setValue($pValue)
|
||||
{
|
||||
@@ -217,7 +217,10 @@ class Cell
|
||||
|
||||
break;
|
||||
case DataType::TYPE_NUMERIC:
|
||||
$this->value = (float) $pValue;
|
||||
if (is_string($pValue) && !is_numeric($pValue)) {
|
||||
throw new Exception('Invalid numeric value for datatype Numeric');
|
||||
}
|
||||
$this->value = 0 + $pValue;
|
||||
|
||||
break;
|
||||
case DataType::TYPE_FORMULA:
|
||||
@@ -263,7 +266,7 @@ class Cell
|
||||
// We don't yet handle array returns
|
||||
if (is_array($result)) {
|
||||
while (is_array($result)) {
|
||||
$result = array_pop($result);
|
||||
$result = array_shift($result);
|
||||
}
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
@@ -511,7 +514,7 @@ class Cell
|
||||
{
|
||||
if ($mergeRange = $this->getMergeRange()) {
|
||||
$mergeRange = Coordinate::splitRange($mergeRange);
|
||||
list($startCell) = $mergeRange[0];
|
||||
[$startCell] = $mergeRange[0];
|
||||
if ($this->getCoordinate() === $startCell) {
|
||||
return true;
|
||||
}
|
||||
@@ -569,7 +572,7 @@ class Cell
|
||||
*/
|
||||
public function isInRange($pRange)
|
||||
{
|
||||
list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($pRange);
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($pRange);
|
||||
|
||||
// Translate properties
|
||||
$myColumn = Coordinate::columnIndexFromString($this->getColumn());
|
||||
@@ -669,7 +672,7 @@ class Cell
|
||||
*
|
||||
* @param mixed $pAttributes
|
||||
*
|
||||
* @return Cell
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormulaAttributes($pAttributes)
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ abstract class Coordinate
|
||||
}
|
||||
|
||||
// Split out any worksheet name from the reference
|
||||
list($worksheet, $pCoordinateString) = Worksheet::extractSheetTitle($pCoordinateString, true);
|
||||
[$worksheet, $pCoordinateString] = Worksheet::extractSheetTitle($pCoordinateString, true);
|
||||
if ($worksheet > '') {
|
||||
$worksheet .= '!';
|
||||
}
|
||||
@@ -102,13 +102,13 @@ abstract class Coordinate
|
||||
}
|
||||
|
||||
// Split out any worksheet name from the coordinate
|
||||
list($worksheet, $pCoordinateString) = Worksheet::extractSheetTitle($pCoordinateString, true);
|
||||
[$worksheet, $pCoordinateString] = Worksheet::extractSheetTitle($pCoordinateString, true);
|
||||
if ($worksheet > '') {
|
||||
$worksheet .= '!';
|
||||
}
|
||||
|
||||
// Create absolute coordinate
|
||||
list($column, $row) = self::coordinateFromString($pCoordinateString);
|
||||
[$column, $row] = self::coordinateFromString($pCoordinateString);
|
||||
$column = ltrim($column, '$');
|
||||
$row = ltrim($row, '$');
|
||||
|
||||
@@ -187,7 +187,7 @@ abstract class Coordinate
|
||||
if (strpos($pRange, ':') === false) {
|
||||
$rangeA = $rangeB = $pRange;
|
||||
} else {
|
||||
list($rangeA, $rangeB) = explode(':', $pRange);
|
||||
[$rangeA, $rangeB] = explode(':', $pRange);
|
||||
}
|
||||
|
||||
// Calculate range outer borders
|
||||
@@ -211,7 +211,7 @@ abstract class Coordinate
|
||||
public static function rangeDimension($pRange)
|
||||
{
|
||||
// Calculate range outer borders
|
||||
list($rangeStart, $rangeEnd) = self::rangeBoundaries($pRange);
|
||||
[$rangeStart, $rangeEnd] = self::rangeBoundaries($pRange);
|
||||
|
||||
return [($rangeEnd[0] - $rangeStart[0] + 1), ($rangeEnd[1] - $rangeStart[1] + 1)];
|
||||
}
|
||||
@@ -238,7 +238,7 @@ abstract class Coordinate
|
||||
if (strpos($pRange, ':') === false) {
|
||||
$rangeA = $rangeB = $pRange;
|
||||
} else {
|
||||
list($rangeA, $rangeB) = explode(':', $pRange);
|
||||
[$rangeA, $rangeB] = explode(':', $pRange);
|
||||
}
|
||||
|
||||
return [self::coordinateFromString($rangeA), self::coordinateFromString($rangeB)];
|
||||
@@ -376,9 +376,9 @@ abstract class Coordinate
|
||||
}
|
||||
|
||||
// Range...
|
||||
list($rangeStart, $rangeEnd) = $range;
|
||||
list($startColumn, $startRow) = self::coordinateFromString($rangeStart);
|
||||
list($endColumn, $endRow) = self::coordinateFromString($rangeEnd);
|
||||
[$rangeStart, $rangeEnd] = $range;
|
||||
[$startColumn, $startRow] = self::coordinateFromString($rangeStart);
|
||||
[$endColumn, $endRow] = self::coordinateFromString($rangeEnd);
|
||||
$startColumnIndex = self::columnIndexFromString($startColumn);
|
||||
$endColumnIndex = self::columnIndexFromString($endColumn);
|
||||
++$endColumnIndex;
|
||||
@@ -432,7 +432,7 @@ abstract class Coordinate
|
||||
continue;
|
||||
}
|
||||
|
||||
list($column, $row) = self::coordinateFromString($coord);
|
||||
[$column, $row] = self::coordinateFromString($coord);
|
||||
$row = (int) (ltrim($row, '$'));
|
||||
$hashCode = $column . '-' . (is_object($value) ? $value->getHashCode() : $value);
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ class DataValidation
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormula1($value)
|
||||
{
|
||||
@@ -166,7 +166,7 @@ class DataValidation
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormula2($value)
|
||||
{
|
||||
@@ -190,7 +190,7 @@ class DataValidation
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setType($value)
|
||||
{
|
||||
@@ -214,7 +214,7 @@ class DataValidation
|
||||
*
|
||||
* @param string $value see self::STYLE_*
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setErrorStyle($value)
|
||||
{
|
||||
@@ -238,7 +238,7 @@ class DataValidation
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setOperator($value)
|
||||
{
|
||||
@@ -262,7 +262,7 @@ class DataValidation
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setAllowBlank($value)
|
||||
{
|
||||
@@ -286,7 +286,7 @@ class DataValidation
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowDropDown($value)
|
||||
{
|
||||
@@ -310,7 +310,7 @@ class DataValidation
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowInputMessage($value)
|
||||
{
|
||||
@@ -334,7 +334,7 @@ class DataValidation
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowErrorMessage($value)
|
||||
{
|
||||
@@ -358,7 +358,7 @@ class DataValidation
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setErrorTitle($value)
|
||||
{
|
||||
@@ -382,7 +382,7 @@ class DataValidation
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setError($value)
|
||||
{
|
||||
@@ -406,7 +406,7 @@ class DataValidation
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setPromptTitle($value)
|
||||
{
|
||||
@@ -430,7 +430,7 @@ class DataValidation
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return DataValidation
|
||||
* @return $this
|
||||
*/
|
||||
public function setPrompt($value)
|
||||
{
|
||||
|
||||
@@ -51,16 +51,16 @@ class DefaultValueBinder implements IValueBinder
|
||||
// Match the value against a few data types
|
||||
if ($pValue === null) {
|
||||
return DataType::TYPE_NULL;
|
||||
} elseif (is_float($pValue) || is_int($pValue)) {
|
||||
return DataType::TYPE_NUMERIC;
|
||||
} elseif (is_bool($pValue)) {
|
||||
return DataType::TYPE_BOOL;
|
||||
} elseif ($pValue === '') {
|
||||
return DataType::TYPE_STRING;
|
||||
} elseif ($pValue instanceof RichText) {
|
||||
return DataType::TYPE_INLINE;
|
||||
} elseif ($pValue[0] === '=' && strlen($pValue) > 1) {
|
||||
} elseif (is_string($pValue) && $pValue[0] === '=' && strlen($pValue) > 1) {
|
||||
return DataType::TYPE_FORMULA;
|
||||
} elseif (is_bool($pValue)) {
|
||||
return DataType::TYPE_BOOL;
|
||||
} elseif (is_float($pValue) || is_int($pValue)) {
|
||||
return DataType::TYPE_NUMERIC;
|
||||
} elseif (preg_match('/^[\+\-]?(\d+\\.?\d*|\d*\\.?\d+)([Ee][\-\+]?[0-2]?\d{1,3})?$/', $pValue)) {
|
||||
$tValue = ltrim($pValue, '+-');
|
||||
if (is_string($pValue) && $tValue[0] === '0' && strlen($tValue) > 1 && $tValue[1] !== '.') {
|
||||
|
||||
@@ -46,7 +46,7 @@ class Hyperlink
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return Hyperlink
|
||||
* @return $this
|
||||
*/
|
||||
public function setUrl($value)
|
||||
{
|
||||
@@ -70,7 +70,7 @@ class Hyperlink
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return Hyperlink
|
||||
* @return $this
|
||||
*/
|
||||
public function setTooltip($value)
|
||||
{
|
||||
|
||||
@@ -354,7 +354,7 @@ class Axis extends Properties
|
||||
*
|
||||
* @param int $shadow_presets
|
||||
*
|
||||
* @return Axis
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowPresetsProperties($shadow_presets)
|
||||
{
|
||||
@@ -370,7 +370,7 @@ class Axis extends Properties
|
||||
* @param array $properties_map
|
||||
* @param mixed &$reference
|
||||
*
|
||||
* @return Axis
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowProperiesMapValues(array $properties_map, &$reference = null)
|
||||
{
|
||||
@@ -402,7 +402,7 @@ class Axis extends Properties
|
||||
* @param int $alpha
|
||||
* @param string $type
|
||||
*
|
||||
* @return Axis
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowColor($color, $alpha, $type)
|
||||
{
|
||||
@@ -416,7 +416,7 @@ class Axis extends Properties
|
||||
*
|
||||
* @param float $blur
|
||||
*
|
||||
* @return Axis
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowBlur($blur)
|
||||
{
|
||||
@@ -432,7 +432,7 @@ class Axis extends Properties
|
||||
*
|
||||
* @param int $angle
|
||||
*
|
||||
* @return Axis
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowAngle($angle)
|
||||
{
|
||||
@@ -448,7 +448,7 @@ class Axis extends Properties
|
||||
*
|
||||
* @param float $distance
|
||||
*
|
||||
* @return Axis
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowDistance($distance)
|
||||
{
|
||||
@@ -506,7 +506,7 @@ class Axis extends Properties
|
||||
*
|
||||
* @param float $size
|
||||
*
|
||||
* @return Axis
|
||||
* @return $this
|
||||
*/
|
||||
private function setGlowSize($size)
|
||||
{
|
||||
@@ -524,7 +524,7 @@ class Axis extends Properties
|
||||
* @param int $alpha
|
||||
* @param string $type
|
||||
*
|
||||
* @return Axis
|
||||
* @return $this
|
||||
*/
|
||||
private function setGlowColor($color, $alpha, $type)
|
||||
{
|
||||
|
||||
@@ -156,7 +156,7 @@ class Chart
|
||||
* @param null|GridLines $majorGridlines
|
||||
* @param null|GridLines $minorGridlines
|
||||
*/
|
||||
public function __construct($name, Title $title = null, Legend $legend = null, PlotArea $plotArea = null, $plotVisibleOnly = true, $displayBlanksAs = '0', Title $xAxisLabel = null, Title $yAxisLabel = null, Axis $xAxis = null, Axis $yAxis = null, GridLines $majorGridlines = null, GridLines $minorGridlines = null)
|
||||
public function __construct($name, Title $title = null, Legend $legend = null, PlotArea $plotArea = null, $plotVisibleOnly = true, $displayBlanksAs = 'gap', Title $xAxisLabel = null, Title $yAxisLabel = null, Axis $xAxis = null, Axis $yAxis = null, GridLines $majorGridlines = null, GridLines $minorGridlines = null)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->title = $title;
|
||||
@@ -197,7 +197,7 @@ class Chart
|
||||
*
|
||||
* @param Worksheet $pValue
|
||||
*
|
||||
* @return Chart
|
||||
* @return $this
|
||||
*/
|
||||
public function setWorksheet(Worksheet $pValue = null)
|
||||
{
|
||||
@@ -221,7 +221,7 @@ class Chart
|
||||
*
|
||||
* @param Title $title
|
||||
*
|
||||
* @return Chart
|
||||
* @return $this
|
||||
*/
|
||||
public function setTitle(Title $title)
|
||||
{
|
||||
@@ -245,7 +245,7 @@ class Chart
|
||||
*
|
||||
* @param Legend $legend
|
||||
*
|
||||
* @return Chart
|
||||
* @return $this
|
||||
*/
|
||||
public function setLegend(Legend $legend)
|
||||
{
|
||||
@@ -269,7 +269,7 @@ class Chart
|
||||
*
|
||||
* @param Title $label
|
||||
*
|
||||
* @return Chart
|
||||
* @return $this
|
||||
*/
|
||||
public function setXAxisLabel(Title $label)
|
||||
{
|
||||
@@ -293,7 +293,7 @@ class Chart
|
||||
*
|
||||
* @param Title $label
|
||||
*
|
||||
* @return Chart
|
||||
* @return $this
|
||||
*/
|
||||
public function setYAxisLabel(Title $label)
|
||||
{
|
||||
@@ -327,7 +327,7 @@ class Chart
|
||||
*
|
||||
* @param bool $plotVisibleOnly
|
||||
*
|
||||
* @return Chart
|
||||
* @return $this
|
||||
*/
|
||||
public function setPlotVisibleOnly($plotVisibleOnly)
|
||||
{
|
||||
@@ -351,7 +351,7 @@ class Chart
|
||||
*
|
||||
* @param string $displayBlanksAs
|
||||
*
|
||||
* @return Chart
|
||||
* @return $this
|
||||
*/
|
||||
public function setDisplayBlanksAs($displayBlanksAs)
|
||||
{
|
||||
@@ -423,7 +423,7 @@ class Chart
|
||||
* @param int $xOffset
|
||||
* @param int $yOffset
|
||||
*
|
||||
* @return Chart
|
||||
* @return $this
|
||||
*/
|
||||
public function setTopLeftPosition($cell, $xOffset = null, $yOffset = null)
|
||||
{
|
||||
@@ -467,7 +467,7 @@ class Chart
|
||||
*
|
||||
* @param string $cell
|
||||
*
|
||||
* @return Chart
|
||||
* @return $this
|
||||
*/
|
||||
public function setTopLeftCell($cell)
|
||||
{
|
||||
@@ -482,7 +482,7 @@ class Chart
|
||||
* @param int $xOffset
|
||||
* @param int $yOffset
|
||||
*
|
||||
* @return Chart
|
||||
* @return $this
|
||||
*/
|
||||
public function setTopLeftOffset($xOffset, $yOffset)
|
||||
{
|
||||
@@ -541,7 +541,7 @@ class Chart
|
||||
* @param int $xOffset
|
||||
* @param int $yOffset
|
||||
*
|
||||
* @return Chart
|
||||
* @return $this
|
||||
*/
|
||||
public function setBottomRightPosition($cell, $xOffset = null, $yOffset = null)
|
||||
{
|
||||
@@ -593,7 +593,7 @@ class Chart
|
||||
* @param int $xOffset
|
||||
* @param int $yOffset
|
||||
*
|
||||
* @return Chart
|
||||
* @return $this
|
||||
*/
|
||||
public function setBottomRightOffset($xOffset, $yOffset)
|
||||
{
|
||||
|
||||
@@ -157,7 +157,7 @@ class DataSeries
|
||||
*
|
||||
* @param string $plotType
|
||||
*
|
||||
* @return DataSeries
|
||||
* @return $this
|
||||
*/
|
||||
public function setPlotType($plotType)
|
||||
{
|
||||
@@ -181,7 +181,7 @@ class DataSeries
|
||||
*
|
||||
* @param string $groupingType
|
||||
*
|
||||
* @return DataSeries
|
||||
* @return $this
|
||||
*/
|
||||
public function setPlotGrouping($groupingType)
|
||||
{
|
||||
@@ -205,7 +205,7 @@ class DataSeries
|
||||
*
|
||||
* @param string $plotDirection
|
||||
*
|
||||
* @return DataSeries
|
||||
* @return $this
|
||||
*/
|
||||
public function setPlotDirection($plotDirection)
|
||||
{
|
||||
@@ -297,7 +297,7 @@ class DataSeries
|
||||
*
|
||||
* @param null|string $plotStyle
|
||||
*
|
||||
* @return DataSeries
|
||||
* @return $this
|
||||
*/
|
||||
public function setPlotStyle($plotStyle)
|
||||
{
|
||||
@@ -360,7 +360,7 @@ class DataSeries
|
||||
*
|
||||
* @param bool $smoothLine
|
||||
*
|
||||
* @return DataSeries
|
||||
* @return $this
|
||||
*/
|
||||
public function setSmoothLine($smoothLine)
|
||||
{
|
||||
|
||||
@@ -117,7 +117,7 @@ class DataSeriesValues
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return DataSeriesValues
|
||||
* @return $this
|
||||
*/
|
||||
public function setDataType($dataType)
|
||||
{
|
||||
@@ -144,7 +144,7 @@ class DataSeriesValues
|
||||
*
|
||||
* @param string $dataSource
|
||||
*
|
||||
* @return DataSeriesValues
|
||||
* @return $this
|
||||
*/
|
||||
public function setDataSource($dataSource)
|
||||
{
|
||||
@@ -168,7 +168,7 @@ class DataSeriesValues
|
||||
*
|
||||
* @param string $marker
|
||||
*
|
||||
* @return DataSeriesValues
|
||||
* @return $this
|
||||
*/
|
||||
public function setPointMarker($marker)
|
||||
{
|
||||
@@ -192,7 +192,7 @@ class DataSeriesValues
|
||||
*
|
||||
* @param string $formatCode
|
||||
*
|
||||
* @return DataSeriesValues
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormatCode($formatCode)
|
||||
{
|
||||
@@ -275,7 +275,7 @@ class DataSeriesValues
|
||||
*
|
||||
* @param int $width
|
||||
*
|
||||
* @return DataSeriesValues
|
||||
* @return $this
|
||||
*/
|
||||
public function setLineWidth($width)
|
||||
{
|
||||
@@ -346,7 +346,7 @@ class DataSeriesValues
|
||||
*
|
||||
* @param array $dataValues
|
||||
*
|
||||
* @return DataSeriesValues
|
||||
* @return $this
|
||||
*/
|
||||
public function setDataValues($dataValues)
|
||||
{
|
||||
@@ -370,13 +370,13 @@ class DataSeriesValues
|
||||
if ($flatten) {
|
||||
$this->dataValues = Functions::flattenArray($newDataValues);
|
||||
foreach ($this->dataValues as &$dataValue) {
|
||||
if ((!empty($dataValue)) && ($dataValue[0] == '#')) {
|
||||
if (is_string($dataValue) && !empty($dataValue) && $dataValue[0] == '#') {
|
||||
$dataValue = 0.0;
|
||||
}
|
||||
}
|
||||
unset($dataValue);
|
||||
} else {
|
||||
list($worksheet, $cellRange) = Worksheet::extractSheetTitle($this->dataSource, true);
|
||||
[$worksheet, $cellRange] = Worksheet::extractSheetTitle($this->dataSource, true);
|
||||
$dimensions = Coordinate::rangeDimension(str_replace('$', '', $cellRange));
|
||||
if (($dimensions[0] == 1) || ($dimensions[1] == 1)) {
|
||||
$this->dataValues = Functions::flattenArray($newDataValues);
|
||||
|
||||
@@ -91,7 +91,7 @@ class GridLines extends Properties
|
||||
/**
|
||||
* Change Object State to True.
|
||||
*
|
||||
* @return GridLines
|
||||
* @return $this
|
||||
*/
|
||||
private function activateObject()
|
||||
{
|
||||
@@ -229,7 +229,7 @@ class GridLines extends Properties
|
||||
*
|
||||
* @param float $size
|
||||
*
|
||||
* @return GridLines
|
||||
* @return $this
|
||||
*/
|
||||
private function setGlowSize($size)
|
||||
{
|
||||
@@ -245,7 +245,7 @@ class GridLines extends Properties
|
||||
* @param int $alpha
|
||||
* @param string $type
|
||||
*
|
||||
* @return GridLines
|
||||
* @return $this
|
||||
*/
|
||||
private function setGlowColor($color, $alpha, $type)
|
||||
{
|
||||
@@ -305,7 +305,7 @@ class GridLines extends Properties
|
||||
*
|
||||
* @param int $shadow_presets
|
||||
*
|
||||
* @return GridLines
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowPresetsProperties($shadow_presets)
|
||||
{
|
||||
@@ -321,7 +321,7 @@ class GridLines extends Properties
|
||||
* @param array $properties_map
|
||||
* @param mixed &$reference
|
||||
*
|
||||
* @return GridLines
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowProperiesMapValues(array $properties_map, &$reference = null)
|
||||
{
|
||||
@@ -353,7 +353,7 @@ class GridLines extends Properties
|
||||
* @param int $alpha
|
||||
* @param string $type
|
||||
*
|
||||
* @return GridLines
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowColor($color, $alpha, $type)
|
||||
{
|
||||
@@ -375,7 +375,7 @@ class GridLines extends Properties
|
||||
*
|
||||
* @param float $blur
|
||||
*
|
||||
* @return GridLines
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowBlur($blur)
|
||||
{
|
||||
@@ -391,7 +391,7 @@ class GridLines extends Properties
|
||||
*
|
||||
* @param int $angle
|
||||
*
|
||||
* @return GridLines
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowAngle($angle)
|
||||
{
|
||||
@@ -407,7 +407,7 @@ class GridLines extends Properties
|
||||
*
|
||||
* @param float $distance
|
||||
*
|
||||
* @return GridLines
|
||||
* @return $this
|
||||
*/
|
||||
private function setShadowDistance($distance)
|
||||
{
|
||||
|
||||
@@ -153,7 +153,7 @@ class Layout
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setLayoutTarget($value)
|
||||
{
|
||||
@@ -177,7 +177,7 @@ class Layout
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setXMode($value)
|
||||
{
|
||||
@@ -201,7 +201,7 @@ class Layout
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setYMode($value)
|
||||
{
|
||||
@@ -225,7 +225,7 @@ class Layout
|
||||
*
|
||||
* @param float $value
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setXPosition($value)
|
||||
{
|
||||
@@ -249,7 +249,7 @@ class Layout
|
||||
*
|
||||
* @param float $value
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setYPosition($value)
|
||||
{
|
||||
@@ -273,7 +273,7 @@ class Layout
|
||||
*
|
||||
* @param float $value
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setWidth($value)
|
||||
{
|
||||
@@ -297,7 +297,7 @@ class Layout
|
||||
*
|
||||
* @param float $value
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeight($value)
|
||||
{
|
||||
@@ -322,7 +322,7 @@ class Layout
|
||||
*
|
||||
* @param bool $value Show legend key
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowLegendKey($value)
|
||||
{
|
||||
@@ -347,7 +347,7 @@ class Layout
|
||||
*
|
||||
* @param bool $value Show val
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowVal($value)
|
||||
{
|
||||
@@ -372,7 +372,7 @@ class Layout
|
||||
*
|
||||
* @param bool $value Show cat name
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowCatName($value)
|
||||
{
|
||||
@@ -397,7 +397,7 @@ class Layout
|
||||
*
|
||||
* @param bool $value Show series name
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowSerName($value)
|
||||
{
|
||||
@@ -422,7 +422,7 @@ class Layout
|
||||
*
|
||||
* @param bool $value Show percentage
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowPercent($value)
|
||||
{
|
||||
@@ -447,7 +447,7 @@ class Layout
|
||||
*
|
||||
* @param bool $value Show bubble size
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowBubbleSize($value)
|
||||
{
|
||||
@@ -472,7 +472,7 @@ class Layout
|
||||
*
|
||||
* @param bool $value Show leader lines
|
||||
*
|
||||
* @return Layout
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowLeaderLines($value)
|
||||
{
|
||||
|
||||
@@ -94,7 +94,7 @@ class PlotArea
|
||||
*
|
||||
* @param DataSeries[] $plotSeries
|
||||
*
|
||||
* @return PlotArea
|
||||
* @return $this
|
||||
*/
|
||||
public function setPlotSeries(array $plotSeries)
|
||||
{
|
||||
|
||||
@@ -442,7 +442,7 @@ class JpGraph implements IRenderer
|
||||
$seriesPlot->link->SetColor(self::$colourSet[self::$plotColour]);
|
||||
} elseif ($scatterStyle == 'smoothMarker') {
|
||||
$spline = new \Spline($dataValuesY, $dataValuesX);
|
||||
list($splineDataY, $splineDataX) = $spline->Get(count($dataValuesX) * self::$width / 20);
|
||||
[$splineDataY, $splineDataX] = $spline->Get(count($dataValuesX) * self::$width / 20);
|
||||
$lplot = new \LinePlot($splineDataX, $splineDataY);
|
||||
$lplot->SetColor(self::$colourSet[self::$plotColour]);
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ class Title
|
||||
*
|
||||
* @param string $caption
|
||||
*
|
||||
* @return Title
|
||||
* @return $this
|
||||
*/
|
||||
public function setCaption($caption)
|
||||
{
|
||||
|
||||
@@ -16,8 +16,6 @@ abstract class CellsFactory
|
||||
* */
|
||||
public static function getInstance(Worksheet $parent)
|
||||
{
|
||||
$instance = new Cells($parent, Settings::getCache());
|
||||
|
||||
return $instance;
|
||||
return new Cells($parent, Settings::getCache());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ class Comment implements IComparable
|
||||
*
|
||||
* @param string $author
|
||||
*
|
||||
* @return Comment
|
||||
* @return $this
|
||||
*/
|
||||
public function setAuthor($author)
|
||||
{
|
||||
@@ -120,7 +120,7 @@ class Comment implements IComparable
|
||||
*
|
||||
* @param RichText $pValue
|
||||
*
|
||||
* @return Comment
|
||||
* @return $this
|
||||
*/
|
||||
public function setText(RichText $pValue)
|
||||
{
|
||||
@@ -144,7 +144,7 @@ class Comment implements IComparable
|
||||
*
|
||||
* @param string $width
|
||||
*
|
||||
* @return Comment
|
||||
* @return $this
|
||||
*/
|
||||
public function setWidth($width)
|
||||
{
|
||||
@@ -168,7 +168,7 @@ class Comment implements IComparable
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return Comment
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeight($value)
|
||||
{
|
||||
@@ -192,7 +192,7 @@ class Comment implements IComparable
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return Comment
|
||||
* @return $this
|
||||
*/
|
||||
public function setMarginLeft($value)
|
||||
{
|
||||
@@ -216,7 +216,7 @@ class Comment implements IComparable
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return Comment
|
||||
* @return $this
|
||||
*/
|
||||
public function setMarginTop($value)
|
||||
{
|
||||
@@ -240,7 +240,7 @@ class Comment implements IComparable
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return Comment
|
||||
* @return $this
|
||||
*/
|
||||
public function setVisible($value)
|
||||
{
|
||||
@@ -264,7 +264,7 @@ class Comment implements IComparable
|
||||
*
|
||||
* @param string $alignment see Style\Alignment::HORIZONTAL_*
|
||||
*
|
||||
* @return Comment
|
||||
* @return $this
|
||||
*/
|
||||
public function setAlignment($alignment)
|
||||
{
|
||||
|
||||
@@ -122,7 +122,7 @@ class Properties
|
||||
*
|
||||
* @param string $creator
|
||||
*
|
||||
* @return Properties
|
||||
* @return $this
|
||||
*/
|
||||
public function setCreator($creator)
|
||||
{
|
||||
@@ -146,7 +146,7 @@ class Properties
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return Properties
|
||||
* @return $this
|
||||
*/
|
||||
public function setLastModifiedBy($pValue)
|
||||
{
|
||||
@@ -170,7 +170,7 @@ class Properties
|
||||
*
|
||||
* @param int|string $time
|
||||
*
|
||||
* @return Properties
|
||||
* @return $this
|
||||
*/
|
||||
public function setCreated($time)
|
||||
{
|
||||
@@ -204,7 +204,7 @@ class Properties
|
||||
*
|
||||
* @param int|string $time
|
||||
*
|
||||
* @return Properties
|
||||
* @return $this
|
||||
*/
|
||||
public function setModified($time)
|
||||
{
|
||||
@@ -238,7 +238,7 @@ class Properties
|
||||
*
|
||||
* @param string $title
|
||||
*
|
||||
* @return Properties
|
||||
* @return $this
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
@@ -262,7 +262,7 @@ class Properties
|
||||
*
|
||||
* @param string $description
|
||||
*
|
||||
* @return Properties
|
||||
* @return $this
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
@@ -286,7 +286,7 @@ class Properties
|
||||
*
|
||||
* @param string $subject
|
||||
*
|
||||
* @return Properties
|
||||
* @return $this
|
||||
*/
|
||||
public function setSubject($subject)
|
||||
{
|
||||
@@ -310,7 +310,7 @@ class Properties
|
||||
*
|
||||
* @param string $keywords
|
||||
*
|
||||
* @return Properties
|
||||
* @return $this
|
||||
*/
|
||||
public function setKeywords($keywords)
|
||||
{
|
||||
@@ -334,7 +334,7 @@ class Properties
|
||||
*
|
||||
* @param string $category
|
||||
*
|
||||
* @return Properties
|
||||
* @return $this
|
||||
*/
|
||||
public function setCategory($category)
|
||||
{
|
||||
@@ -358,7 +358,7 @@ class Properties
|
||||
*
|
||||
* @param string $company
|
||||
*
|
||||
* @return Properties
|
||||
* @return $this
|
||||
*/
|
||||
public function setCompany($company)
|
||||
{
|
||||
@@ -382,7 +382,7 @@ class Properties
|
||||
*
|
||||
* @param string $manager
|
||||
*
|
||||
* @return Properties
|
||||
* @return $this
|
||||
*/
|
||||
public function setManager($manager)
|
||||
{
|
||||
@@ -453,7 +453,7 @@ class Properties
|
||||
* 'd' : Date/Time
|
||||
* 'b' : Boolean
|
||||
*
|
||||
* @return Properties
|
||||
* @return $this
|
||||
*/
|
||||
public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null)
|
||||
{
|
||||
|
||||
@@ -75,7 +75,7 @@ class Security
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Security
|
||||
* @return $this
|
||||
*/
|
||||
public function setLockRevision($pValue)
|
||||
{
|
||||
@@ -99,7 +99,7 @@ class Security
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Security
|
||||
* @return $this
|
||||
*/
|
||||
public function setLockStructure($pValue)
|
||||
{
|
||||
@@ -123,7 +123,7 @@ class Security
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Security
|
||||
* @return $this
|
||||
*/
|
||||
public function setLockWindows($pValue)
|
||||
{
|
||||
@@ -148,7 +148,7 @@ class Security
|
||||
* @param string $pValue
|
||||
* @param bool $pAlreadyHashed If the password has already been hashed, set this to true
|
||||
*
|
||||
* @return Security
|
||||
* @return $this
|
||||
*/
|
||||
public function setRevisionsPassword($pValue, $pAlreadyHashed = false)
|
||||
{
|
||||
@@ -176,7 +176,7 @@ class Security
|
||||
* @param string $pValue
|
||||
* @param bool $pAlreadyHashed If the password has already been hashed, set this to true
|
||||
*
|
||||
* @return Security
|
||||
* @return $this
|
||||
*/
|
||||
public function setWorkbookPassword($pValue, $pAlreadyHashed = false)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Category;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class DocumentGenerator
|
||||
{
|
||||
/**
|
||||
* @param array[] $phpSpreadsheetFunctions
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function generateFunctionListByCategory(array $phpSpreadsheetFunctions): string
|
||||
{
|
||||
$result = "# Function list by category\n";
|
||||
foreach (self::getCategories() as $categoryConstant => $category) {
|
||||
$result .= "\n";
|
||||
$result .= "## {$categoryConstant}\n";
|
||||
$result .= "\n";
|
||||
$lengths = [20, 42];
|
||||
$result .= self::tableRow($lengths, ['Excel Function', 'PhpSpreadsheet Function']) . "\n";
|
||||
$result .= self::tableRow($lengths, null) . "\n";
|
||||
foreach ($phpSpreadsheetFunctions as $excelFunction => $functionInfo) {
|
||||
if ($category === $functionInfo['category']) {
|
||||
$phpFunction = self::getPhpSpreadsheetFunctionText($functionInfo['functionCall']);
|
||||
$result .= self::tableRow($lengths, [$excelFunction, $phpFunction]) . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ReflectionException
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function getCategories(): array
|
||||
{
|
||||
return (new ReflectionClass(Category::class))->getConstants();
|
||||
}
|
||||
|
||||
private static function tableRow(array $lengths, array $values = null): string
|
||||
{
|
||||
$result = '';
|
||||
foreach (array_map(null, $lengths, $values ?? []) as $i => [$length, $value]) {
|
||||
$pad = $value === null ? '-' : ' ';
|
||||
if ($i > 0) {
|
||||
$result .= '|' . $pad;
|
||||
}
|
||||
$result .= str_pad($value ?? '', $length, $pad);
|
||||
}
|
||||
|
||||
return rtrim($result, ' ');
|
||||
}
|
||||
|
||||
private static function getPhpSpreadsheetFunctionText($functionCall): string
|
||||
{
|
||||
if (is_string($functionCall)) {
|
||||
return $functionCall;
|
||||
}
|
||||
if ($functionCall === [Functions::class, 'DUMMY']) {
|
||||
return '**Not yet Implemented**';
|
||||
}
|
||||
if (is_array($functionCall)) {
|
||||
return "\\{$functionCall[0]}::{$functionCall[1]}";
|
||||
}
|
||||
|
||||
throw new UnexpectedValueException(
|
||||
'$functionCall is of type ' . gettype($functionCall) . '. string or array expected'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array[] $phpSpreadsheetFunctions
|
||||
*
|
||||
* @throws ReflectionException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function generateFunctionListByName(array $phpSpreadsheetFunctions): string
|
||||
{
|
||||
$categoryConstants = array_flip(self::getCategories());
|
||||
$result = "# Function list by name\n";
|
||||
$lastAlphabet = null;
|
||||
foreach ($phpSpreadsheetFunctions as $excelFunction => $functionInfo) {
|
||||
$lengths = [20, 31, 42];
|
||||
if ($lastAlphabet !== $excelFunction[0]) {
|
||||
$lastAlphabet = $excelFunction[0];
|
||||
$result .= "\n";
|
||||
$result .= "## {$lastAlphabet}\n";
|
||||
$result .= "\n";
|
||||
$result .= self::tableRow($lengths, ['Excel Function', 'Category', 'PhpSpreadsheet Function']) . "\n";
|
||||
$result .= self::tableRow($lengths, null) . "\n";
|
||||
}
|
||||
$category = $categoryConstants[$functionInfo['category']];
|
||||
$phpFunction = self::getPhpSpreadsheetFunctionText($functionInfo['functionCall']);
|
||||
$result .= self::tableRow($lengths, [$excelFunction, $category, $phpFunction]) . "\n";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -52,9 +52,8 @@ abstract class IOFactory
|
||||
|
||||
// Instantiate writer
|
||||
$className = self::$writers[$writerType];
|
||||
$writer = new $className($spreadsheet);
|
||||
|
||||
return $writer;
|
||||
return new $className($spreadsheet);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,9 +73,8 @@ abstract class IOFactory
|
||||
|
||||
// Instantiate reader
|
||||
$className = self::$readers[$readerType];
|
||||
$reader = new $className();
|
||||
|
||||
return $reader;
|
||||
return new $className();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -82,7 +82,7 @@ class NamedRange
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return NamedRange
|
||||
* @return $this
|
||||
*/
|
||||
public function setName($value)
|
||||
{
|
||||
@@ -123,7 +123,7 @@ class NamedRange
|
||||
*
|
||||
* @param Worksheet $value
|
||||
*
|
||||
* @return NamedRange
|
||||
* @return $this
|
||||
*/
|
||||
public function setWorksheet(Worksheet $value = null)
|
||||
{
|
||||
@@ -149,7 +149,7 @@ class NamedRange
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return NamedRange
|
||||
* @return $this
|
||||
*/
|
||||
public function setRange($value)
|
||||
{
|
||||
@@ -175,7 +175,7 @@ class NamedRange
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return NamedRange
|
||||
* @return $this
|
||||
*/
|
||||
public function setLocalOnly($value)
|
||||
{
|
||||
@@ -200,7 +200,7 @@ class NamedRange
|
||||
*
|
||||
* @param null|Worksheet $value
|
||||
*
|
||||
* @return NamedRange
|
||||
* @return $this
|
||||
*/
|
||||
public function setScope(Worksheet $value = null)
|
||||
{
|
||||
|
||||
@@ -70,7 +70,7 @@ class Csv extends BaseReader
|
||||
*
|
||||
* @param string $pValue Input encoding, eg: 'UTF-8'
|
||||
*
|
||||
* @return Csv
|
||||
* @return $this
|
||||
*/
|
||||
public function setInputEncoding($pValue)
|
||||
{
|
||||
@@ -175,9 +175,8 @@ class Csv extends BaseReader
|
||||
}
|
||||
}
|
||||
foreach ($potentialDelimiters as $delimiter) {
|
||||
$counts[$delimiter][] = isset($countLine[$delimiter])
|
||||
? $countLine[$delimiter]
|
||||
: 0;
|
||||
$counts[$delimiter][] = $countLine[$delimiter]
|
||||
?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,7 +415,7 @@ class Csv extends BaseReader
|
||||
*
|
||||
* @param string $delimiter Delimiter, eg: ','
|
||||
*
|
||||
* @return CSV
|
||||
* @return $this
|
||||
*/
|
||||
public function setDelimiter($delimiter)
|
||||
{
|
||||
@@ -440,7 +439,7 @@ class Csv extends BaseReader
|
||||
*
|
||||
* @param string $enclosure Enclosure, defaults to "
|
||||
*
|
||||
* @return CSV
|
||||
* @return $this
|
||||
*/
|
||||
public function setEnclosure($enclosure)
|
||||
{
|
||||
@@ -467,7 +466,7 @@ class Csv extends BaseReader
|
||||
*
|
||||
* @param int $pValue Sheet index
|
||||
*
|
||||
* @return CSV
|
||||
* @return $this
|
||||
*/
|
||||
public function setSheetIndex($pValue)
|
||||
{
|
||||
@@ -481,7 +480,7 @@ class Csv extends BaseReader
|
||||
*
|
||||
* @param bool $contiguous
|
||||
*
|
||||
* @return Csv
|
||||
* @return $this
|
||||
*/
|
||||
public function setContiguous($contiguous)
|
||||
{
|
||||
|
||||
@@ -267,7 +267,7 @@ class Gnumeric extends BaseReader
|
||||
|
||||
break;
|
||||
case 'user-defined':
|
||||
list(, $attrName) = explode(':', $attributes['name']);
|
||||
[, $attrName] = explode(':', $attributes['name']);
|
||||
switch ($attrName) {
|
||||
case 'publisher':
|
||||
$docProps->setCompany(trim($propertyValue));
|
||||
@@ -879,7 +879,7 @@ class Gnumeric extends BaseReader
|
||||
|
||||
private static function parseGnumericColour($gnmColour)
|
||||
{
|
||||
list($gnmR, $gnmG, $gnmB) = explode(':', $gnmColour);
|
||||
[$gnmR, $gnmG, $gnmB] = explode(':', $gnmColour);
|
||||
$gnmR = substr(str_pad($gnmR, 4, '0', STR_PAD_RIGHT), 0, 2);
|
||||
$gnmG = substr(str_pad($gnmG, 4, '0', STR_PAD_RIGHT), 0, 2);
|
||||
$gnmB = substr(str_pad($gnmB, 4, '0', STR_PAD_RIGHT), 0, 2);
|
||||
|
||||
@@ -223,7 +223,7 @@ class Html extends BaseReader
|
||||
*
|
||||
* @param string $pValue Input encoding, eg: 'ANSI'
|
||||
*
|
||||
* @return Html
|
||||
* @return $this
|
||||
*/
|
||||
public function setInputEncoding($pValue)
|
||||
{
|
||||
@@ -374,8 +374,9 @@ class Html extends BaseReader
|
||||
// no break
|
||||
case 'br':
|
||||
if ($this->tableLevel > 0) {
|
||||
// If we're inside a table, replace with a \n
|
||||
// If we're inside a table, replace with a \n and set the cell to wrap
|
||||
$cellContent .= "\n";
|
||||
$sheet->getStyle($column . $row)->getAlignment()->setWrapText(true);
|
||||
} else {
|
||||
// Otherwise flush our existing content and move the row cursor on
|
||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||
@@ -489,22 +490,22 @@ class Html extends BaseReader
|
||||
case 'td':
|
||||
$this->processDomElement($child, $sheet, $row, $column, $cellContent);
|
||||
|
||||
// apply inline style
|
||||
$this->applyInlineStyle($sheet, $row, $column, $attributeArray);
|
||||
|
||||
while (isset($this->rowspan[$column . $row])) {
|
||||
++$column;
|
||||
}
|
||||
|
||||
// apply inline style
|
||||
$this->applyInlineStyle($sheet, $row, $column, $attributeArray);
|
||||
|
||||
$this->flushCell($sheet, $column, $row, $cellContent);
|
||||
|
||||
if (isset($attributeArray['rowspan'], $attributeArray['colspan'])) {
|
||||
//create merging rowspan and colspan
|
||||
$columnTo = $column;
|
||||
for ($i = 0; $i < $attributeArray['colspan'] - 1; ++$i) {
|
||||
for ($i = 0; $i < (int) $attributeArray['colspan'] - 1; ++$i) {
|
||||
++$columnTo;
|
||||
}
|
||||
$range = $column . $row . ':' . $columnTo . ($row + $attributeArray['rowspan'] - 1);
|
||||
$range = $column . $row . ':' . $columnTo . ($row + (int) $attributeArray['rowspan'] - 1);
|
||||
foreach (Coordinate::extractAllCellReferencesInRange($range) as $value) {
|
||||
$this->rowspan[$value] = true;
|
||||
}
|
||||
@@ -512,7 +513,7 @@ class Html extends BaseReader
|
||||
$column = $columnTo;
|
||||
} elseif (isset($attributeArray['rowspan'])) {
|
||||
//create merging rowspan
|
||||
$range = $column . $row . ':' . $column . ($row + $attributeArray['rowspan'] - 1);
|
||||
$range = $column . $row . ':' . $column . ($row + (int) $attributeArray['rowspan'] - 1);
|
||||
foreach (Coordinate::extractAllCellReferencesInRange($range) as $value) {
|
||||
$this->rowspan[$value] = true;
|
||||
}
|
||||
@@ -520,7 +521,7 @@ class Html extends BaseReader
|
||||
} elseif (isset($attributeArray['colspan'])) {
|
||||
//create merging colspan
|
||||
$columnTo = $column;
|
||||
for ($i = 0; $i < $attributeArray['colspan'] - 1; ++$i) {
|
||||
for ($i = 0; $i < (int) $attributeArray['colspan'] - 1; ++$i) {
|
||||
++$columnTo;
|
||||
}
|
||||
$sheet->mergeCells($column . $row . ':' . $columnTo . $row);
|
||||
@@ -591,28 +592,63 @@ class Html extends BaseReader
|
||||
throw new Exception($pFilename . ' is an Invalid HTML file.');
|
||||
}
|
||||
|
||||
// Create new sheet
|
||||
while ($spreadsheet->getSheetCount() <= $this->sheetIndex) {
|
||||
$spreadsheet->createSheet();
|
||||
}
|
||||
$spreadsheet->setActiveSheetIndex($this->sheetIndex);
|
||||
|
||||
// Create a new DOM object
|
||||
// Create a new DOM object
|
||||
$dom = new DOMDocument();
|
||||
// Reload the HTML file into the DOM object
|
||||
// Reload the HTML file into the DOM object
|
||||
$loaded = $dom->loadHTML(mb_convert_encoding($this->securityScanner->scanFile($pFilename), 'HTML-ENTITIES', 'UTF-8'));
|
||||
if ($loaded === false) {
|
||||
throw new Exception('Failed to load ' . $pFilename . ' as a DOM Document');
|
||||
}
|
||||
|
||||
// Discard white space
|
||||
$dom->preserveWhiteSpace = false;
|
||||
return $this->loadDocument($dom, $spreadsheet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spreadsheet from content.
|
||||
*
|
||||
* @param string $content
|
||||
* @param null|Spreadsheet $spreadsheet
|
||||
*
|
||||
* @return Spreadsheet
|
||||
*/
|
||||
public function loadFromString($content, ?Spreadsheet $spreadsheet = null): Spreadsheet
|
||||
{
|
||||
// Create a new DOM object
|
||||
$dom = new DOMDocument();
|
||||
// Reload the HTML file into the DOM object
|
||||
$loaded = $dom->loadHTML(mb_convert_encoding($this->securityScanner->scan($content), 'HTML-ENTITIES', 'UTF-8'));
|
||||
if ($loaded === false) {
|
||||
throw new Exception('Failed to load content as a DOM Document');
|
||||
}
|
||||
|
||||
return $this->loadDocument($dom, $spreadsheet ?? new Spreadsheet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads PhpSpreadsheet from DOMDocument into PhpSpreadsheet instance.
|
||||
*
|
||||
* @param DOMDocument $document
|
||||
* @param Spreadsheet $spreadsheet
|
||||
*
|
||||
* @throws \PhpOffice\PhpSpreadsheet\Exception
|
||||
*
|
||||
* @return Spreadsheet
|
||||
*/
|
||||
private function loadDocument(DOMDocument $document, Spreadsheet $spreadsheet): Spreadsheet
|
||||
{
|
||||
while ($spreadsheet->getSheetCount() <= $this->sheetIndex) {
|
||||
$spreadsheet->createSheet();
|
||||
}
|
||||
$spreadsheet->setActiveSheetIndex($this->sheetIndex);
|
||||
|
||||
// Discard white space
|
||||
$document->preserveWhiteSpace = false;
|
||||
|
||||
$row = 0;
|
||||
$column = 'A';
|
||||
$content = '';
|
||||
$this->rowspan = [];
|
||||
$this->processDomElement($dom, $spreadsheet->getActiveSheet(), $row, $column, $content);
|
||||
$this->processDomElement($document, $spreadsheet->getActiveSheet(), $row, $column, $content);
|
||||
|
||||
// Return
|
||||
return $spreadsheet;
|
||||
@@ -633,7 +669,7 @@ class Html extends BaseReader
|
||||
*
|
||||
* @param int $pValue Sheet index
|
||||
*
|
||||
* @return HTML
|
||||
* @return $this
|
||||
*/
|
||||
public function setSheetIndex($pValue)
|
||||
{
|
||||
@@ -919,7 +955,7 @@ class Html extends BaseReader
|
||||
*/
|
||||
private function setBorderStyle(Style $cellStyle, $styleValue, $type)
|
||||
{
|
||||
list(, $borderStyle, $color) = explode(' ', $styleValue);
|
||||
[, $borderStyle, $color] = explode(' ', $styleValue);
|
||||
|
||||
$cellStyle->applyFromArray([
|
||||
'borders' => [
|
||||
|
||||
@@ -490,7 +490,7 @@ class Ods extends BaseReader
|
||||
|
||||
$dateObj = new DateTime($value, $GMT);
|
||||
$dateObj->setTimeZone($timezoneObj);
|
||||
list($year, $month, $day, $hour, $minute, $second) = explode(
|
||||
[$year, $month, $day, $hour, $minute, $second] = explode(
|
||||
' ',
|
||||
$dateObj->format('Y m d H i s')
|
||||
);
|
||||
|
||||
@@ -19,12 +19,11 @@ class Properties
|
||||
$docProps = $this->spreadsheet->getProperties();
|
||||
$officeProperty = $xml->children($namespacesMeta['office']);
|
||||
foreach ($officeProperty as $officePropertyData) {
|
||||
/** @var \SimpleXMLElement $officePropertyData */
|
||||
$officePropertiesDC = (object) [];
|
||||
// @var \SimpleXMLElement $officePropertyData
|
||||
if (isset($namespacesMeta['dc'])) {
|
||||
$officePropertiesDC = $officePropertyData->children($namespacesMeta['dc']);
|
||||
$this->setCoreProperties($docProps, $officePropertiesDC);
|
||||
}
|
||||
$this->setCoreProperties($docProps, $officePropertiesDC);
|
||||
|
||||
$officePropertyMeta = (object) [];
|
||||
if (isset($namespacesMeta['dc'])) {
|
||||
|
||||
@@ -83,7 +83,7 @@ class Slk extends BaseReader
|
||||
*
|
||||
* @param string $pValue Input encoding, eg: 'ANSI'
|
||||
*
|
||||
* @return Slk
|
||||
* @return $this
|
||||
*/
|
||||
public function setInputEncoding($pValue)
|
||||
{
|
||||
@@ -384,7 +384,7 @@ class Slk extends BaseReader
|
||||
|
||||
break;
|
||||
case 'W':
|
||||
list($startCol, $endCol, $columnWidth) = explode(' ', substr($rowDatum, 1));
|
||||
[$startCol, $endCol, $columnWidth] = explode(' ', substr($rowDatum, 1));
|
||||
|
||||
break;
|
||||
case 'S':
|
||||
@@ -485,7 +485,7 @@ class Slk extends BaseReader
|
||||
*
|
||||
* @param int $pValue Sheet index
|
||||
*
|
||||
* @return Slk
|
||||
* @return $this
|
||||
*/
|
||||
public function setSheetIndex($pValue)
|
||||
{
|
||||
|
||||
@@ -1089,8 +1089,8 @@ class Xls extends BaseReader
|
||||
}
|
||||
|
||||
// calculate the width and height of the shape
|
||||
list($startColumn, $startRow) = Coordinate::coordinateFromString($spContainer->getStartCoordinates());
|
||||
list($endColumn, $endRow) = Coordinate::coordinateFromString($spContainer->getEndCoordinates());
|
||||
[$startColumn, $startRow] = Coordinate::coordinateFromString($spContainer->getStartCoordinates());
|
||||
[$endColumn, $endRow] = Coordinate::coordinateFromString($spContainer->getEndCoordinates());
|
||||
|
||||
$startOffsetX = $spContainer->getStartOffsetX();
|
||||
$startOffsetY = $spContainer->getStartOffsetY();
|
||||
@@ -1175,7 +1175,7 @@ class Xls extends BaseReader
|
||||
// treat SHAREDFMLA records
|
||||
if ($this->version == self::XLS_BIFF8) {
|
||||
foreach ($this->sharedFormulaParts as $cell => $baseCell) {
|
||||
list($column, $row) = Coordinate::coordinateFromString($cell);
|
||||
[$column, $row] = Coordinate::coordinateFromString($cell);
|
||||
if (($this->getReadFilter() !== null) && $this->getReadFilter()->readCell($column, $row, $this->phpSheet->getTitle())) {
|
||||
$formula = $this->getFormulaFromStructure($this->sharedFormulas[$baseCell], $cell);
|
||||
$this->phpSheet->getCell($cell)->setValueExplicit('=' . $formula, DataType::TYPE_FORMULA);
|
||||
@@ -1251,8 +1251,8 @@ class Xls extends BaseReader
|
||||
|
||||
$coordinateStrings = explode(':', $extractedRange);
|
||||
if (count($coordinateStrings) == 2) {
|
||||
list($firstColumn, $firstRow) = Coordinate::coordinateFromString($coordinateStrings[0]);
|
||||
list($lastColumn, $lastRow) = Coordinate::coordinateFromString($coordinateStrings[1]);
|
||||
[$firstColumn, $firstRow] = Coordinate::coordinateFromString($coordinateStrings[0]);
|
||||
[$lastColumn, $lastRow] = Coordinate::coordinateFromString($coordinateStrings[1]);
|
||||
|
||||
if ($firstColumn == 'A' and $lastColumn == 'IV') {
|
||||
// then we have repeating rows
|
||||
@@ -3825,7 +3825,7 @@ class Xls extends BaseReader
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->readDataOnly && !$emptyCell) {
|
||||
if (!$this->readDataOnly && !$emptyCell && isset($this->mapCellXfIndex[$xfIndex])) {
|
||||
// add style information
|
||||
$cell->setXfIndex($this->mapCellXfIndex[$xfIndex]);
|
||||
}
|
||||
@@ -5279,12 +5279,10 @@ class Xls extends BaseReader
|
||||
$nextIdentifier = self::getUInt2d($this->data, $this->pos);
|
||||
} while ($nextIdentifier == self::XLS_TYPE_CONTINUE);
|
||||
|
||||
$splicedData = [
|
||||
return [
|
||||
'recordData' => $data,
|
||||
'spliceOffsets' => $spliceOffsets,
|
||||
];
|
||||
|
||||
return $splicedData;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5355,12 +5353,12 @@ class Xls extends BaseReader
|
||||
$formulaStrings = [];
|
||||
foreach ($tokens as $token) {
|
||||
// initialize spaces
|
||||
$space0 = isset($space0) ? $space0 : ''; // spaces before next token, not tParen
|
||||
$space1 = isset($space1) ? $space1 : ''; // carriage returns before next token, not tParen
|
||||
$space2 = isset($space2) ? $space2 : ''; // spaces before opening parenthesis
|
||||
$space3 = isset($space3) ? $space3 : ''; // carriage returns before opening parenthesis
|
||||
$space4 = isset($space4) ? $space4 : ''; // spaces before closing parenthesis
|
||||
$space5 = isset($space5) ? $space5 : ''; // carriage returns before closing parenthesis
|
||||
$space0 = $space0 ?? ''; // spaces before next token, not tParen
|
||||
$space1 = $space1 ?? ''; // carriage returns before next token, not tParen
|
||||
$space2 = $space2 ?? ''; // spaces before opening parenthesis
|
||||
$space3 = $space3 ?? ''; // carriage returns before opening parenthesis
|
||||
$space4 = $space4 ?? ''; // spaces before closing parenthesis
|
||||
$space5 = $space5 ?? ''; // carriage returns before closing parenthesis
|
||||
|
||||
switch ($token['name']) {
|
||||
case 'tAdd': // addition
|
||||
@@ -7145,7 +7143,7 @@ class Xls extends BaseReader
|
||||
*/
|
||||
private function readBIFF8CellAddressB($cellAddressStructure, $baseCell = 'A1')
|
||||
{
|
||||
list($baseCol, $baseRow) = Coordinate::coordinateFromString($baseCell);
|
||||
[$baseCol, $baseRow] = Coordinate::coordinateFromString($baseCell);
|
||||
$baseCol = Coordinate::columnIndexFromString($baseCol) - 1;
|
||||
|
||||
// offset: 0; size: 2; index to row (0... 65535) (or offset (-32768... 32767))
|
||||
@@ -7328,7 +7326,7 @@ class Xls extends BaseReader
|
||||
*/
|
||||
private function readBIFF8CellRangeAddressB($subData, $baseCell = 'A1')
|
||||
{
|
||||
list($baseCol, $baseRow) = Coordinate::coordinateFromString($baseCell);
|
||||
[$baseCol, $baseRow] = Coordinate::coordinateFromString($baseCell);
|
||||
$baseCol = Coordinate::columnIndexFromString($baseCol) - 1;
|
||||
|
||||
// TODO: if cell range is just a single cell, should this funciton
|
||||
|
||||
@@ -77,34 +77,17 @@ class Xlsx extends BaseReader
|
||||
{
|
||||
File::assertFile($pFilename);
|
||||
|
||||
$xl = false;
|
||||
// Load file
|
||||
$result = false;
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($pFilename) === true) {
|
||||
// check if it is an OOXML archive
|
||||
$rels = simplexml_load_string(
|
||||
$this->securityScanner->scan(
|
||||
$this->getFromZipArchive($zip, '_rels/.rels')
|
||||
),
|
||||
'SimpleXMLElement',
|
||||
Settings::getLibXmlLoaderOptions()
|
||||
);
|
||||
if ($rels !== false) {
|
||||
foreach ($rels->Relationship as $rel) {
|
||||
switch ($rel['Type']) {
|
||||
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
|
||||
if (basename($rel['Target']) == 'workbook.xml') {
|
||||
$xl = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($zip->open($pFilename) === true) {
|
||||
$workbookBasename = $this->getWorkbookBaseName($zip);
|
||||
$result = !empty($workbookBasename);
|
||||
|
||||
$zip->close();
|
||||
}
|
||||
|
||||
return $xl;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -357,8 +340,9 @@ class Xlsx extends BaseReader
|
||||
|
||||
// Read the theme first, because we need the colour scheme when reading the styles
|
||||
//~ http://schemas.openxmlformats.org/package/2006/relationships"
|
||||
$workbookBasename = $this->getWorkbookBaseName($zip);
|
||||
$wbRels = simplexml_load_string(
|
||||
$this->securityScanner->scan($this->getFromZipArchive($zip, 'xl/_rels/workbook.xml.rels')),
|
||||
$this->securityScanner->scan($this->getFromZipArchive($zip, "xl/_rels/${workbookBasename}.rels")),
|
||||
'SimpleXMLElement',
|
||||
Settings::getLibXmlLoaderOptions()
|
||||
);
|
||||
@@ -445,18 +429,20 @@ class Xlsx extends BaseReader
|
||||
|
||||
$sharedStrings = [];
|
||||
$xpath = self::getArrayItem($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']"));
|
||||
//~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
||||
$xmlStrings = simplexml_load_string(
|
||||
$this->securityScanner->scan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")),
|
||||
'SimpleXMLElement',
|
||||
Settings::getLibXmlLoaderOptions()
|
||||
);
|
||||
if (isset($xmlStrings, $xmlStrings->si)) {
|
||||
foreach ($xmlStrings->si as $val) {
|
||||
if (isset($val->t)) {
|
||||
$sharedStrings[] = StringHelper::controlCharacterOOXML2PHP((string) $val->t);
|
||||
} elseif (isset($val->r)) {
|
||||
$sharedStrings[] = $this->parseRichText($val);
|
||||
if ($xpath) {
|
||||
//~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
||||
$xmlStrings = simplexml_load_string(
|
||||
$this->securityScanner->scan($this->getFromZipArchive($zip, "$dir/$xpath[Target]")),
|
||||
'SimpleXMLElement',
|
||||
Settings::getLibXmlLoaderOptions()
|
||||
);
|
||||
if (isset($xmlStrings, $xmlStrings->si)) {
|
||||
foreach ($xmlStrings->si as $val) {
|
||||
if (isset($val->t)) {
|
||||
$sharedStrings[] = StringHelper::controlCharacterOOXML2PHP((string) $val->t);
|
||||
} elseif (isset($val->r)) {
|
||||
$sharedStrings[] = $this->parseRichText($val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -743,15 +729,6 @@ class Xlsx extends BaseReader
|
||||
|
||||
// read empty cells or the cells are not empty
|
||||
if ($this->readEmptyCells || ($value !== null && $value !== '')) {
|
||||
// Check for numeric values
|
||||
if (is_numeric($value) && $cellDataType != 's') {
|
||||
if ($value == (int) $value) {
|
||||
$value = (int) $value;
|
||||
} elseif ($value == (float) $value) {
|
||||
$value = (float) $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Rich text?
|
||||
if ($value instanceof RichText && $this->readDataOnly) {
|
||||
$value = $value->getPlainText();
|
||||
@@ -1352,7 +1329,7 @@ class Xlsx extends BaseReader
|
||||
$rangeSets = preg_split("/('?(?:.*?)'?(?:![A-Z0-9]+:[A-Z0-9]+)),?/", $extractedRange, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
$newRangeSets = [];
|
||||
foreach ($rangeSets as $rangeSet) {
|
||||
list($sheetName, $rangeSet) = Worksheet::extractSheetTitle($rangeSet, true);
|
||||
[$sheetName, $rangeSet] = Worksheet::extractSheetTitle($rangeSet, true);
|
||||
if (strpos($rangeSet, ':') === false) {
|
||||
$rangeSet = $rangeSet . ':' . $rangeSet;
|
||||
}
|
||||
@@ -1426,7 +1403,7 @@ class Xlsx extends BaseReader
|
||||
$locatedSheet = $excel->getSheetByName($extractedSheetName);
|
||||
|
||||
// Modify range
|
||||
list($worksheetName, $extractedRange) = Worksheet::extractSheetTitle($extractedRange, true);
|
||||
[$worksheetName, $extractedRange] = Worksheet::extractSheetTitle($extractedRange, true);
|
||||
}
|
||||
|
||||
if ($locatedSheet !== null) {
|
||||
@@ -1437,7 +1414,7 @@ class Xlsx extends BaseReader
|
||||
}
|
||||
}
|
||||
|
||||
if ((!$this->readDataOnly) || (!empty($this->loadSheetsOnly))) {
|
||||
if ((!$this->readDataOnly || !empty($this->loadSheetsOnly)) && isset($xmlWorkbook->bookViews->workbookView)) {
|
||||
$workbookView = $xmlWorkbook->bookViews->workbookView;
|
||||
|
||||
// active sheet index
|
||||
@@ -1643,8 +1620,6 @@ class Xlsx extends BaseReader
|
||||
$docStyle->getFill()->setFillType($patternType);
|
||||
if ($style->fill->patternFill->fgColor) {
|
||||
$docStyle->getFill()->getStartColor()->setARGB(self::readColor($style->fill->patternFill->fgColor, true));
|
||||
} else {
|
||||
$docStyle->getFill()->getStartColor()->setARGB('FF000000');
|
||||
}
|
||||
if ($style->fill->patternFill->bgColor) {
|
||||
$docStyle->getFill()->getEndColor()->setARGB(self::readColor($style->fill->patternFill->bgColor, true));
|
||||
@@ -1841,7 +1816,7 @@ class Xlsx extends BaseReader
|
||||
|
||||
private static function getArrayItem($array, $key = 0)
|
||||
{
|
||||
return isset($array[$key]) ? $array[$key] : null;
|
||||
return $array[$key] ?? null;
|
||||
}
|
||||
|
||||
private static function dirAdd($base, $add)
|
||||
@@ -1851,7 +1826,7 @@ class Xlsx extends BaseReader
|
||||
|
||||
private static function toCSSArray($style)
|
||||
{
|
||||
$style = trim(str_replace(["\r", "\n"], '', $style), ';');
|
||||
$style = self::stripWhiteSpaceFromStyleString($style);
|
||||
|
||||
$temp = explode(';', $style);
|
||||
$style = [];
|
||||
@@ -1880,6 +1855,11 @@ class Xlsx extends BaseReader
|
||||
return $style;
|
||||
}
|
||||
|
||||
public static function stripWhiteSpaceFromStyleString($string)
|
||||
{
|
||||
return trim(str_replace(["\r", "\n", ' '], '', $string), ';');
|
||||
}
|
||||
|
||||
private static function boolean($value)
|
||||
{
|
||||
if (is_object($value)) {
|
||||
@@ -2026,4 +2006,38 @@ class Xlsx extends BaseReader
|
||||
|
||||
return (bool) $xsdBoolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ZipArchive $zip Opened zip archive
|
||||
*
|
||||
* @return string basename of the used excel workbook
|
||||
*/
|
||||
private function getWorkbookBaseName(ZipArchive $zip)
|
||||
{
|
||||
$workbookBasename = '';
|
||||
|
||||
// check if it is an OOXML archive
|
||||
$rels = simplexml_load_string(
|
||||
$this->securityScanner->scan(
|
||||
$this->getFromZipArchive($zip, '_rels/.rels')
|
||||
),
|
||||
'SimpleXMLElement',
|
||||
Settings::getLibXmlLoaderOptions()
|
||||
);
|
||||
if ($rels !== false) {
|
||||
foreach ($rels->Relationship as $rel) {
|
||||
switch ($rel['Type']) {
|
||||
case 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument':
|
||||
$basename = basename($rel['Target']);
|
||||
if (preg_match('/workbook.*\.xml/', $basename)) {
|
||||
$workbookBasename = $basename;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $workbookBasename;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ class AutoFilter
|
||||
|
||||
public function load()
|
||||
{
|
||||
$autoFilterRange = (string) $this->worksheetXml->autoFilter['ref'];
|
||||
// Remove all "$" in the auto filter range
|
||||
$autoFilterRange = preg_replace('/\$/', '', $this->worksheetXml->autoFilter['ref']);
|
||||
if (strpos($autoFilterRange, ':') !== false) {
|
||||
$this->readAutoFilter($autoFilterRange, $this->worksheetXml);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ class ConditionalStyles
|
||||
if (((string) $cfRule['type'] == Conditional::CONDITION_NONE
|
||||
|| (string) $cfRule['type'] == Conditional::CONDITION_CELLIS
|
||||
|| (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSTEXT
|
||||
|| (string) $cfRule['type'] == Conditional::CONDITION_CONTAINSBLANKS
|
||||
|| (string) $cfRule['type'] == Conditional::CONDITION_NOTCONTAINSBLANKS
|
||||
|| (string) $cfRule['type'] == Conditional::CONDITION_EXPRESSION)
|
||||
&& isset($this->dxfs[(int) ($cfRule['dxfId'])])) {
|
||||
$conditionals[(string) $conditional['sqref']][(int) ($cfRule['priority'])] = $cfRule;
|
||||
|
||||
@@ -86,6 +86,6 @@ class Properties
|
||||
|
||||
private static function getArrayItem(array $array, $key = 0)
|
||||
{
|
||||
return isset($array[$key]) ? $array[$key] : null;
|
||||
return $array[$key] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ class SheetViews extends BaseParserClass
|
||||
$this->gridLines();
|
||||
$this->headers();
|
||||
$this->direction();
|
||||
$this->showZeros();
|
||||
|
||||
if (isset($this->sheetViewXml->pane)) {
|
||||
$this->pane();
|
||||
@@ -92,6 +93,15 @@ class SheetViews extends BaseParserClass
|
||||
}
|
||||
}
|
||||
|
||||
private function showZeros()
|
||||
{
|
||||
if (isset($this->sheetViewXml['showZeros'])) {
|
||||
$this->worksheet->getSheetView()->setShowZeros(
|
||||
self::boolean((string) $this->sheetViewXml['showZeros'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function pane()
|
||||
{
|
||||
$xSplit = 0;
|
||||
|
||||
@@ -8,6 +8,7 @@ use PhpOffice\PhpSpreadsheet\Style\Borders;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Color;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Font;
|
||||
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Protection;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Style;
|
||||
|
||||
@@ -71,6 +72,17 @@ class Styles extends BaseParserClass
|
||||
}
|
||||
}
|
||||
|
||||
private static function readNumberFormat(NumberFormat $numfmtStyle, \SimpleXMLElement $numfmtStyleXml)
|
||||
{
|
||||
if ($numfmtStyleXml->count() === 0) {
|
||||
return;
|
||||
}
|
||||
$numfmt = $numfmtStyleXml->attributes();
|
||||
if ($numfmt->count() > 0 && isset($numfmt['formatCode'])) {
|
||||
$numfmtStyle->setFormatCode((string) $numfmt['formatCode']);
|
||||
}
|
||||
}
|
||||
|
||||
private static function readFillStyle(Fill $fillStyle, \SimpleXMLElement $fillStyleXml)
|
||||
{
|
||||
if ($fillStyleXml->gradientFill) {
|
||||
@@ -149,7 +161,11 @@ class Styles extends BaseParserClass
|
||||
|
||||
private function readStyle(Style $docStyle, $style)
|
||||
{
|
||||
$docStyle->getNumberFormat()->setFormatCode($style->numFmt);
|
||||
if ($style->numFmt instanceof \SimpleXMLElement) {
|
||||
self::readNumberFormat($docStyle->getNumberFormat(), $style->numFmt);
|
||||
} else {
|
||||
$docStyle->getNumberFormat()->setFormatCode($style->numFmt);
|
||||
}
|
||||
|
||||
if (isset($style->font)) {
|
||||
self::readFontStyle($docStyle->getFont(), $style->font);
|
||||
@@ -163,7 +179,7 @@ class Styles extends BaseParserClass
|
||||
self::readBorderStyle($docStyle->getBorders(), $style->border);
|
||||
}
|
||||
|
||||
if (isset($style->alignment)) {
|
||||
if (isset($style->alignment->alignment)) {
|
||||
self::readAlignmentStyle($docStyle->getAlignment(), $style->alignment);
|
||||
}
|
||||
|
||||
@@ -260,6 +276,6 @@ class Styles extends BaseParserClass
|
||||
|
||||
private static function getArrayItem($array, $key = 0)
|
||||
{
|
||||
return isset($array[$key]) ? $array[$key] : null;
|
||||
return $array[$key] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,9 +285,8 @@ class Xml extends BaseReader
|
||||
{
|
||||
$pixels = ($widthUnits / 256) * 7;
|
||||
$offsetWidthUnits = $widthUnits % 256;
|
||||
$pixels += round($offsetWidthUnits / (256 / 7));
|
||||
|
||||
return $pixels;
|
||||
return $pixels + round($offsetWidthUnits / (256 / 7));
|
||||
}
|
||||
|
||||
protected static function hex2str($hex)
|
||||
|
||||
@@ -82,11 +82,8 @@ class ReferenceHelper
|
||||
*/
|
||||
public static function cellSort($a, $b)
|
||||
{
|
||||
// TODO Scrutinizer doesn't like sscanf($a, '%[A-Z]%d', $ac, $ar), and we can't use short list() syntax
|
||||
// [$ac, $ar] = sscanf($a, '%[A-Z]%d') while retaining PHP 5.6 support.
|
||||
// Switch when we drop support for 5.6
|
||||
list($ac, $ar) = sscanf($a, '%[A-Z]%d');
|
||||
list($bc, $br) = sscanf($b, '%[A-Z]%d');
|
||||
[$ac, $ar] = sscanf($a, '%[A-Z]%d');
|
||||
[$bc, $br] = sscanf($b, '%[A-Z]%d');
|
||||
|
||||
if ($ar === $br) {
|
||||
return strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc);
|
||||
@@ -106,11 +103,8 @@ class ReferenceHelper
|
||||
*/
|
||||
public static function cellReverseSort($a, $b)
|
||||
{
|
||||
// TODO Scrutinizer doesn't like sscanf($a, '%[A-Z]%d', $ac, $ar), and we can't use short list() syntax
|
||||
// [$ac, $ar] = sscanf($a, '%[A-Z]%d') while retaining PHP 5.6 support.
|
||||
// Switch when we drop support for 5.6
|
||||
list($ac, $ar) = sscanf($a, '%[A-Z]%d');
|
||||
list($bc, $br) = sscanf($b, '%[A-Z]%d');
|
||||
[$ac, $ar] = sscanf($a, '%[A-Z]%d');
|
||||
[$bc, $br] = sscanf($b, '%[A-Z]%d');
|
||||
|
||||
if ($ar === $br) {
|
||||
return 1 - strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc);
|
||||
@@ -132,7 +126,7 @@ class ReferenceHelper
|
||||
*/
|
||||
private static function cellAddressInDeleteRange($cellAddress, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)
|
||||
{
|
||||
list($cellColumn, $cellRow) = Coordinate::coordinateFromString($cellAddress);
|
||||
[$cellColumn, $cellRow] = Coordinate::coordinateFromString($cellAddress);
|
||||
$cellColumnIndex = Coordinate::columnIndexFromString($cellColumn);
|
||||
// Is cell within the range of rows/columns if we're deleting
|
||||
if ($pNumRows < 0 &&
|
||||
@@ -319,7 +313,7 @@ class ReferenceHelper
|
||||
if (!empty($aColumnDimensions)) {
|
||||
foreach ($aColumnDimensions as $objColumnDimension) {
|
||||
$newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows);
|
||||
list($newReference) = Coordinate::coordinateFromString($newReference);
|
||||
[$newReference] = Coordinate::coordinateFromString($newReference);
|
||||
if ($objColumnDimension->getColumnIndex() != $newReference) {
|
||||
$objColumnDimension->setColumnIndex($newReference);
|
||||
}
|
||||
@@ -344,7 +338,7 @@ class ReferenceHelper
|
||||
if (!empty($aRowDimensions)) {
|
||||
foreach ($aRowDimensions as $objRowDimension) {
|
||||
$newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows);
|
||||
list(, $newReference) = Coordinate::coordinateFromString($newReference);
|
||||
[, $newReference] = Coordinate::coordinateFromString($newReference);
|
||||
if ($objRowDimension->getRowIndex() != $newReference) {
|
||||
$objRowDimension->setRowIndex($newReference);
|
||||
}
|
||||
@@ -378,7 +372,7 @@ class ReferenceHelper
|
||||
$allCoordinates = $pSheet->getCoordinates();
|
||||
|
||||
// Get coordinate of $pBefore
|
||||
list($beforeColumn, $beforeRow) = Coordinate::coordinateFromString($pBefore);
|
||||
[$beforeColumn, $beforeRow] = Coordinate::coordinateFromString($pBefore);
|
||||
$beforeColumnIndex = Coordinate::columnIndexFromString($beforeColumn);
|
||||
|
||||
// Clear cells if we are removing columns or rows
|
||||
@@ -539,7 +533,7 @@ class ReferenceHelper
|
||||
$row = 0;
|
||||
sscanf($pBefore, '%[A-Z]%d', $column, $row);
|
||||
$columnIndex = Coordinate::columnIndexFromString($column);
|
||||
list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($autoFilterRange);
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($autoFilterRange);
|
||||
if ($columnIndex <= $rangeEnd[0]) {
|
||||
if ($pNumCols < 0) {
|
||||
// If we're actually deleting any columns that fall within the autofilter range,
|
||||
@@ -707,7 +701,7 @@ class ReferenceHelper
|
||||
if (($match[2] == '') || (trim($match[2], "'") == $sheetName)) {
|
||||
$toString = ($match[2] > '') ? $match[2] . '!' : '';
|
||||
$toString .= $modified3 . ':' . $modified4;
|
||||
list($column, $row) = Coordinate::coordinateFromString($match[3]);
|
||||
[$column, $row] = Coordinate::coordinateFromString($match[3]);
|
||||
// Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
|
||||
$column = Coordinate::columnIndexFromString(trim($column, '$')) + 100000;
|
||||
$row = trim($row, '$') + 10000000;
|
||||
@@ -733,7 +727,7 @@ class ReferenceHelper
|
||||
if (($match[2] == '') || (trim($match[2], "'") == $sheetName)) {
|
||||
$toString = ($match[2] > '') ? $match[2] . '!' : '';
|
||||
$toString .= $modified3;
|
||||
list($column, $row) = Coordinate::coordinateFromString($match[3]);
|
||||
[$column, $row] = Coordinate::coordinateFromString($match[3]);
|
||||
// Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more
|
||||
$column = Coordinate::columnIndexFromString(trim($column, '$')) + 100000;
|
||||
$row = trim($row, '$') + 10000000;
|
||||
@@ -881,10 +875,10 @@ class ReferenceHelper
|
||||
}
|
||||
|
||||
// Get coordinate of $pBefore
|
||||
list($beforeColumn, $beforeRow) = Coordinate::coordinateFromString($pBefore);
|
||||
[$beforeColumn, $beforeRow] = Coordinate::coordinateFromString($pBefore);
|
||||
|
||||
// Get coordinate of $pCellReference
|
||||
list($newColumn, $newRow) = Coordinate::coordinateFromString($pCellReference);
|
||||
[$newColumn, $newRow] = Coordinate::coordinateFromString($pCellReference);
|
||||
|
||||
// Verify which parts should be updated
|
||||
$updateColumn = (($newColumn[0] != '$') && ($beforeColumn[0] != '$') && (Coordinate::columnIndexFromString($newColumn) >= Coordinate::columnIndexFromString($beforeColumn)));
|
||||
|
||||
@@ -47,7 +47,7 @@ class RichText implements IComparable
|
||||
*
|
||||
* @param ITextElement $pText Rich text element
|
||||
*
|
||||
* @return RichText
|
||||
* @return $this
|
||||
*/
|
||||
public function addText(ITextElement $pText)
|
||||
{
|
||||
@@ -133,7 +133,7 @@ class RichText implements IComparable
|
||||
*
|
||||
* @param ITextElement[] $textElements Array of elements
|
||||
*
|
||||
* @return RichText
|
||||
* @return $this
|
||||
*/
|
||||
public function setRichTextElements(array $textElements)
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ class Run extends TextElement implements ITextElement
|
||||
*
|
||||
* @param Font $pFont Font
|
||||
*
|
||||
* @return ITextElement
|
||||
* @return $this
|
||||
*/
|
||||
public function setFont(Font $pFont = null)
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ class TextElement implements ITextElement
|
||||
*
|
||||
* @param $text string Text
|
||||
*
|
||||
* @return ITextElement
|
||||
* @return $this
|
||||
*/
|
||||
public function setText($text)
|
||||
{
|
||||
|
||||
@@ -30,7 +30,6 @@ class Settings
|
||||
* 7.2 < 7.2.1
|
||||
* 7.1 < 7.1.13
|
||||
* 7.0 < 7.0.27
|
||||
* 5.6 ANY
|
||||
* then you may need to disable this check to prevent unwanted behaviour in other threads
|
||||
* SECURITY WARNING: Changing this flag is not recommended.
|
||||
*
|
||||
@@ -122,7 +121,6 @@ class Settings
|
||||
* 7.2 < 7.2.1
|
||||
* 7.1 < 7.1.13
|
||||
* 7.0 < 7.0.27
|
||||
* 5.6 ANY
|
||||
* then you may need to disable this check to prevent unwanted behaviour in other threads
|
||||
* SECURITY WARNING: Changing this flag to false is not recommended.
|
||||
*
|
||||
|
||||
@@ -298,9 +298,7 @@ class Font
|
||||
$upperLeftCornerX = $textBox[6];
|
||||
|
||||
// Consider the rotation when calculating the width
|
||||
$textWidth = max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX);
|
||||
|
||||
return $textWidth;
|
||||
return max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -174,7 +174,7 @@ class Matrix
|
||||
switch ($match) {
|
||||
//A($i0...; $j0...)
|
||||
case 'integer,integer':
|
||||
list($i0, $j0) = $args;
|
||||
[$i0, $j0] = $args;
|
||||
if ($i0 >= 0) {
|
||||
$m = $this->m - $i0;
|
||||
} else {
|
||||
@@ -197,7 +197,7 @@ class Matrix
|
||||
break;
|
||||
//A($i0...$iF; $j0...$jF)
|
||||
case 'integer,integer,integer,integer':
|
||||
list($i0, $iF, $j0, $jF) = $args;
|
||||
[$i0, $iF, $j0, $jF] = $args;
|
||||
if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) {
|
||||
$m = $iF - $i0;
|
||||
} else {
|
||||
@@ -220,7 +220,7 @@ class Matrix
|
||||
break;
|
||||
//$R = array of row indices; $C = array of column indices
|
||||
case 'array,array':
|
||||
list($RL, $CL) = $args;
|
||||
[$RL, $CL] = $args;
|
||||
if (count($RL) > 0) {
|
||||
$m = count($RL);
|
||||
} else {
|
||||
@@ -243,7 +243,7 @@ class Matrix
|
||||
break;
|
||||
//A($i0...$iF); $CL = array of column indices
|
||||
case 'integer,integer,array':
|
||||
list($i0, $iF, $CL) = $args;
|
||||
[$i0, $iF, $CL] = $args;
|
||||
if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) {
|
||||
$m = $iF - $i0;
|
||||
} else {
|
||||
@@ -266,7 +266,7 @@ class Matrix
|
||||
break;
|
||||
//$RL = array of row indices
|
||||
case 'array,integer,integer':
|
||||
list($RL, $j0, $jF) = $args;
|
||||
[$RL, $j0, $jF] = $args;
|
||||
if (count($RL) > 0) {
|
||||
$m = count($RL);
|
||||
} else {
|
||||
@@ -524,7 +524,7 @@ class Matrix
|
||||
*
|
||||
* @param mixed $B Matrix/Array
|
||||
*
|
||||
* @return Matrix Sum
|
||||
* @return $this
|
||||
*/
|
||||
public function plusEquals(...$args)
|
||||
{
|
||||
@@ -628,7 +628,7 @@ class Matrix
|
||||
*
|
||||
* @param mixed $B Matrix/Array
|
||||
*
|
||||
* @return Matrix Sum
|
||||
* @return $this
|
||||
*/
|
||||
public function minusEquals(...$args)
|
||||
{
|
||||
@@ -734,7 +734,7 @@ class Matrix
|
||||
*
|
||||
* @param mixed $B Matrix/Array
|
||||
*
|
||||
* @return Matrix Matrix Aij
|
||||
* @return $this
|
||||
*/
|
||||
public function arrayTimesEquals(...$args)
|
||||
{
|
||||
@@ -1091,7 +1091,7 @@ class Matrix
|
||||
*
|
||||
* @param mixed $B Matrix/Array
|
||||
*
|
||||
* @return Matrix Sum
|
||||
* @return $this
|
||||
*/
|
||||
public function power(...$args)
|
||||
{
|
||||
@@ -1150,7 +1150,7 @@ class Matrix
|
||||
*
|
||||
* @param mixed $B Matrix/Array
|
||||
*
|
||||
* @return Matrix Sum
|
||||
* @return $this
|
||||
*/
|
||||
public function concat(...$args)
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ class QRDecomposition
|
||||
{
|
||||
if ($A instanceof Matrix) {
|
||||
// Initialize.
|
||||
$this->QR = $A->getArrayCopy();
|
||||
$this->QR = $A->getArray();
|
||||
$this->m = $A->getRowDimension();
|
||||
$this->n = $A->getColumnDimension();
|
||||
// Main loop.
|
||||
|
||||
@@ -253,7 +253,7 @@ class OLE
|
||||
*/
|
||||
private static function _readInt1($fh)
|
||||
{
|
||||
list(, $tmp) = unpack('c', fread($fh, 1));
|
||||
[, $tmp] = unpack('c', fread($fh, 1));
|
||||
|
||||
return $tmp;
|
||||
}
|
||||
@@ -267,7 +267,7 @@ class OLE
|
||||
*/
|
||||
private static function _readInt2($fh)
|
||||
{
|
||||
list(, $tmp) = unpack('v', fread($fh, 2));
|
||||
[, $tmp] = unpack('v', fread($fh, 2));
|
||||
|
||||
return $tmp;
|
||||
}
|
||||
@@ -281,7 +281,7 @@ class OLE
|
||||
*/
|
||||
private static function _readInt4($fh)
|
||||
{
|
||||
list(, $tmp) = unpack('V', fread($fh, 4));
|
||||
[, $tmp] = unpack('V', fread($fh, 4));
|
||||
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ class Root extends PPS
|
||||
$aList = [];
|
||||
PPS::_savePpsSetPnt($aList, [$this]);
|
||||
// calculate values for header
|
||||
list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList); //, $rhInfo);
|
||||
[$iSBDcnt, $iBBcnt, $iPPScnt] = $this->_calcSize($aList); //, $rhInfo);
|
||||
// Save Header
|
||||
$this->_saveHeader($iSBDcnt, $iBBcnt, $iPPScnt);
|
||||
|
||||
@@ -149,7 +149,7 @@ class Root extends PPS
|
||||
public function _calcSize(&$raList)
|
||||
{
|
||||
// Calculate Basic Setting
|
||||
list($iSBDcnt, $iBBcnt, $iPPScnt) = [0, 0, 0];
|
||||
[$iSBDcnt, $iBBcnt, $iPPScnt] = [0, 0, 0];
|
||||
$iSmallLen = 0;
|
||||
$iSBcnt = 0;
|
||||
$iCount = count($raList);
|
||||
|
||||
@@ -430,9 +430,7 @@ class StringHelper
|
||||
// characters
|
||||
$chars = self::convertEncoding($value, 'UTF-16LE', 'UTF-8');
|
||||
|
||||
$data = pack('vC', $ln, 0x0001) . $chars;
|
||||
|
||||
return $data;
|
||||
return pack('vC', $ln, 0x0001) . $chars;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -211,7 +211,7 @@ class Xls
|
||||
*/
|
||||
public static function oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height)
|
||||
{
|
||||
list($column, $row) = Coordinate::coordinateFromString($coordinates);
|
||||
[$column, $row] = Coordinate::coordinateFromString($coordinates);
|
||||
$col_start = Coordinate::columnIndexFromString($column);
|
||||
$row_start = $row - 1;
|
||||
|
||||
@@ -269,7 +269,7 @@ class Xls
|
||||
$startCoordinates = Coordinate::stringFromColumnIndex($col_start) . ($row_start + 1);
|
||||
$endCoordinates = Coordinate::stringFromColumnIndex($col_end) . ($row_end + 1);
|
||||
|
||||
$twoAnchor = [
|
||||
return [
|
||||
'startCoordinates' => $startCoordinates,
|
||||
'startOffsetX' => $x1,
|
||||
'startOffsetY' => $y1,
|
||||
@@ -277,7 +277,5 @@ class Xls
|
||||
'endOffsetX' => $x2,
|
||||
'endOffsetY' => $y2,
|
||||
];
|
||||
|
||||
return $twoAnchor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -721,7 +721,7 @@ class Spreadsheet
|
||||
{
|
||||
$worksheetCount = count($this->workSheetCollection);
|
||||
for ($i = 0; $i < $worksheetCount; ++$i) {
|
||||
if ($this->workSheetCollection[$i]->getTitle() === $pName) {
|
||||
if ($this->workSheetCollection[$i]->getTitle() === trim($pName, "'")) {
|
||||
return $this->workSheetCollection[$i];
|
||||
}
|
||||
}
|
||||
@@ -955,7 +955,7 @@ class Spreadsheet
|
||||
* @param string $namedRange
|
||||
* @param null|Worksheet $pSheet scope: use null for global scope
|
||||
*
|
||||
* @return Spreadsheet
|
||||
* @return $this
|
||||
*/
|
||||
public function removeNamedRange($namedRange, Worksheet $pSheet = null)
|
||||
{
|
||||
|
||||
@@ -140,7 +140,7 @@ class Alignment extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Alignment
|
||||
* @return $this
|
||||
*/
|
||||
public function applyFromArray(array $pStyles)
|
||||
{
|
||||
@@ -193,7 +193,7 @@ class Alignment extends Supervisor
|
||||
*
|
||||
* @param string $pValue see self::HORIZONTAL_*
|
||||
*
|
||||
* @return Alignment
|
||||
* @return $this
|
||||
*/
|
||||
public function setHorizontal($pValue)
|
||||
{
|
||||
@@ -230,7 +230,7 @@ class Alignment extends Supervisor
|
||||
*
|
||||
* @param string $pValue see self::VERTICAL_*
|
||||
*
|
||||
* @return Alignment
|
||||
* @return $this
|
||||
*/
|
||||
public function setVertical($pValue)
|
||||
{
|
||||
@@ -269,7 +269,7 @@ class Alignment extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Alignment
|
||||
* @return $this
|
||||
*/
|
||||
public function setTextRotation($pValue)
|
||||
{
|
||||
@@ -312,7 +312,7 @@ class Alignment extends Supervisor
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Alignment
|
||||
* @return $this
|
||||
*/
|
||||
public function setWrapText($pValue)
|
||||
{
|
||||
@@ -348,7 +348,7 @@ class Alignment extends Supervisor
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Alignment
|
||||
* @return $this
|
||||
*/
|
||||
public function setShrinkToFit($pValue)
|
||||
{
|
||||
@@ -384,7 +384,7 @@ class Alignment extends Supervisor
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return Alignment
|
||||
* @return $this
|
||||
*/
|
||||
public function setIndent($pValue)
|
||||
{
|
||||
@@ -424,7 +424,7 @@ class Alignment extends Supervisor
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return Alignment
|
||||
* @return $this
|
||||
*/
|
||||
public function setReadOrder($pValue)
|
||||
{
|
||||
|
||||
@@ -127,7 +127,7 @@ class Border extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Border
|
||||
* @return $this
|
||||
*/
|
||||
public function applyFromArray(array $pStyles)
|
||||
{
|
||||
@@ -166,7 +166,7 @@ class Border extends Supervisor
|
||||
* When passing a boolean, FALSE equates Border::BORDER_NONE
|
||||
* and TRUE to Border::BORDER_MEDIUM
|
||||
*
|
||||
* @return Border
|
||||
* @return $this
|
||||
*/
|
||||
public function setBorderStyle($pValue)
|
||||
{
|
||||
@@ -202,7 +202,7 @@ class Border extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Border
|
||||
* @return $this
|
||||
*/
|
||||
public function setColor(Color $pValue)
|
||||
{
|
||||
|
||||
@@ -197,7 +197,7 @@ class Borders extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Borders
|
||||
* @return $this
|
||||
*/
|
||||
public function applyFromArray(array $pStyles)
|
||||
{
|
||||
@@ -382,7 +382,7 @@ class Borders extends Supervisor
|
||||
*
|
||||
* @param int $pValue see self::DIAGONAL_*
|
||||
*
|
||||
* @return Borders
|
||||
* @return $this
|
||||
*/
|
||||
public function setDiagonalDirection($pValue)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,17 @@ use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
|
||||
class Color extends Supervisor
|
||||
{
|
||||
const NAMED_COLORS = [
|
||||
'Black',
|
||||
'White',
|
||||
'Red',
|
||||
'Green',
|
||||
'Blue',
|
||||
'Yellow',
|
||||
'Magenta',
|
||||
'Cyan',
|
||||
];
|
||||
|
||||
// Colors
|
||||
const COLOR_BLACK = 'FF000000';
|
||||
const COLOR_WHITE = 'FFFFFFFF';
|
||||
@@ -95,7 +106,7 @@ class Color extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Color
|
||||
* @return $this
|
||||
*/
|
||||
public function applyFromArray(array $pStyles)
|
||||
{
|
||||
@@ -132,7 +143,7 @@ class Color extends Supervisor
|
||||
*
|
||||
* @param string $pValue see self::COLOR_*
|
||||
*
|
||||
* @return Color
|
||||
* @return $this
|
||||
*/
|
||||
public function setARGB($pValue)
|
||||
{
|
||||
@@ -168,7 +179,7 @@ class Color extends Supervisor
|
||||
*
|
||||
* @param string $pValue RGB value
|
||||
*
|
||||
* @return Color
|
||||
* @return $this
|
||||
*/
|
||||
public function setRGB($pValue)
|
||||
{
|
||||
@@ -198,11 +209,8 @@ class Color extends Supervisor
|
||||
private static function getColourComponent($RGB, $offset, $hex = true)
|
||||
{
|
||||
$colour = substr($RGB, $offset, 2);
|
||||
if (!$hex) {
|
||||
$colour = hexdec($colour);
|
||||
}
|
||||
|
||||
return $colour;
|
||||
return ($hex) ? $colour : hexdec($colour);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,7 +265,7 @@ class Color extends Supervisor
|
||||
*/
|
||||
public static function changeBrightness($hex, $adjustPercentage)
|
||||
{
|
||||
$rgba = (strlen($hex) == 8);
|
||||
$rgba = (strlen($hex) === 8);
|
||||
|
||||
$red = self::getRed($hex, false);
|
||||
$green = self::getGreen($hex, false);
|
||||
@@ -289,9 +297,9 @@ class Color extends Supervisor
|
||||
}
|
||||
|
||||
$rgb = strtoupper(
|
||||
str_pad(dechex($red), 2, '0', 0) .
|
||||
str_pad(dechex($green), 2, '0', 0) .
|
||||
str_pad(dechex($blue), 2, '0', 0)
|
||||
str_pad(dechex((int) $red), 2, '0', 0) .
|
||||
str_pad(dechex((int) $green), 2, '0', 0) .
|
||||
str_pad(dechex((int) $blue), 2, '0', 0)
|
||||
);
|
||||
|
||||
return (($rgba) ? 'FF' : '') . $rgb;
|
||||
@@ -304,7 +312,7 @@ class Color extends Supervisor
|
||||
* @param bool $background Flag to indicate whether default background or foreground colour
|
||||
* should be returned if the indexed colour doesn't exist
|
||||
*
|
||||
* @return Color
|
||||
* @return self
|
||||
*/
|
||||
public static function indexedColor($pIndex, $background = false)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ class Conditional implements IComparable
|
||||
const CONDITION_CONTAINSTEXT = 'containsText';
|
||||
const CONDITION_EXPRESSION = 'expression';
|
||||
const CONDITION_CONTAINSBLANKS = 'containsBlanks';
|
||||
const CONDITION_NOTCONTAINSBLANKS = 'notContainsBlanks';
|
||||
|
||||
// Operator types
|
||||
const OPERATOR_NONE = '';
|
||||
@@ -93,7 +94,7 @@ class Conditional implements IComparable
|
||||
*
|
||||
* @param string $pValue Condition type, see self::CONDITION_*
|
||||
*
|
||||
* @return Conditional
|
||||
* @return $this
|
||||
*/
|
||||
public function setConditionType($pValue)
|
||||
{
|
||||
@@ -117,7 +118,7 @@ class Conditional implements IComparable
|
||||
*
|
||||
* @param string $pValue Conditional operator type, see self::OPERATOR_*
|
||||
*
|
||||
* @return Conditional
|
||||
* @return $this
|
||||
*/
|
||||
public function setOperatorType($pValue)
|
||||
{
|
||||
@@ -141,7 +142,7 @@ class Conditional implements IComparable
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return Conditional
|
||||
* @return $this
|
||||
*/
|
||||
public function setText($value)
|
||||
{
|
||||
@@ -165,7 +166,7 @@ class Conditional implements IComparable
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return Conditional
|
||||
* @return $this
|
||||
*/
|
||||
public function setStopIfTrue($value)
|
||||
{
|
||||
@@ -189,7 +190,7 @@ class Conditional implements IComparable
|
||||
*
|
||||
* @param string[] $pValue Condition
|
||||
*
|
||||
* @return Conditional
|
||||
* @return $this
|
||||
*/
|
||||
public function setConditions($pValue)
|
||||
{
|
||||
@@ -206,7 +207,7 @@ class Conditional implements IComparable
|
||||
*
|
||||
* @param string $pValue Condition
|
||||
*
|
||||
* @return Conditional
|
||||
* @return $this
|
||||
*/
|
||||
public function addCondition($pValue)
|
||||
{
|
||||
@@ -230,7 +231,7 @@ class Conditional implements IComparable
|
||||
*
|
||||
* @param Style $pValue
|
||||
*
|
||||
* @return Conditional
|
||||
* @return $this
|
||||
*/
|
||||
public function setStyle(Style $pValue = null)
|
||||
{
|
||||
|
||||
@@ -141,7 +141,7 @@ class Fill extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Fill
|
||||
* @return $this
|
||||
*/
|
||||
public function applyFromArray(array $pStyles)
|
||||
{
|
||||
@@ -188,7 +188,7 @@ class Fill extends Supervisor
|
||||
*
|
||||
* @param string $pValue Fill type, see self::FILL_*
|
||||
*
|
||||
* @return Fill
|
||||
* @return $this
|
||||
*/
|
||||
public function setFillType($pValue)
|
||||
{
|
||||
@@ -221,7 +221,7 @@ class Fill extends Supervisor
|
||||
*
|
||||
* @param float $pValue
|
||||
*
|
||||
* @return Fill
|
||||
* @return $this
|
||||
*/
|
||||
public function setRotation($pValue)
|
||||
{
|
||||
@@ -252,7 +252,7 @@ class Fill extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Fill
|
||||
* @return $this
|
||||
*/
|
||||
public function setStartColor(Color $pValue)
|
||||
{
|
||||
@@ -286,7 +286,7 @@ class Fill extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Fill
|
||||
* @return $this
|
||||
*/
|
||||
public function setEndColor(Color $pValue)
|
||||
{
|
||||
@@ -313,12 +313,13 @@ class Fill extends Supervisor
|
||||
if ($this->isSupervisor) {
|
||||
return $this->getSharedComponent()->getHashCode();
|
||||
}
|
||||
|
||||
// Note that we don't care about colours for fill type NONE, but could have duplicate NONEs with
|
||||
// different hashes if we don't explicitly prevent this
|
||||
return md5(
|
||||
$this->getFillType() .
|
||||
$this->getRotation() .
|
||||
$this->getStartColor()->getHashCode() .
|
||||
$this->getEndColor()->getHashCode() .
|
||||
($this->getFillType() !== self::FILL_NONE ? $this->getStartColor()->getHashCode() : '') .
|
||||
($this->getFillType() !== self::FILL_NONE ? $this->getEndColor()->getHashCode() : '') .
|
||||
__CLASS__
|
||||
);
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ class Font extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Font
|
||||
* @return $this
|
||||
*/
|
||||
public function applyFromArray(array $pStyles)
|
||||
{
|
||||
@@ -219,7 +219,7 @@ class Font extends Supervisor
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return Font
|
||||
* @return $this
|
||||
*/
|
||||
public function setName($pValue)
|
||||
{
|
||||
@@ -255,7 +255,7 @@ class Font extends Supervisor
|
||||
*
|
||||
* @param float $pValue
|
||||
*
|
||||
* @return Font
|
||||
* @return $this
|
||||
*/
|
||||
public function setSize($pValue)
|
||||
{
|
||||
@@ -291,7 +291,7 @@ class Font extends Supervisor
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Font
|
||||
* @return $this
|
||||
*/
|
||||
public function setBold($pValue)
|
||||
{
|
||||
@@ -327,7 +327,7 @@ class Font extends Supervisor
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Font
|
||||
* @return $this
|
||||
*/
|
||||
public function setItalic($pValue)
|
||||
{
|
||||
@@ -363,7 +363,7 @@ class Font extends Supervisor
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Font
|
||||
* @return $this
|
||||
*/
|
||||
public function setSuperscript($pValue)
|
||||
{
|
||||
@@ -400,7 +400,7 @@ class Font extends Supervisor
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Font
|
||||
* @return $this
|
||||
*/
|
||||
public function setSubscript($pValue)
|
||||
{
|
||||
@@ -439,7 +439,7 @@ class Font extends Supervisor
|
||||
* If a boolean is passed, then TRUE equates to UNDERLINE_SINGLE,
|
||||
* false equates to UNDERLINE_NONE
|
||||
*
|
||||
* @return Font
|
||||
* @return $this
|
||||
*/
|
||||
public function setUnderline($pValue)
|
||||
{
|
||||
@@ -477,7 +477,7 @@ class Font extends Supervisor
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Font
|
||||
* @return $this
|
||||
*/
|
||||
public function setStrikethrough($pValue)
|
||||
{
|
||||
@@ -512,7 +512,7 @@ class Font extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Font
|
||||
* @return $this
|
||||
*/
|
||||
public function setColor(Color $pValue)
|
||||
{
|
||||
|
||||
@@ -23,8 +23,8 @@ class NumberFormat extends Supervisor
|
||||
const FORMAT_PERCENTAGE_00 = '0.00%';
|
||||
|
||||
const FORMAT_DATE_YYYYMMDD2 = 'yyyy-mm-dd';
|
||||
const FORMAT_DATE_YYYYMMDD = 'yy-mm-dd';
|
||||
const FORMAT_DATE_DDMMYYYY = 'dd/mm/yy';
|
||||
const FORMAT_DATE_YYYYMMDD = 'yyyy-mm-dd';
|
||||
const FORMAT_DATE_DDMMYYYY = 'dd/mm/yyyy';
|
||||
const FORMAT_DATE_DMYSLASH = 'd/m/yy';
|
||||
const FORMAT_DATE_DMYMINUS = 'd-m-yy';
|
||||
const FORMAT_DATE_DMMINUS = 'd-m';
|
||||
@@ -43,7 +43,7 @@ class NumberFormat extends Supervisor
|
||||
const FORMAT_DATE_TIME6 = 'h:mm:ss';
|
||||
const FORMAT_DATE_TIME7 = 'i:s.S';
|
||||
const FORMAT_DATE_TIME8 = 'h:mm:ss;@';
|
||||
const FORMAT_DATE_YYYYMMDDSLASH = 'yy/mm/dd;@';
|
||||
const FORMAT_DATE_YYYYMMDDSLASH = 'yyyy/mm/dd;@';
|
||||
|
||||
const FORMAT_CURRENCY_USD_SIMPLE = '"$"#,##0.00_-';
|
||||
const FORMAT_CURRENCY_USD = '$#,##0_-';
|
||||
@@ -139,7 +139,7 @@ class NumberFormat extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return NumberFormat
|
||||
* @return $this
|
||||
*/
|
||||
public function applyFromArray(array $pStyles)
|
||||
{
|
||||
@@ -176,7 +176,7 @@ class NumberFormat extends Supervisor
|
||||
*
|
||||
* @param string $pValue see self::FORMAT_*
|
||||
*
|
||||
* @return NumberFormat
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormatCode($pValue)
|
||||
{
|
||||
@@ -213,7 +213,7 @@ class NumberFormat extends Supervisor
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return NumberFormat
|
||||
* @return $this
|
||||
*/
|
||||
public function setBuiltInFormatCode($pValue)
|
||||
{
|
||||
@@ -367,7 +367,7 @@ class NumberFormat extends Supervisor
|
||||
self::fillBuiltInFormatCodes();
|
||||
|
||||
// Lookup format code
|
||||
if (isset(self::$flippedBuiltInFormats[$formatCode])) {
|
||||
if (array_key_exists($formatCode, self::$flippedBuiltInFormats)) {
|
||||
return self::$flippedBuiltInFormats[$formatCode];
|
||||
}
|
||||
|
||||
@@ -551,24 +551,32 @@ class NumberFormat extends Supervisor
|
||||
}
|
||||
}
|
||||
|
||||
private static function complexNumberFormatMask($number, $mask)
|
||||
private static function mergeComplexNumberFormatMasks($numbers, $masks)
|
||||
{
|
||||
$sign = ($number < 0.0);
|
||||
$number = abs($number);
|
||||
if (strpos($mask, '.') !== false) {
|
||||
$numbers = explode('.', $number . '.0');
|
||||
$masks = explode('.', $mask . '.0');
|
||||
$result1 = self::complexNumberFormatMask($numbers[0], $masks[0]);
|
||||
$result2 = strrev(self::complexNumberFormatMask(strrev($numbers[1]), strrev($masks[1])));
|
||||
$decimalCount = strlen($numbers[1]);
|
||||
$postDecimalMasks = [];
|
||||
|
||||
return (($sign) ? '-' : '') . $result1 . '.' . $result2;
|
||||
}
|
||||
do {
|
||||
$tempMask = array_pop($masks);
|
||||
$postDecimalMasks[] = $tempMask;
|
||||
$decimalCount -= strlen($tempMask);
|
||||
} while ($decimalCount > 0);
|
||||
|
||||
$r = preg_match_all('/0+/', $mask, $result, PREG_OFFSET_CAPTURE);
|
||||
if ($r > 1) {
|
||||
$result = array_reverse($result[0]);
|
||||
return [
|
||||
implode('.', $masks),
|
||||
implode('.', array_reverse($postDecimalMasks)),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($result as $block) {
|
||||
private static function processComplexNumberFormatMask($number, $mask)
|
||||
{
|
||||
$result = $number;
|
||||
$maskingBlockCount = preg_match_all('/0+/', $mask, $maskingBlocks, PREG_OFFSET_CAPTURE);
|
||||
|
||||
if ($maskingBlockCount > 1) {
|
||||
$maskingBlocks = array_reverse($maskingBlocks[0]);
|
||||
|
||||
foreach ($maskingBlocks as $block) {
|
||||
$divisor = 1 . $block[0];
|
||||
$size = strlen($block[0]);
|
||||
$offset = $block[1];
|
||||
@@ -584,13 +592,134 @@ class NumberFormat extends Supervisor
|
||||
$mask = substr_replace($mask, $number, $offset, 0);
|
||||
}
|
||||
$result = $mask;
|
||||
} else {
|
||||
$result = $number;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private static function complexNumberFormatMask($number, $mask, $splitOnPoint = true)
|
||||
{
|
||||
$sign = ($number < 0.0);
|
||||
$number = abs($number);
|
||||
|
||||
if ($splitOnPoint && strpos($mask, '.') !== false && strpos($number, '.') !== false) {
|
||||
$numbers = explode('.', $number);
|
||||
$masks = explode('.', $mask);
|
||||
if (count($masks) > 2) {
|
||||
$masks = self::mergeComplexNumberFormatMasks($numbers, $masks);
|
||||
}
|
||||
$result1 = self::complexNumberFormatMask($numbers[0], $masks[0], false);
|
||||
$result2 = strrev(self::complexNumberFormatMask(strrev($numbers[1]), strrev($masks[1]), false));
|
||||
|
||||
return (($sign) ? '-' : '') . $result1 . '.' . $result2;
|
||||
}
|
||||
|
||||
$result = self::processComplexNumberFormatMask($number, $mask);
|
||||
|
||||
return (($sign) ? '-' : '') . $result;
|
||||
}
|
||||
|
||||
private static function formatStraightNumericValue($value, $format, array $matches, $useThousands, $number_regex)
|
||||
{
|
||||
$left = $matches[1];
|
||||
$dec = $matches[2];
|
||||
$right = $matches[3];
|
||||
|
||||
// minimun width of formatted number (including dot)
|
||||
$minWidth = strlen($left) + strlen($dec) + strlen($right);
|
||||
if ($useThousands) {
|
||||
$value = number_format(
|
||||
$value,
|
||||
strlen($right),
|
||||
StringHelper::getDecimalSeparator(),
|
||||
StringHelper::getThousandsSeparator()
|
||||
);
|
||||
$value = preg_replace($number_regex, $value, $format);
|
||||
} else {
|
||||
if (preg_match('/[0#]E[+-]0/i', $format)) {
|
||||
// Scientific format
|
||||
$value = sprintf('%5.2E', $value);
|
||||
} elseif (preg_match('/0([^\d\.]+)0/', $format) || substr_count($format, '.') > 1) {
|
||||
if ($value == (int) $value && substr_count($format, '.') === 1) {
|
||||
$value *= 10 ** strlen(explode('.', $format)[1]);
|
||||
}
|
||||
$value = self::complexNumberFormatMask($value, $format);
|
||||
} else {
|
||||
$sprintf_pattern = "%0$minWidth." . strlen($right) . 'f';
|
||||
$value = sprintf($sprintf_pattern, $value);
|
||||
$value = preg_replace($number_regex, $value, $format);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
private static function formatAsNumber($value, $format)
|
||||
{
|
||||
if ($format === self::FORMAT_CURRENCY_EUR_SIMPLE) {
|
||||
return 'EUR ' . sprintf('%1.2f', $value);
|
||||
}
|
||||
|
||||
// Some non-number strings are quoted, so we'll get rid of the quotes, likewise any positional * symbols
|
||||
$format = str_replace(['"', '*'], '', $format);
|
||||
|
||||
// Find out if we need thousands separator
|
||||
// This is indicated by a comma enclosed by a digit placeholder:
|
||||
// #,# or 0,0
|
||||
$useThousands = preg_match('/(#,#|0,0)/', $format);
|
||||
if ($useThousands) {
|
||||
$format = preg_replace('/0,0/', '00', $format);
|
||||
$format = preg_replace('/#,#/', '##', $format);
|
||||
}
|
||||
|
||||
// Scale thousands, millions,...
|
||||
// This is indicated by a number of commas after a digit placeholder:
|
||||
// #, or 0.0,,
|
||||
$scale = 1; // same as no scale
|
||||
$matches = [];
|
||||
if (preg_match('/(#|0)(,+)/', $format, $matches)) {
|
||||
$scale = pow(1000, strlen($matches[2]));
|
||||
|
||||
// strip the commas
|
||||
$format = preg_replace('/0,+/', '0', $format);
|
||||
$format = preg_replace('/#,+/', '#', $format);
|
||||
}
|
||||
|
||||
if (preg_match('/#?.*\?\/\?/', $format, $m)) {
|
||||
if ($value != (int) $value) {
|
||||
self::formatAsFraction($value, $format);
|
||||
}
|
||||
} else {
|
||||
// Handle the number itself
|
||||
|
||||
// scale number
|
||||
$value = $value / $scale;
|
||||
// Strip #
|
||||
$format = preg_replace('/\\#/', '0', $format);
|
||||
// Remove locale code [$-###]
|
||||
$format = preg_replace('/\[\$\-.*\]/', '', $format);
|
||||
|
||||
$n = '/\\[[^\\]]+\\]/';
|
||||
$m = preg_replace($n, '', $format);
|
||||
$number_regex = '/(0+)(\\.?)(0*)/';
|
||||
if (preg_match($number_regex, $m, $matches)) {
|
||||
$value = self::formatStraightNumericValue($value, $format, $matches, $useThousands, $number_regex);
|
||||
}
|
||||
}
|
||||
|
||||
if (preg_match('/\[\$(.*)\]/u', $format, $m)) {
|
||||
// Currency or Accounting
|
||||
$currencyCode = $m[1];
|
||||
[$currencyCode] = explode('-', $currencyCode);
|
||||
if ($currencyCode == '') {
|
||||
$currencyCode = StringHelper::getCurrencyCode();
|
||||
}
|
||||
$value = preg_replace('/\[\$([^\]]*)\]/u', $currencyCode, $value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a value in a pre-defined format to a PHP string.
|
||||
*
|
||||
@@ -660,7 +789,9 @@ class NumberFormat extends Supervisor
|
||||
|
||||
// Save format with color information for later use below
|
||||
$formatColor = $format;
|
||||
|
||||
// Strip colour information
|
||||
$color_regex = '/\[(' . implode('|', Color::NAMED_COLORS) . ')\]/';
|
||||
$format = preg_replace($color_regex, '', $format);
|
||||
// Let's begin inspecting the format and converting the value to a formatted string
|
||||
|
||||
// Check for date/time characters (not inside quotes)
|
||||
@@ -668,105 +799,19 @@ class NumberFormat extends Supervisor
|
||||
// datetime format
|
||||
self::formatAsDate($value, $format);
|
||||
} else {
|
||||
// Strip color information
|
||||
$color_regex = '/^\\[[a-zA-Z]+\\]/';
|
||||
$format = preg_replace($color_regex, '', $format);
|
||||
if (preg_match('/%$/', $format)) {
|
||||
if (substr($format, 0, 1) === '"' && substr($format, -1, 1) === '"') {
|
||||
$value = substr($format, 1, -1);
|
||||
} elseif (preg_match('/%$/', $format)) {
|
||||
// % number format
|
||||
self::formatAsPercentage($value, $format);
|
||||
} else {
|
||||
if ($format === self::FORMAT_CURRENCY_EUR_SIMPLE) {
|
||||
$value = 'EUR ' . sprintf('%1.2f', $value);
|
||||
} else {
|
||||
// Some non-number strings are quoted, so we'll get rid of the quotes, likewise any positional * symbols
|
||||
$format = str_replace(['"', '*'], '', $format);
|
||||
|
||||
// Find out if we need thousands separator
|
||||
// This is indicated by a comma enclosed by a digit placeholder:
|
||||
// #,# or 0,0
|
||||
$useThousands = preg_match('/(#,#|0,0)/', $format);
|
||||
if ($useThousands) {
|
||||
$format = preg_replace('/0,0/', '00', $format);
|
||||
$format = preg_replace('/#,#/', '##', $format);
|
||||
}
|
||||
|
||||
// Scale thousands, millions,...
|
||||
// This is indicated by a number of commas after a digit placeholder:
|
||||
// #, or 0.0,,
|
||||
$scale = 1; // same as no scale
|
||||
$matches = [];
|
||||
if (preg_match('/(#|0)(,+)/', $format, $matches)) {
|
||||
$scale = pow(1000, strlen($matches[2]));
|
||||
|
||||
// strip the commas
|
||||
$format = preg_replace('/0,+/', '0', $format);
|
||||
$format = preg_replace('/#,+/', '#', $format);
|
||||
}
|
||||
|
||||
if (preg_match('/#?.*\?\/\?/', $format, $m)) {
|
||||
if ($value != (int) $value) {
|
||||
self::formatAsFraction($value, $format);
|
||||
}
|
||||
} else {
|
||||
// Handle the number itself
|
||||
|
||||
// scale number
|
||||
$value = $value / $scale;
|
||||
|
||||
// Strip #
|
||||
$format = preg_replace('/\\#/', '0', $format);
|
||||
|
||||
// Remove locale code [$-###]
|
||||
$format = preg_replace('/\[\$\-.*\]/', '', $format);
|
||||
|
||||
$n = '/\\[[^\\]]+\\]/';
|
||||
$m = preg_replace($n, '', $format);
|
||||
$number_regex = '/(0+)(\\.?)(0*)/';
|
||||
if (preg_match($number_regex, $m, $matches)) {
|
||||
$left = $matches[1];
|
||||
$dec = $matches[2];
|
||||
$right = $matches[3];
|
||||
|
||||
// minimun width of formatted number (including dot)
|
||||
$minWidth = strlen($left) + strlen($dec) + strlen($right);
|
||||
if ($useThousands) {
|
||||
$value = number_format(
|
||||
$value,
|
||||
strlen($right),
|
||||
StringHelper::getDecimalSeparator(),
|
||||
StringHelper::getThousandsSeparator()
|
||||
);
|
||||
$value = preg_replace($number_regex, $value, $format);
|
||||
} else {
|
||||
if (preg_match('/[0#]E[+-]0/i', $format)) {
|
||||
// Scientific format
|
||||
$value = sprintf('%5.2E', $value);
|
||||
} elseif (preg_match('/0([^\d\.]+)0/', $format)) {
|
||||
$value = self::complexNumberFormatMask($value, $format);
|
||||
} else {
|
||||
$sprintf_pattern = "%0$minWidth." . strlen($right) . 'f';
|
||||
$value = sprintf($sprintf_pattern, $value);
|
||||
$value = preg_replace($number_regex, $value, $format);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (preg_match('/\[\$(.*)\]/u', $format, $m)) {
|
||||
// Currency or Accounting
|
||||
$currencyCode = $m[1];
|
||||
list($currencyCode) = explode('-', $currencyCode);
|
||||
if ($currencyCode == '') {
|
||||
$currencyCode = StringHelper::getCurrencyCode();
|
||||
}
|
||||
$value = preg_replace('/\[\$([^\]]*)\]/u', $currencyCode, $value);
|
||||
}
|
||||
}
|
||||
$value = self::formatAsNumber($value, $format);
|
||||
}
|
||||
}
|
||||
|
||||
// Additional formatting provided by callback function
|
||||
if ($callBack !== null) {
|
||||
list($writerInstance, $function) = $callBack;
|
||||
[$writerInstance, $function] = $callBack;
|
||||
$value = $writerInstance->$function($value, $formatColor);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ class Protection extends Supervisor
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function applyFromArray(array $pStyles)
|
||||
{
|
||||
@@ -123,7 +123,7 @@ class Protection extends Supervisor
|
||||
*
|
||||
* @param string $pValue see self::PROTECTION_*
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setLocked($pValue)
|
||||
{
|
||||
@@ -156,7 +156,7 @@ class Protection extends Supervisor
|
||||
*
|
||||
* @param string $pValue see self::PROTECTION_*
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setHidden($pValue)
|
||||
{
|
||||
|
||||
@@ -189,7 +189,7 @@ class Style extends Supervisor
|
||||
* @param array $pStyles Array containing style information
|
||||
* @param bool $pAdvanced advanced mode for setting borders
|
||||
*
|
||||
* @return Style
|
||||
* @return $this
|
||||
*/
|
||||
public function applyFromArray(array $pStyles, $pAdvanced = true)
|
||||
{
|
||||
@@ -204,7 +204,7 @@ class Style extends Supervisor
|
||||
$rangeA = $pRange;
|
||||
$rangeB = $pRange;
|
||||
} else {
|
||||
list($rangeA, $rangeB) = explode(':', $pRange);
|
||||
[$rangeA, $rangeB] = explode(':', $pRange);
|
||||
}
|
||||
|
||||
// Calculate range outer borders
|
||||
@@ -485,7 +485,7 @@ class Style extends Supervisor
|
||||
*
|
||||
* @param Font $font
|
||||
*
|
||||
* @return Style
|
||||
* @return $this
|
||||
*/
|
||||
public function setFont(Font $font)
|
||||
{
|
||||
@@ -539,7 +539,7 @@ class Style extends Supervisor
|
||||
*
|
||||
* @param Conditional[] $pValue Array of conditional styles
|
||||
*
|
||||
* @return Style
|
||||
* @return $this
|
||||
*/
|
||||
public function setConditionalStyles(array $pValue)
|
||||
{
|
||||
@@ -577,7 +577,7 @@ class Style extends Supervisor
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Style
|
||||
* @return $this
|
||||
*/
|
||||
public function setQuotePrefix($pValue)
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@ abstract class Supervisor implements IComparable
|
||||
* @param Spreadsheet|Style $parent
|
||||
* @param null|string $parentPropertyName
|
||||
*
|
||||
* @return Supervisor
|
||||
* @return $this
|
||||
*/
|
||||
public function bindParent($parent, $parentPropertyName = null)
|
||||
{
|
||||
|
||||
@@ -59,7 +59,7 @@ class AutoFilter
|
||||
*
|
||||
* @param Worksheet $pSheet
|
||||
*
|
||||
* @return AutoFilter
|
||||
* @return $this
|
||||
*/
|
||||
public function setParent(Worksheet $pSheet = null)
|
||||
{
|
||||
@@ -85,12 +85,12 @@ class AutoFilter
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return AutoFilter
|
||||
* @return $this
|
||||
*/
|
||||
public function setRange($pRange)
|
||||
{
|
||||
// extract coordinate
|
||||
list($worksheet, $pRange) = Worksheet::extractSheetTitle($pRange, true);
|
||||
[$worksheet, $pRange] = Worksheet::extractSheetTitle($pRange, true);
|
||||
|
||||
if (strpos($pRange, ':') !== false) {
|
||||
$this->range = $pRange;
|
||||
@@ -105,7 +105,7 @@ class AutoFilter
|
||||
$this->columns = [];
|
||||
} else {
|
||||
// Discard any column rules that are no longer valid within this range
|
||||
list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($this->range);
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range);
|
||||
foreach ($this->columns as $key => $value) {
|
||||
$colIndex = Coordinate::columnIndexFromString($key);
|
||||
if (($rangeStart[0] > $colIndex) || ($rangeEnd[0] < $colIndex)) {
|
||||
@@ -143,7 +143,7 @@ class AutoFilter
|
||||
}
|
||||
|
||||
$columnIndex = Coordinate::columnIndexFromString($column);
|
||||
list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($this->range);
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range);
|
||||
if (($rangeStart[0] > $columnIndex) || ($rangeEnd[0] < $columnIndex)) {
|
||||
throw new PhpSpreadsheetException('Column is outside of current autofilter range.');
|
||||
}
|
||||
@@ -196,7 +196,7 @@ class AutoFilter
|
||||
*/
|
||||
public function getColumnByOffset($pColumnOffset)
|
||||
{
|
||||
list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($this->range);
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range);
|
||||
$pColumn = Coordinate::stringFromColumnIndex($rangeStart[0] + $pColumnOffset);
|
||||
|
||||
return $this->getColumn($pColumn);
|
||||
@@ -210,7 +210,7 @@ class AutoFilter
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return AutoFilter
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumn($pColumn)
|
||||
{
|
||||
@@ -241,7 +241,7 @@ class AutoFilter
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return AutoFilter
|
||||
* @return $this
|
||||
*/
|
||||
public function clearColumn($pColumn)
|
||||
{
|
||||
@@ -264,7 +264,7 @@ class AutoFilter
|
||||
* @param string $fromColumn Column name (e.g. A)
|
||||
* @param string $toColumn Column name (e.g. B)
|
||||
*
|
||||
* @return AutoFilter
|
||||
* @return $this
|
||||
*/
|
||||
public function shiftColumn($fromColumn, $toColumn)
|
||||
{
|
||||
@@ -357,7 +357,7 @@ class AutoFilter
|
||||
{
|
||||
$dataSet = $ruleSet['filterRules'];
|
||||
$join = $ruleSet['join'];
|
||||
$customRuleForBlanks = isset($ruleSet['customRuleForBlanks']) ? $ruleSet['customRuleForBlanks'] : false;
|
||||
$customRuleForBlanks = $ruleSet['customRuleForBlanks'] ?? false;
|
||||
|
||||
if (!$customRuleForBlanks) {
|
||||
// Blank cells are always ignored, so return a FALSE
|
||||
@@ -617,11 +617,11 @@ class AutoFilter
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return AutoFilter
|
||||
* @return $this
|
||||
*/
|
||||
public function showHideRows()
|
||||
{
|
||||
list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($this->range);
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($this->range);
|
||||
|
||||
// The heading row should always be visible
|
||||
$this->workSheet->getRowDimension($rangeStart[1])->setVisible(true);
|
||||
|
||||
@@ -101,7 +101,7 @@ class Column
|
||||
}
|
||||
|
||||
/**
|
||||
* Get AutoFilter Column Index.
|
||||
* Get AutoFilter column index as string eg: 'A'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -111,13 +111,13 @@ class Column
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AutoFilter Column Index.
|
||||
* Set AutoFilter column index as string eg: 'A'.
|
||||
*
|
||||
* @param string $pColumn Column (e.g. A)
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Column
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumnIndex($pColumn)
|
||||
{
|
||||
@@ -147,7 +147,7 @@ class Column
|
||||
*
|
||||
* @param AutoFilter $pParent
|
||||
*
|
||||
* @return Column
|
||||
* @return $this
|
||||
*/
|
||||
public function setParent(AutoFilter $pParent = null)
|
||||
{
|
||||
@@ -173,7 +173,7 @@ class Column
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Column
|
||||
* @return $this
|
||||
*/
|
||||
public function setFilterType($pFilterType)
|
||||
{
|
||||
@@ -203,7 +203,7 @@ class Column
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Column
|
||||
* @return $this
|
||||
*/
|
||||
public function setJoin($pJoin)
|
||||
{
|
||||
@@ -223,7 +223,7 @@ class Column
|
||||
*
|
||||
* @param string[] $attributes
|
||||
*
|
||||
* @return Column
|
||||
* @return $this
|
||||
*/
|
||||
public function setAttributes(array $attributes)
|
||||
{
|
||||
@@ -238,7 +238,7 @@ class Column
|
||||
* @param string $pName Attribute Name
|
||||
* @param string $pValue Attribute Value
|
||||
*
|
||||
* @return Column
|
||||
* @return $this
|
||||
*/
|
||||
public function setAttribute($pName, $pValue)
|
||||
{
|
||||
@@ -316,7 +316,7 @@ class Column
|
||||
*
|
||||
* @param Column\Rule $pRule
|
||||
*
|
||||
* @return Column
|
||||
* @return $this
|
||||
*/
|
||||
public function addRule(Column\Rule $pRule)
|
||||
{
|
||||
@@ -332,7 +332,7 @@ class Column
|
||||
*
|
||||
* @param int $pIndex Rule index in the ruleset array
|
||||
*
|
||||
* @return Column
|
||||
* @return $this
|
||||
*/
|
||||
public function deleteRule($pIndex)
|
||||
{
|
||||
@@ -350,7 +350,7 @@ class Column
|
||||
/**
|
||||
* Delete all AutoFilter Column Rules.
|
||||
*
|
||||
* @return Column
|
||||
* @return $this
|
||||
*/
|
||||
public function clearRules()
|
||||
{
|
||||
|
||||
@@ -262,7 +262,7 @@ class Rule
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Rule
|
||||
* @return $this
|
||||
*/
|
||||
public function setRuleType($pRuleType)
|
||||
{
|
||||
@@ -292,7 +292,7 @@ class Rule
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Rule
|
||||
* @return $this
|
||||
*/
|
||||
public function setValue($pValue)
|
||||
{
|
||||
@@ -336,7 +336,7 @@ class Rule
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Rule
|
||||
* @return $this
|
||||
*/
|
||||
public function setOperator($pOperator)
|
||||
{
|
||||
@@ -369,7 +369,7 @@ class Rule
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Rule
|
||||
* @return $this
|
||||
*/
|
||||
public function setGrouping($pGrouping)
|
||||
{
|
||||
@@ -393,7 +393,7 @@ class Rule
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Rule
|
||||
* @return $this
|
||||
*/
|
||||
public function setRule($pOperator, $pValue, $pGrouping = null)
|
||||
{
|
||||
@@ -424,7 +424,7 @@ class Rule
|
||||
*
|
||||
* @param Column $pParent
|
||||
*
|
||||
* @return Rule
|
||||
* @return $this
|
||||
*/
|
||||
public function setParent(Column $pParent = null)
|
||||
{
|
||||
|
||||
@@ -154,7 +154,7 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return BaseDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setName($pValue)
|
||||
{
|
||||
@@ -178,7 +178,7 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @param string $description
|
||||
*
|
||||
* @return BaseDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
@@ -205,7 +205,7 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return BaseDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setWorksheet(Worksheet $pValue = null, $pOverrideOld = false)
|
||||
{
|
||||
@@ -253,7 +253,7 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @param string $pValue eg: 'A1'
|
||||
*
|
||||
* @return BaseDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setCoordinates($pValue)
|
||||
{
|
||||
@@ -277,7 +277,7 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return BaseDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setOffsetX($pValue)
|
||||
{
|
||||
@@ -301,7 +301,7 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return BaseDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setOffsetY($pValue)
|
||||
{
|
||||
@@ -325,7 +325,7 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return BaseDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setWidth($pValue)
|
||||
{
|
||||
@@ -356,7 +356,7 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return BaseDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeight($pValue)
|
||||
{
|
||||
@@ -386,7 +386,7 @@ class BaseDrawing implements IComparable
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
*
|
||||
* @return BaseDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setWidthAndHeight($width, $height)
|
||||
{
|
||||
@@ -423,7 +423,7 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return BaseDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setResizeProportional($pValue)
|
||||
{
|
||||
@@ -447,7 +447,7 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return BaseDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setRotation($pValue)
|
||||
{
|
||||
@@ -471,7 +471,7 @@ class BaseDrawing implements IComparable
|
||||
*
|
||||
* @param Drawing\Shadow $pValue
|
||||
*
|
||||
* @return BaseDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setShadow(Drawing\Shadow $pValue = null)
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ class Column
|
||||
}
|
||||
|
||||
/**
|
||||
* Get column index.
|
||||
* Get column index as string eg: 'A'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
||||
@@ -59,7 +59,7 @@ class ColumnCellIterator extends CellIterator
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return ColumnCellIterator
|
||||
* @return $this
|
||||
*/
|
||||
public function resetStart($startRow = 1)
|
||||
{
|
||||
@@ -77,7 +77,7 @@ class ColumnCellIterator extends CellIterator
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return ColumnCellIterator
|
||||
* @return $this
|
||||
*/
|
||||
public function resetEnd($endRow = null)
|
||||
{
|
||||
@@ -94,7 +94,7 @@ class ColumnCellIterator extends CellIterator
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return ColumnCellIterator
|
||||
* @return $this
|
||||
*/
|
||||
public function seek($row = 1)
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ class ColumnDimension extends Dimension
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ColumnIndex.
|
||||
* Get column index as string eg: 'A'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -52,11 +52,11 @@ class ColumnDimension extends Dimension
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ColumnIndex.
|
||||
* Set column index as string eg: 'A'.
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return ColumnDimension
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumnIndex($pValue)
|
||||
{
|
||||
@@ -80,7 +80,7 @@ class ColumnDimension extends Dimension
|
||||
*
|
||||
* @param float $pValue
|
||||
*
|
||||
* @return ColumnDimension
|
||||
* @return $this
|
||||
*/
|
||||
public function setWidth($pValue)
|
||||
{
|
||||
@@ -104,7 +104,7 @@ class ColumnDimension extends Dimension
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return ColumnDimension
|
||||
* @return $this
|
||||
*/
|
||||
public function setAutoSize($pValue)
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@ class ColumnIterator implements \Iterator
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return ColumnIterator
|
||||
* @return $this
|
||||
*/
|
||||
public function resetStart($startColumn = 'A')
|
||||
{
|
||||
@@ -89,7 +89,7 @@ class ColumnIterator implements \Iterator
|
||||
*
|
||||
* @param string $endColumn The column address at which to stop iterating
|
||||
*
|
||||
* @return ColumnIterator
|
||||
* @return $this
|
||||
*/
|
||||
public function resetEnd($endColumn = null)
|
||||
{
|
||||
@@ -106,7 +106,7 @@ class ColumnIterator implements \Iterator
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return ColumnIterator
|
||||
* @return $this
|
||||
*/
|
||||
public function seek($column = 'A')
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ abstract class Dimension
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Dimension
|
||||
* @return $this
|
||||
*/
|
||||
public function setVisible($pValue)
|
||||
{
|
||||
@@ -87,7 +87,7 @@ abstract class Dimension
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Dimension
|
||||
* @return $this
|
||||
*/
|
||||
public function setOutlineLevel($pValue)
|
||||
{
|
||||
@@ -115,7 +115,7 @@ abstract class Dimension
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Dimension
|
||||
* @return $this
|
||||
*/
|
||||
public function setCollapsed($pValue)
|
||||
{
|
||||
@@ -139,7 +139,7 @@ abstract class Dimension
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return Dimension
|
||||
* @return $this
|
||||
*/
|
||||
public function setXfIndex($pValue)
|
||||
{
|
||||
|
||||
@@ -78,7 +78,7 @@ class Drawing extends BaseDrawing
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return Drawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setPath($pValue, $pVerifyFile = true)
|
||||
{
|
||||
@@ -88,7 +88,7 @@ class Drawing extends BaseDrawing
|
||||
|
||||
if ($this->width == 0 && $this->height == 0) {
|
||||
// Get width/height
|
||||
list($this->width, $this->height) = getimagesize($pValue);
|
||||
[$this->width, $this->height] = getimagesize($pValue);
|
||||
}
|
||||
} else {
|
||||
throw new PhpSpreadsheetException("File $pValue not found!");
|
||||
|
||||
@@ -100,7 +100,7 @@ class Shadow implements IComparable
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Shadow
|
||||
* @return $this
|
||||
*/
|
||||
public function setVisible($pValue)
|
||||
{
|
||||
@@ -124,7 +124,7 @@ class Shadow implements IComparable
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return Shadow
|
||||
* @return $this
|
||||
*/
|
||||
public function setBlurRadius($pValue)
|
||||
{
|
||||
@@ -148,7 +148,7 @@ class Shadow implements IComparable
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return Shadow
|
||||
* @return $this
|
||||
*/
|
||||
public function setDistance($pValue)
|
||||
{
|
||||
@@ -172,7 +172,7 @@ class Shadow implements IComparable
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return Shadow
|
||||
* @return $this
|
||||
*/
|
||||
public function setDirection($pValue)
|
||||
{
|
||||
@@ -196,7 +196,7 @@ class Shadow implements IComparable
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return Shadow
|
||||
* @return $this
|
||||
*/
|
||||
public function setAlignment($pValue)
|
||||
{
|
||||
@@ -220,7 +220,7 @@ class Shadow implements IComparable
|
||||
*
|
||||
* @param Color $pValue
|
||||
*
|
||||
* @return Shadow
|
||||
* @return $this
|
||||
*/
|
||||
public function setColor(Color $pValue = null)
|
||||
{
|
||||
@@ -244,7 +244,7 @@ class Shadow implements IComparable
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return Shadow
|
||||
* @return $this
|
||||
*/
|
||||
public function setAlpha($pValue)
|
||||
{
|
||||
|
||||
@@ -172,7 +172,7 @@ class HeaderFooter
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function setOddHeader($pValue)
|
||||
{
|
||||
@@ -196,7 +196,7 @@ class HeaderFooter
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function setOddFooter($pValue)
|
||||
{
|
||||
@@ -220,7 +220,7 @@ class HeaderFooter
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function setEvenHeader($pValue)
|
||||
{
|
||||
@@ -244,7 +244,7 @@ class HeaderFooter
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function setEvenFooter($pValue)
|
||||
{
|
||||
@@ -268,7 +268,7 @@ class HeaderFooter
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function setFirstHeader($pValue)
|
||||
{
|
||||
@@ -292,7 +292,7 @@ class HeaderFooter
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function setFirstFooter($pValue)
|
||||
{
|
||||
@@ -316,7 +316,7 @@ class HeaderFooter
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function setDifferentOddEven($pValue)
|
||||
{
|
||||
@@ -340,7 +340,7 @@ class HeaderFooter
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function setDifferentFirst($pValue)
|
||||
{
|
||||
@@ -364,7 +364,7 @@ class HeaderFooter
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function setScaleWithDocument($pValue)
|
||||
{
|
||||
@@ -388,7 +388,7 @@ class HeaderFooter
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function setAlignWithMargins($pValue)
|
||||
{
|
||||
@@ -403,7 +403,7 @@ class HeaderFooter
|
||||
* @param HeaderFooterDrawing $image
|
||||
* @param string $location
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function addImage(HeaderFooterDrawing $image, $location = self::IMAGE_HEADER_LEFT)
|
||||
{
|
||||
@@ -417,7 +417,7 @@ class HeaderFooter
|
||||
*
|
||||
* @param string $location
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function removeImage($location = self::IMAGE_HEADER_LEFT)
|
||||
{
|
||||
@@ -433,7 +433,7 @@ class HeaderFooter
|
||||
*
|
||||
* @param HeaderFooterDrawing[] $images
|
||||
*
|
||||
* @return HeaderFooter
|
||||
* @return $this
|
||||
*/
|
||||
public function setImages(array $images)
|
||||
{
|
||||
|
||||
@@ -74,7 +74,7 @@ class MemoryDrawing extends BaseDrawing
|
||||
*
|
||||
* @param resource $value
|
||||
*
|
||||
* @return MemoryDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setImageResource($value)
|
||||
{
|
||||
@@ -104,7 +104,7 @@ class MemoryDrawing extends BaseDrawing
|
||||
*
|
||||
* @param string $value see self::RENDERING_*
|
||||
*
|
||||
* @return MemoryDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setRenderingFunction($value)
|
||||
{
|
||||
@@ -128,7 +128,7 @@ class MemoryDrawing extends BaseDrawing
|
||||
*
|
||||
* @param string $value see self::MIMETYPE_*
|
||||
*
|
||||
* @return MemoryDrawing
|
||||
* @return $this
|
||||
*/
|
||||
public function setMimeType($value)
|
||||
{
|
||||
|
||||
@@ -68,7 +68,7 @@ class PageMargins
|
||||
*
|
||||
* @param float $pValue
|
||||
*
|
||||
* @return PageMargins
|
||||
* @return $this
|
||||
*/
|
||||
public function setLeft($pValue)
|
||||
{
|
||||
@@ -92,7 +92,7 @@ class PageMargins
|
||||
*
|
||||
* @param float $pValue
|
||||
*
|
||||
* @return PageMargins
|
||||
* @return $this
|
||||
*/
|
||||
public function setRight($pValue)
|
||||
{
|
||||
@@ -116,7 +116,7 @@ class PageMargins
|
||||
*
|
||||
* @param float $pValue
|
||||
*
|
||||
* @return PageMargins
|
||||
* @return $this
|
||||
*/
|
||||
public function setTop($pValue)
|
||||
{
|
||||
@@ -140,7 +140,7 @@ class PageMargins
|
||||
*
|
||||
* @param float $pValue
|
||||
*
|
||||
* @return PageMargins
|
||||
* @return $this
|
||||
*/
|
||||
public function setBottom($pValue)
|
||||
{
|
||||
@@ -164,7 +164,7 @@ class PageMargins
|
||||
*
|
||||
* @param float $pValue
|
||||
*
|
||||
* @return PageMargins
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeader($pValue)
|
||||
{
|
||||
@@ -188,7 +188,7 @@ class PageMargins
|
||||
*
|
||||
* @param float $pValue
|
||||
*
|
||||
* @return PageMargins
|
||||
* @return $this
|
||||
*/
|
||||
public function setFooter($pValue)
|
||||
{
|
||||
|
||||
@@ -180,7 +180,7 @@ class PageSetup
|
||||
* Print scaling. Valid values range from 10 to 400
|
||||
* This setting is overridden when fitToWidth and/or fitToHeight are in use
|
||||
*
|
||||
* @var int?
|
||||
* @var null|int
|
||||
*/
|
||||
private $scale = 100;
|
||||
|
||||
@@ -196,7 +196,7 @@ class PageSetup
|
||||
* Fit To Height
|
||||
* Number of vertical pages to fit on.
|
||||
*
|
||||
* @var int?
|
||||
* @var null|int
|
||||
*/
|
||||
private $fitToHeight = 1;
|
||||
|
||||
@@ -204,7 +204,7 @@ class PageSetup
|
||||
* Fit To Width
|
||||
* Number of horizontal pages to fit on.
|
||||
*
|
||||
* @var int?
|
||||
* @var null|int
|
||||
*/
|
||||
private $fitToWidth = 1;
|
||||
|
||||
@@ -272,7 +272,7 @@ class PageSetup
|
||||
*
|
||||
* @param int $pValue see self::PAPERSIZE_*
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setPaperSize($pValue)
|
||||
{
|
||||
@@ -296,7 +296,7 @@ class PageSetup
|
||||
*
|
||||
* @param string $pValue see self::ORIENTATION_*
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setOrientation($pValue)
|
||||
{
|
||||
@@ -308,7 +308,7 @@ class PageSetup
|
||||
/**
|
||||
* Get Scale.
|
||||
*
|
||||
* @return int?
|
||||
* @return null|int
|
||||
*/
|
||||
public function getScale()
|
||||
{
|
||||
@@ -325,7 +325,7 @@ class PageSetup
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setScale($pValue, $pUpdate = true)
|
||||
{
|
||||
@@ -358,7 +358,7 @@ class PageSetup
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setFitToPage($pValue)
|
||||
{
|
||||
@@ -370,7 +370,7 @@ class PageSetup
|
||||
/**
|
||||
* Get Fit To Height.
|
||||
*
|
||||
* @return int?
|
||||
* @return null|int
|
||||
*/
|
||||
public function getFitToHeight()
|
||||
{
|
||||
@@ -383,7 +383,7 @@ class PageSetup
|
||||
* @param null|int $pValue
|
||||
* @param bool $pUpdate Update fitToPage so it applies rather than scaling
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setFitToHeight($pValue, $pUpdate = true)
|
||||
{
|
||||
@@ -398,7 +398,7 @@ class PageSetup
|
||||
/**
|
||||
* Get Fit To Width.
|
||||
*
|
||||
* @return int?
|
||||
* @return null|int
|
||||
*/
|
||||
public function getFitToWidth()
|
||||
{
|
||||
@@ -411,7 +411,7 @@ class PageSetup
|
||||
* @param null|int $pValue
|
||||
* @param bool $pUpdate Update fitToPage so it applies rather than scaling
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setFitToWidth($pValue, $pUpdate = true)
|
||||
{
|
||||
@@ -454,7 +454,7 @@ class PageSetup
|
||||
*
|
||||
* @param array $pValue Containing start column and end column, empty array if option unset
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumnsToRepeatAtLeft(array $pValue)
|
||||
{
|
||||
@@ -469,7 +469,7 @@ class PageSetup
|
||||
* @param string $pStart eg: 'A'
|
||||
* @param string $pEnd eg: 'B'
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumnsToRepeatAtLeftByStartAndEnd($pStart, $pEnd)
|
||||
{
|
||||
@@ -509,7 +509,7 @@ class PageSetup
|
||||
*
|
||||
* @param array $pValue Containing start column and end column, empty array if option unset
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setRowsToRepeatAtTop(array $pValue)
|
||||
{
|
||||
@@ -524,7 +524,7 @@ class PageSetup
|
||||
* @param int $pStart eg: 1
|
||||
* @param int $pEnd eg: 1
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setRowsToRepeatAtTopByStartAndEnd($pStart, $pEnd)
|
||||
{
|
||||
@@ -548,7 +548,7 @@ class PageSetup
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setHorizontalCentered($value)
|
||||
{
|
||||
@@ -572,7 +572,7 @@ class PageSetup
|
||||
*
|
||||
* @param bool $value
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setVerticalCentered($value)
|
||||
{
|
||||
@@ -634,7 +634,7 @@ class PageSetup
|
||||
* Otherwise, the range identified by the value of $index will be removed from the series
|
||||
* Print areas are numbered from 1
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function clearPrintArea($index = 0)
|
||||
{
|
||||
@@ -671,7 +671,7 @@ class PageSetup
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setPrintArea($value, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE)
|
||||
{
|
||||
@@ -732,7 +732,7 @@ class PageSetup
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function addPrintArea($value, $index = -1)
|
||||
{
|
||||
@@ -762,7 +762,7 @@ class PageSetup
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE)
|
||||
{
|
||||
@@ -789,7 +789,7 @@ class PageSetup
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function addPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = -1)
|
||||
{
|
||||
@@ -815,7 +815,7 @@ class PageSetup
|
||||
*
|
||||
* @param int $value
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function setFirstPageNumber($value)
|
||||
{
|
||||
@@ -827,7 +827,7 @@ class PageSetup
|
||||
/**
|
||||
* Reset first page number.
|
||||
*
|
||||
* @return PageSetup
|
||||
* @return $this
|
||||
*/
|
||||
public function resetFirstPageNumber()
|
||||
{
|
||||
|
||||
@@ -172,7 +172,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setSheet($pValue)
|
||||
{
|
||||
@@ -196,7 +196,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setObjects($pValue)
|
||||
{
|
||||
@@ -220,7 +220,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setScenarios($pValue)
|
||||
{
|
||||
@@ -244,7 +244,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormatCells($pValue)
|
||||
{
|
||||
@@ -268,7 +268,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormatColumns($pValue)
|
||||
{
|
||||
@@ -292,7 +292,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setFormatRows($pValue)
|
||||
{
|
||||
@@ -316,7 +316,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setInsertColumns($pValue)
|
||||
{
|
||||
@@ -340,7 +340,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setInsertRows($pValue)
|
||||
{
|
||||
@@ -364,7 +364,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setInsertHyperlinks($pValue)
|
||||
{
|
||||
@@ -388,7 +388,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setDeleteColumns($pValue)
|
||||
{
|
||||
@@ -412,7 +412,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setDeleteRows($pValue)
|
||||
{
|
||||
@@ -436,7 +436,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setSelectLockedCells($pValue)
|
||||
{
|
||||
@@ -460,7 +460,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setSort($pValue)
|
||||
{
|
||||
@@ -484,7 +484,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setAutoFilter($pValue)
|
||||
{
|
||||
@@ -508,7 +508,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setPivotTables($pValue)
|
||||
{
|
||||
@@ -532,7 +532,7 @@ class Protection
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setSelectUnlockedCells($pValue)
|
||||
{
|
||||
@@ -557,7 +557,7 @@ class Protection
|
||||
* @param string $pValue
|
||||
* @param bool $pAlreadyHashed If the password has already been hashed, set this to true
|
||||
*
|
||||
* @return Protection
|
||||
* @return $this
|
||||
*/
|
||||
public function setPassword($pValue, $pAlreadyHashed = false)
|
||||
{
|
||||
|
||||
@@ -59,7 +59,7 @@ class RowCellIterator extends CellIterator
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return RowCellIterator
|
||||
* @return $this
|
||||
*/
|
||||
public function resetStart($startColumn = 'A')
|
||||
{
|
||||
@@ -77,7 +77,7 @@ class RowCellIterator extends CellIterator
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return RowCellIterator
|
||||
* @return $this
|
||||
*/
|
||||
public function resetEnd($endColumn = null)
|
||||
{
|
||||
@@ -95,7 +95,7 @@ class RowCellIterator extends CellIterator
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return RowCellIterator
|
||||
* @return $this
|
||||
*/
|
||||
public function seek($column = 'A')
|
||||
{
|
||||
|
||||
@@ -56,7 +56,7 @@ class RowDimension extends Dimension
|
||||
*
|
||||
* @param int $pValue
|
||||
*
|
||||
* @return RowDimension
|
||||
* @return $this
|
||||
*/
|
||||
public function setRowIndex($pValue)
|
||||
{
|
||||
@@ -80,7 +80,7 @@ class RowDimension extends Dimension
|
||||
*
|
||||
* @param float $pValue
|
||||
*
|
||||
* @return RowDimension
|
||||
* @return $this
|
||||
*/
|
||||
public function setRowHeight($pValue)
|
||||
{
|
||||
@@ -104,7 +104,7 @@ class RowDimension extends Dimension
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return RowDimension
|
||||
* @return $this
|
||||
*/
|
||||
public function setZeroHeight($pValue)
|
||||
{
|
||||
|
||||
@@ -64,7 +64,7 @@ class RowIterator implements \Iterator
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return RowIterator
|
||||
* @return $this
|
||||
*/
|
||||
public function resetStart($startRow = 1)
|
||||
{
|
||||
@@ -86,7 +86,7 @@ class RowIterator implements \Iterator
|
||||
*
|
||||
* @param int $endRow The row number at which to stop iterating
|
||||
*
|
||||
* @return RowIterator
|
||||
* @return $this
|
||||
*/
|
||||
public function resetEnd($endRow = null)
|
||||
{
|
||||
@@ -102,7 +102,7 @@ class RowIterator implements \Iterator
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return RowIterator
|
||||
* @return $this
|
||||
*/
|
||||
public function seek($row = 1)
|
||||
{
|
||||
|
||||
@@ -35,6 +35,16 @@ class SheetView
|
||||
*/
|
||||
private $zoomScaleNormal = 100;
|
||||
|
||||
/**
|
||||
* ShowZeros.
|
||||
*
|
||||
* If true, "null" values from a calculation will be shown as "0". This is the default Excel behaviour and can be changed
|
||||
* with the advanced worksheet option "Show a zero in cells that have zero value"
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $showZeros = true;
|
||||
|
||||
/**
|
||||
* View.
|
||||
*
|
||||
@@ -69,7 +79,7 @@ class SheetView
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return SheetView
|
||||
* @return $this
|
||||
*/
|
||||
public function setZoomScale($pValue)
|
||||
{
|
||||
@@ -102,7 +112,7 @@ class SheetView
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return SheetView
|
||||
* @return $this
|
||||
*/
|
||||
public function setZoomScaleNormal($pValue)
|
||||
{
|
||||
@@ -115,6 +125,24 @@ class SheetView
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ShowZeroes setting.
|
||||
*
|
||||
* @param bool $pValue
|
||||
*/
|
||||
public function setShowZeros($pValue)
|
||||
{
|
||||
$this->showZeros = $pValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getShowZeros()
|
||||
{
|
||||
return $this->showZeros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get View.
|
||||
*
|
||||
@@ -137,7 +165,7 @@ class SheetView
|
||||
*
|
||||
* @throws PhpSpreadsheetException
|
||||
*
|
||||
* @return SheetView
|
||||
* @return $this
|
||||
*/
|
||||
public function setView($pValue)
|
||||
{
|
||||
|
||||
@@ -647,7 +647,7 @@ class Worksheet implements IComparable
|
||||
/**
|
||||
* Refresh column dimensions.
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function refreshColumnDimensions()
|
||||
{
|
||||
@@ -666,7 +666,7 @@ class Worksheet implements IComparable
|
||||
/**
|
||||
* Refresh row dimensions.
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function refreshRowDimensions()
|
||||
{
|
||||
@@ -690,7 +690,7 @@ class Worksheet implements IComparable
|
||||
public function calculateWorksheetDimension()
|
||||
{
|
||||
// Return
|
||||
return 'A1' . ':' . $this->getHighestColumn() . $this->getHighestRow();
|
||||
return 'A1:' . $this->getHighestColumn() . $this->getHighestRow();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -701,13 +701,13 @@ class Worksheet implements IComparable
|
||||
public function calculateWorksheetDataDimension()
|
||||
{
|
||||
// Return
|
||||
return 'A1' . ':' . $this->getHighestDataColumn() . $this->getHighestDataRow();
|
||||
return 'A1:' . $this->getHighestDataColumn() . $this->getHighestDataRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate widths for auto-size columns.
|
||||
*
|
||||
* @return Worksheet;
|
||||
* @return $this
|
||||
*/
|
||||
public function calculateColumnWidths()
|
||||
{
|
||||
@@ -797,7 +797,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param Spreadsheet $parent
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function rebindParent(Spreadsheet $parent)
|
||||
{
|
||||
@@ -838,7 +838,7 @@ class Worksheet implements IComparable
|
||||
* @param bool $validate False to skip validation of new title. WARNING: This should only be set
|
||||
* at parse time (by Readers), where titles can be assumed to be valid.
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setTitle($pValue, $updateFormulaCellReferences = true, $validate = true)
|
||||
{
|
||||
@@ -913,7 +913,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param string $value Sheet state (visible, hidden, veryHidden)
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setSheetState($value)
|
||||
{
|
||||
@@ -937,7 +937,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param PageSetup $pValue
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setPageSetup(PageSetup $pValue)
|
||||
{
|
||||
@@ -961,7 +961,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param PageMargins $pValue
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setPageMargins(PageMargins $pValue)
|
||||
{
|
||||
@@ -985,7 +985,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param HeaderFooter $pValue
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setHeaderFooter(HeaderFooter $pValue)
|
||||
{
|
||||
@@ -1009,7 +1009,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param SheetView $pValue
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setSheetView(SheetView $pValue)
|
||||
{
|
||||
@@ -1033,7 +1033,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param Protection $pValue
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setProtection(Protection $pValue)
|
||||
{
|
||||
@@ -1119,7 +1119,7 @@ class Worksheet implements IComparable
|
||||
* @param string $pCoordinate Coordinate of the cell, eg: 'A1'
|
||||
* @param mixed $pValue Value of the cell
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellValue($pCoordinate, $pValue)
|
||||
{
|
||||
@@ -1135,7 +1135,7 @@ class Worksheet implements IComparable
|
||||
* @param int $row Numeric row coordinate of the cell
|
||||
* @param mixed $value Value of the cell
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellValueByColumnAndRow($columnIndex, $row, $value)
|
||||
{
|
||||
@@ -1151,7 +1151,7 @@ class Worksheet implements IComparable
|
||||
* @param mixed $pValue Value of the cell
|
||||
* @param string $pDataType Explicit data type, see DataType::TYPE_*
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellValueExplicit($pCoordinate, $pValue, $pDataType)
|
||||
{
|
||||
@@ -1169,7 +1169,7 @@ class Worksheet implements IComparable
|
||||
* @param mixed $value Value of the cell
|
||||
* @param string $dataType Explicit data type, see DataType::TYPE_*
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellValueExplicitByColumnAndRow($columnIndex, $row, $value, $dataType)
|
||||
{
|
||||
@@ -1441,7 +1441,7 @@ class Worksheet implements IComparable
|
||||
$this->parent->setActiveSheetIndex($this->parent->getIndex($this));
|
||||
|
||||
// set cell coordinate as active
|
||||
$this->setSelectedCells(strtoupper($pCellCoordinate));
|
||||
$this->setSelectedCells($pCellCoordinate);
|
||||
|
||||
return $this->parent->getCellXfSupervisor();
|
||||
}
|
||||
@@ -1480,7 +1480,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param string $pCoordinate eg: 'A1'
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function removeConditionalStyles($pCoordinate)
|
||||
{
|
||||
@@ -1505,7 +1505,7 @@ class Worksheet implements IComparable
|
||||
* @param string $pCoordinate eg: 'A1'
|
||||
* @param $pValue Conditional[]
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setConditionalStyles($pCoordinate, $pValue)
|
||||
{
|
||||
@@ -1545,7 +1545,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function duplicateStyle(Style $pCellStyle, $pRange)
|
||||
{
|
||||
@@ -1561,7 +1561,7 @@ class Worksheet implements IComparable
|
||||
}
|
||||
|
||||
// Calculate range outer borders
|
||||
list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($pRange . ':' . $pRange);
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($pRange . ':' . $pRange);
|
||||
|
||||
// Make sure we can loop upwards on rows and columns
|
||||
if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) {
|
||||
@@ -1590,7 +1590,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function duplicateConditionalStyle(array $pCellStyle, $pRange = '')
|
||||
{
|
||||
@@ -1601,7 +1601,7 @@ class Worksheet implements IComparable
|
||||
}
|
||||
|
||||
// Calculate range outer borders
|
||||
list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($pRange . ':' . $pRange);
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($pRange . ':' . $pRange);
|
||||
|
||||
// Make sure we can loop upwards on rows and columns
|
||||
if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) {
|
||||
@@ -1628,7 +1628,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setBreak($pCoordinate, $pBreak)
|
||||
{
|
||||
@@ -1657,7 +1657,7 @@ class Worksheet implements IComparable
|
||||
* @param int $row Numeric row coordinate of the cell
|
||||
* @param int $break Break type (type of Worksheet::BREAK_*)
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setBreakByColumnAndRow($columnIndex, $row, $break)
|
||||
{
|
||||
@@ -1681,7 +1681,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function mergeCells($pRange)
|
||||
{
|
||||
@@ -1726,7 +1726,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function mergeCellsByColumnAndRow($columnIndex1, $row1, $columnIndex2, $row2)
|
||||
{
|
||||
@@ -1742,7 +1742,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function unmergeCells($pRange)
|
||||
{
|
||||
@@ -1772,7 +1772,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function unmergeCellsByColumnAndRow($columnIndex1, $row1, $columnIndex2, $row2)
|
||||
{
|
||||
@@ -1797,7 +1797,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param array $pValue
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setMergeCells(array $pValue)
|
||||
{
|
||||
@@ -1813,7 +1813,7 @@ class Worksheet implements IComparable
|
||||
* @param string $pPassword Password to unlock the protection
|
||||
* @param bool $pAlreadyHashed If the password has already been hashed, set this to true
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function protectCells($pRange, $pPassword, $pAlreadyHashed = false)
|
||||
{
|
||||
@@ -1838,7 +1838,7 @@ class Worksheet implements IComparable
|
||||
* @param string $password Password to unlock the protection
|
||||
* @param bool $alreadyHashed If the password has already been hashed, set this to true
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function protectCellsByColumnAndRow($columnIndex1, $row1, $columnIndex2, $row2, $password, $alreadyHashed = false)
|
||||
{
|
||||
@@ -1854,7 +1854,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function unprotectCells($pRange)
|
||||
{
|
||||
@@ -1880,7 +1880,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function unprotectCellsByColumnAndRow($columnIndex1, $row1, $columnIndex2, $row2)
|
||||
{
|
||||
@@ -1917,7 +1917,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setAutoFilter($pValue)
|
||||
{
|
||||
@@ -1940,7 +1940,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setAutoFilterByColumnAndRow($columnIndex1, $row1, $columnIndex2, $row2)
|
||||
{
|
||||
@@ -1954,7 +1954,7 @@ class Worksheet implements IComparable
|
||||
/**
|
||||
* Remove autofilter.
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function removeAutoFilter()
|
||||
{
|
||||
@@ -1987,7 +1987,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function freezePane($cell, $topLeftCell = null)
|
||||
{
|
||||
@@ -2012,7 +2012,7 @@ class Worksheet implements IComparable
|
||||
* @param int $columnIndex Numeric column coordinate of the cell
|
||||
* @param int $row Numeric row coordinate of the cell
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function freezePaneByColumnAndRow($columnIndex, $row)
|
||||
{
|
||||
@@ -2022,7 +2022,7 @@ class Worksheet implements IComparable
|
||||
/**
|
||||
* Unfreeze Pane.
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function unfreezePane()
|
||||
{
|
||||
@@ -2047,7 +2047,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function insertNewRowBefore($pBefore, $pNumRows = 1)
|
||||
{
|
||||
@@ -2069,7 +2069,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function insertNewColumnBefore($pBefore, $pNumCols = 1)
|
||||
{
|
||||
@@ -2091,7 +2091,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function insertNewColumnBeforeByIndex($beforeColumnIndex, $pNumCols = 1)
|
||||
{
|
||||
@@ -2110,22 +2110,31 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function removeRow($pRow, $pNumRows = 1)
|
||||
{
|
||||
if ($pRow >= 1) {
|
||||
$highestRow = $this->getHighestDataRow();
|
||||
$objReferenceHelper = ReferenceHelper::getInstance();
|
||||
$objReferenceHelper->insertNewBefore('A' . ($pRow + $pNumRows), 0, -$pNumRows, $this);
|
||||
for ($r = 0; $r < $pNumRows; ++$r) {
|
||||
$this->getCellCollection()->removeRow($highestRow);
|
||||
--$highestRow;
|
||||
}
|
||||
} else {
|
||||
if ($pRow < 1) {
|
||||
throw new Exception('Rows to be deleted should at least start from row 1.');
|
||||
}
|
||||
|
||||
$highestRow = $this->getHighestDataRow();
|
||||
$removedRowsCounter = 0;
|
||||
|
||||
for ($r = 0; $r < $pNumRows; ++$r) {
|
||||
if ($pRow + $r <= $highestRow) {
|
||||
$this->getCellCollection()->removeRow($pRow + $r);
|
||||
++$removedRowsCounter;
|
||||
}
|
||||
}
|
||||
|
||||
$objReferenceHelper = ReferenceHelper::getInstance();
|
||||
$objReferenceHelper->insertNewBefore('A' . ($pRow + $pNumRows), 0, -$pNumRows, $this);
|
||||
for ($r = 0; $r < $removedRowsCounter; ++$r) {
|
||||
$this->getCellCollection()->removeRow($highestRow);
|
||||
--$highestRow;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -2137,23 +2146,35 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function removeColumn($pColumn, $pNumCols = 1)
|
||||
{
|
||||
if (!is_numeric($pColumn)) {
|
||||
$highestColumn = $this->getHighestDataColumn();
|
||||
$pColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($pColumn) + $pNumCols);
|
||||
$objReferenceHelper = ReferenceHelper::getInstance();
|
||||
$objReferenceHelper->insertNewBefore($pColumn . '1', -$pNumCols, 0, $this);
|
||||
for ($c = 0; $c < $pNumCols; ++$c) {
|
||||
$this->getCellCollection()->removeColumn($highestColumn);
|
||||
$highestColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($highestColumn) - 1);
|
||||
}
|
||||
} else {
|
||||
if (is_numeric($pColumn)) {
|
||||
throw new Exception('Column references should not be numeric.');
|
||||
}
|
||||
|
||||
$highestColumn = $this->getHighestDataColumn();
|
||||
$highestColumnIndex = Coordinate::columnIndexFromString($highestColumn);
|
||||
$pColumnIndex = Coordinate::columnIndexFromString($pColumn);
|
||||
|
||||
if ($pColumnIndex > $highestColumnIndex) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$pColumn = Coordinate::stringFromColumnIndex($pColumnIndex + $pNumCols);
|
||||
$objReferenceHelper = ReferenceHelper::getInstance();
|
||||
$objReferenceHelper->insertNewBefore($pColumn . '1', -$pNumCols, 0, $this);
|
||||
|
||||
$maxPossibleColumnsToBeRemoved = $highestColumnIndex - $pColumnIndex + 1;
|
||||
|
||||
for ($c = 0, $n = min($maxPossibleColumnsToBeRemoved, $pNumCols); $c < $n; ++$c) {
|
||||
$this->getCellCollection()->removeColumn($highestColumn);
|
||||
$highestColumn = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($highestColumn) - 1);
|
||||
}
|
||||
|
||||
$this->garbageCollect();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -2165,7 +2186,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function removeColumnByIndex($columnIndex, $numColumns = 1)
|
||||
{
|
||||
@@ -2191,7 +2212,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param bool $pValue Show gridlines (true/false)
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowGridlines($pValue)
|
||||
{
|
||||
@@ -2215,7 +2236,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param bool $pValue Print gridlines (true/false)
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setPrintGridlines($pValue)
|
||||
{
|
||||
@@ -2239,7 +2260,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param bool $pValue Show row and column headers (true/false)
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowRowColHeaders($pValue)
|
||||
{
|
||||
@@ -2263,7 +2284,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param bool $pValue Show summary below (true/false)
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowSummaryBelow($pValue)
|
||||
{
|
||||
@@ -2287,7 +2308,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param bool $pValue Show summary right (true/false)
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setShowSummaryRight($pValue)
|
||||
{
|
||||
@@ -2311,7 +2332,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param Comment[] $pValue
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setComments(array $pValue)
|
||||
{
|
||||
@@ -2392,7 +2413,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param string $pCoordinate Cell (i.e. A1)
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setSelectedCell($pCoordinate)
|
||||
{
|
||||
@@ -2404,7 +2425,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param string $pCoordinate Cell range, examples: 'A1', 'B2:G5', 'A:C', '3:6'
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setSelectedCells($pCoordinate)
|
||||
{
|
||||
@@ -2424,7 +2445,7 @@ class Worksheet implements IComparable
|
||||
$pCoordinate = preg_replace('/^(\d+):(\d+)$/', 'A${1}:XFD${2}', $pCoordinate);
|
||||
|
||||
if (Coordinate::coordinateIsRange($pCoordinate)) {
|
||||
list($first) = Coordinate::splitRange($pCoordinate);
|
||||
[$first] = Coordinate::splitRange($pCoordinate);
|
||||
$this->activeCell = $first[0];
|
||||
} else {
|
||||
$this->activeCell = $pCoordinate;
|
||||
@@ -2442,7 +2463,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setSelectedCellByColumnAndRow($columnIndex, $row)
|
||||
{
|
||||
@@ -2464,7 +2485,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @param bool $value Right-to-left true/false
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setRightToLeft($value)
|
||||
{
|
||||
@@ -2483,7 +2504,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function fromArray(array $source, $nullValue = null, $startCell = 'A1', $strictNullComparison = false)
|
||||
{
|
||||
@@ -2493,7 +2514,7 @@ class Worksheet implements IComparable
|
||||
}
|
||||
|
||||
// start coordinate
|
||||
list($startColumn, $startRow) = Coordinate::coordinateFromString($startCell);
|
||||
[$startColumn, $startRow] = Coordinate::coordinateFromString($startCell);
|
||||
|
||||
// Loop through $source
|
||||
foreach ($source as $rowData) {
|
||||
@@ -2535,7 +2556,7 @@ class Worksheet implements IComparable
|
||||
// Returnvalue
|
||||
$returnValue = [];
|
||||
// Identify the range that we need to extract from the worksheet
|
||||
list($rangeStart, $rangeEnd) = Coordinate::rangeBoundaries($pRange);
|
||||
[$rangeStart, $rangeEnd] = Coordinate::rangeBoundaries($pRange);
|
||||
$minCol = Coordinate::stringFromColumnIndex($rangeStart[0]);
|
||||
$minRow = $rangeStart[1];
|
||||
$maxCol = Coordinate::stringFromColumnIndex($rangeEnd[0]);
|
||||
@@ -2545,11 +2566,11 @@ class Worksheet implements IComparable
|
||||
// Loop through rows
|
||||
$r = -1;
|
||||
for ($row = $minRow; $row <= $maxRow; ++$row) {
|
||||
$rRef = ($returnCellRef) ? $row : ++$r;
|
||||
$rRef = $returnCellRef ? $row : ++$r;
|
||||
$c = -1;
|
||||
// Loop through columns in the current row
|
||||
for ($col = $minCol; $col != $maxCol; ++$col) {
|
||||
$cRef = ($returnCellRef) ? $col : ++$c;
|
||||
$cRef = $returnCellRef ? $col : ++$c;
|
||||
// Using getCell() will create a new cell if it doesn't already exist. We don't want that to happen
|
||||
// so we test and retrieve directly against cellCollection
|
||||
if ($this->cellCollection->has($col . $row)) {
|
||||
@@ -2668,7 +2689,7 @@ class Worksheet implements IComparable
|
||||
/**
|
||||
* Run PhpSpreadsheet garbage collector.
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function garbageCollect()
|
||||
{
|
||||
@@ -2768,7 +2789,7 @@ class Worksheet implements IComparable
|
||||
* @param string $pCellCoordinate Cell coordinate to insert hyperlink, eg: 'A1'
|
||||
* @param null|Hyperlink $pHyperlink
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setHyperlink($pCellCoordinate, Hyperlink $pHyperlink = null)
|
||||
{
|
||||
@@ -2829,7 +2850,7 @@ class Worksheet implements IComparable
|
||||
* @param string $pCellCoordinate Cell coordinate to insert data validation, eg: 'A1'
|
||||
* @param null|DataValidation $pDataValidation
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setDataValidation($pCellCoordinate, DataValidation $pDataValidation = null)
|
||||
{
|
||||
@@ -2896,9 +2917,8 @@ class Worksheet implements IComparable
|
||||
$rangeSet = $rangeBoundaries[0][0] . $rangeBoundaries[0][1] . ':' . $rangeBoundaries[1][0] . $rangeBoundaries[1][1];
|
||||
}
|
||||
unset($rangeSet);
|
||||
$stRange = implode(' ', $rangeBlocks);
|
||||
|
||||
return $stRange;
|
||||
return implode(' ', $rangeBlocks);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2918,7 +2938,7 @@ class Worksheet implements IComparable
|
||||
/**
|
||||
* Reset tab color.
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function resetTabColor()
|
||||
{
|
||||
@@ -2941,13 +2961,11 @@ class Worksheet implements IComparable
|
||||
/**
|
||||
* Copy worksheet (!= clone!).
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return static
|
||||
*/
|
||||
public function copy()
|
||||
{
|
||||
$copied = clone $this;
|
||||
|
||||
return $copied;
|
||||
return clone $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2994,7 +3012,7 @@ class Worksheet implements IComparable
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Worksheet
|
||||
* @return $this
|
||||
*/
|
||||
public function setCodeName($pValue, $validate = true)
|
||||
{
|
||||
@@ -3034,7 +3052,7 @@ class Worksheet implements IComparable
|
||||
}
|
||||
}
|
||||
|
||||
$pValue = $pValue . '_' . $i; // ok, we have a valid name
|
||||
$pValue .= '_' . $i; // ok, we have a valid name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ class Csv extends BaseWriter
|
||||
*
|
||||
* @param string $pValue Delimiter, defaults to ','
|
||||
*
|
||||
* @return CSV
|
||||
* @return $this
|
||||
*/
|
||||
public function setDelimiter($pValue)
|
||||
{
|
||||
@@ -171,7 +171,7 @@ class Csv extends BaseWriter
|
||||
*
|
||||
* @param string $pValue Enclosure, defaults to "
|
||||
*
|
||||
* @return CSV
|
||||
* @return $this
|
||||
*/
|
||||
public function setEnclosure($pValue)
|
||||
{
|
||||
@@ -198,7 +198,7 @@ class Csv extends BaseWriter
|
||||
*
|
||||
* @param string $pValue Line ending, defaults to OS line ending (PHP_EOL)
|
||||
*
|
||||
* @return CSV
|
||||
* @return $this
|
||||
*/
|
||||
public function setLineEnding($pValue)
|
||||
{
|
||||
@@ -222,7 +222,7 @@ class Csv extends BaseWriter
|
||||
*
|
||||
* @param bool $pValue Use UTF-8 byte-order mark? Defaults to false
|
||||
*
|
||||
* @return CSV
|
||||
* @return $this
|
||||
*/
|
||||
public function setUseBOM($pValue)
|
||||
{
|
||||
@@ -246,7 +246,7 @@ class Csv extends BaseWriter
|
||||
*
|
||||
* @param bool $pValue Use separator line? Defaults to false
|
||||
*
|
||||
* @return CSV
|
||||
* @return $this
|
||||
*/
|
||||
public function setIncludeSeparatorLine($pValue)
|
||||
{
|
||||
@@ -271,7 +271,7 @@ class Csv extends BaseWriter
|
||||
* @param bool $pValue Set the file to be written as a fully Excel compatible csv file
|
||||
* Note that this overrides other settings such as useBOM, enclosure and delimiter
|
||||
*
|
||||
* @return CSV
|
||||
* @return $this
|
||||
*/
|
||||
public function setExcelCompatibility($pValue)
|
||||
{
|
||||
@@ -295,7 +295,7 @@ class Csv extends BaseWriter
|
||||
*
|
||||
* @param int $pValue Sheet index
|
||||
*
|
||||
* @return CSV
|
||||
* @return $this
|
||||
*/
|
||||
public function setSheetIndex($pValue)
|
||||
{
|
||||
|
||||
@@ -62,6 +62,13 @@ class Html extends BaseWriter
|
||||
*/
|
||||
private $useInlineCss = false;
|
||||
|
||||
/**
|
||||
* Use embedded CSS?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $useEmbeddedCSS = true;
|
||||
|
||||
/**
|
||||
* Array of CSS styles.
|
||||
*
|
||||
@@ -290,7 +297,7 @@ class Html extends BaseWriter
|
||||
*
|
||||
* @param int $pValue Sheet index
|
||||
*
|
||||
* @return HTML
|
||||
* @return $this
|
||||
*/
|
||||
public function setSheetIndex($pValue)
|
||||
{
|
||||
@@ -314,7 +321,7 @@ class Html extends BaseWriter
|
||||
*
|
||||
* @param bool $pValue Flag indicating whether the sheet navigation block should be generated or not
|
||||
*
|
||||
* @return HTML
|
||||
* @return $this
|
||||
*/
|
||||
public function setGenerateSheetNavigationBlock($pValue)
|
||||
{
|
||||
@@ -325,6 +332,8 @@ class Html extends BaseWriter
|
||||
|
||||
/**
|
||||
* Write all sheets (resets sheetIndex to NULL).
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function writeAllSheets()
|
||||
{
|
||||
@@ -643,7 +652,10 @@ class Html extends BaseWriter
|
||||
} else {
|
||||
$imageDetails = getimagesize($filename);
|
||||
if ($fp = fopen($filename, 'rb', 0)) {
|
||||
$picture = fread($fp, filesize($filename));
|
||||
$picture = '';
|
||||
while (!feof($fp)) {
|
||||
$picture .= fread($fp, 1024);
|
||||
}
|
||||
fclose($fp);
|
||||
// base64 encode the binary data, then break it
|
||||
// into chunks according to RFC 2045 semantics
|
||||
@@ -888,8 +900,8 @@ class Html extends BaseWriter
|
||||
$css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = $width . 'pt';
|
||||
|
||||
if ($columnDimension->getVisible() === false) {
|
||||
$css['table.sheet' . $sheetIndex . ' col.col' . $column]['visibility'] = 'collapse';
|
||||
$css['table.sheet' . $sheetIndex . ' col.col' . $column]['*display'] = 'none'; // target IE6+7
|
||||
$css['table.sheet' . $sheetIndex . ' .column' . $column]['visibility'] = 'collapse';
|
||||
$css['table.sheet' . $sheetIndex . ' .column' . $column]['display'] = 'none'; // target IE6+7
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -950,15 +962,12 @@ class Html extends BaseWriter
|
||||
private function createCSSStyle(Style $pStyle)
|
||||
{
|
||||
// Create CSS
|
||||
$css = array_merge(
|
||||
return array_merge(
|
||||
$this->createCSSStyleAlignment($pStyle->getAlignment()),
|
||||
$this->createCSSStyleBorders($pStyle->getBorders()),
|
||||
$this->createCSSStyleFont($pStyle->getFont()),
|
||||
$this->createCSSStyleFill($pStyle->getFill())
|
||||
);
|
||||
|
||||
// Return
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1051,9 +1060,8 @@ class Html extends BaseWriter
|
||||
{
|
||||
// Create CSS - add !important to non-none border styles for merged cells
|
||||
$borderStyle = $this->mapBorderStyle($pStyle->getBorderStyle());
|
||||
$css = $borderStyle . ' #' . $pStyle->getColor()->getRGB() . (($borderStyle == 'none') ? '' : ' !important');
|
||||
|
||||
return $css;
|
||||
return $borderStyle . ' #' . $pStyle->getColor()->getRGB() . (($borderStyle == 'none') ? '' : ' !important');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1102,7 +1110,9 @@ class Html extends BaseWriter
|
||||
|
||||
// Construct HTML
|
||||
$html = '';
|
||||
$html .= $this->setMargins($pSheet);
|
||||
if ($this->useEmbeddedCSS) {
|
||||
$html .= $this->setMargins($pSheet);
|
||||
}
|
||||
|
||||
if (!$this->useInlineCss) {
|
||||
$gridlines = $pSheet->getShowGridlines() ? ' gridlines' : '';
|
||||
@@ -1141,9 +1151,7 @@ class Html extends BaseWriter
|
||||
*/
|
||||
private function generateTableFooter()
|
||||
{
|
||||
$html = ' </table>' . PHP_EOL;
|
||||
|
||||
return $html;
|
||||
return ' </table>' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1432,7 +1440,7 @@ class Html extends BaseWriter
|
||||
*
|
||||
* @param string $pValue
|
||||
*
|
||||
* @return HTML
|
||||
* @return $this
|
||||
*/
|
||||
public function setImagesRoot($pValue)
|
||||
{
|
||||
@@ -1456,7 +1464,7 @@ class Html extends BaseWriter
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return HTML
|
||||
* @return $this
|
||||
*/
|
||||
public function setEmbedImages($pValue)
|
||||
{
|
||||
@@ -1480,7 +1488,7 @@ class Html extends BaseWriter
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return HTML
|
||||
* @return $this
|
||||
*/
|
||||
public function setUseInlineCss($pValue)
|
||||
{
|
||||
@@ -1489,6 +1497,30 @@ class Html extends BaseWriter
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get use embedded CSS?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseEmbeddedCSS()
|
||||
{
|
||||
return $this->useEmbeddedCSS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set use embedded CSS?
|
||||
*
|
||||
* @param bool $pValue
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setUseEmbeddedCSS($pValue)
|
||||
{
|
||||
$this->useEmbeddedCSS = $pValue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add color to formatted string as inline style.
|
||||
*
|
||||
@@ -1538,14 +1570,14 @@ class Html extends BaseWriter
|
||||
|
||||
// loop through all Excel merged cells
|
||||
foreach ($sheet->getMergeCells() as $cells) {
|
||||
list($cells) = Coordinate::splitRange($cells);
|
||||
[$cells] = Coordinate::splitRange($cells);
|
||||
$first = $cells[0];
|
||||
$last = $cells[1];
|
||||
|
||||
list($fc, $fr) = Coordinate::coordinateFromString($first);
|
||||
[$fc, $fr] = Coordinate::coordinateFromString($first);
|
||||
$fc = Coordinate::columnIndexFromString($fc) - 1;
|
||||
|
||||
list($lc, $lr) = Coordinate::coordinateFromString($last);
|
||||
[$lc, $lr] = Coordinate::coordinateFromString($last);
|
||||
$lc = Coordinate::columnIndexFromString($lc) - 1;
|
||||
|
||||
// loop through the individual cells in the individual merge
|
||||
|
||||
@@ -167,7 +167,7 @@ class Ods extends BaseWriter
|
||||
*
|
||||
* @param Spreadsheet $spreadsheet PhpSpreadsheet object
|
||||
*
|
||||
* @return self
|
||||
* @return $this
|
||||
*/
|
||||
public function setSpreadsheet(Spreadsheet $spreadsheet)
|
||||
{
|
||||
|
||||
@@ -314,7 +314,7 @@ class Content extends WriterPart
|
||||
}
|
||||
|
||||
if ($size = $font->getSize()) {
|
||||
$writer->writeAttribute('fo:font-size', sprintf('%.1fpt', $size));
|
||||
$writer->writeAttribute('fo:font-size', sprintf('%.1Fpt', $size));
|
||||
}
|
||||
|
||||
if ($font->getUnderline() && $font->getUnderline() != Font::UNDERLINE_NONE) {
|
||||
@@ -383,7 +383,7 @@ class Content extends WriterPart
|
||||
}
|
||||
|
||||
$mergeRange = Coordinate::splitRange($cell->getMergeRange());
|
||||
list($startCell, $endCell) = $mergeRange[0];
|
||||
[$startCell, $endCell] = $mergeRange[0];
|
||||
$start = Coordinate::coordinateFromString($startCell);
|
||||
$end = Coordinate::coordinateFromString($endCell);
|
||||
$columnSpan = Coordinate::columnIndexFromString($end[0]) - Coordinate::columnIndexFromString($start[0]) + 1;
|
||||
|
||||
@@ -150,7 +150,7 @@ abstract class Pdf extends Html
|
||||
*
|
||||
* @param string $fontName
|
||||
*
|
||||
* @return Pdf
|
||||
* @return $this
|
||||
*/
|
||||
public function setFont($fontName)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user