TextData - Minor Changes, Test Coverage (#2151)
* PHP8.1 Deprecation Passing Null to String Function
For each of the files in this PR, one or more statements can pass a null to string functions like strlower. This is deprecated in PHP8.1, and, when deprecated messages are enabled, causes many tests to error out. In every case, use coercion to pass null string rather than null.
* TextData - Minor Changes, Test Coverage
Per agreement on a previous push, I looked into standardizing the initialization of the TextData functions (like Engineering and MathTrig), with particular regard for avoiding multiple later null coercions. This simplifies the code quite a bit. This PR also increases coverage to 100% for all TextData modules. All entries in Phpstan baseline for non-deprecated TEXTDATA functions are removed. There were some minor bugfixes.
Whereas Excel (and Gnumeric) treat booleans when supplied as strings as 'TRUE' or 'FALSE', ODS treats them as '1' or '0'. Unlike Excel, ODS generally does not allow bool for int arguments; it does, however, allow them for FIND and SEARCH. ODS allows boolean for into for SUBSTITUTE even though Excel doesn't. ODS allows bool for string for NUMBERVALUE and VALUE even though Excel doesn't. ODS accepts 0 as an argument for CHAR; Excel doesn't. Most of this seems like random decisions on the part of the developers; I've done my best to follow the products in each case. There is a new test member devoted to ODS tests.
Gnumeric has an anomaly vis-a-vis the others - if length is supplied to LEFT/MID/RIGHT as null, Gnumeric treats it as 0 rather than 1.
All tests now take place in the context of a spreadsheet ...
Except for RETURNSTRING, which is not the implementation of an Excel function, and is referred to in the rest of PhpSpreadsheet only in the unit tests for itself. It should probably be deprecated, but that is not part of this PR, just in case there is some reason for it that I couldn't discern.
I have tried to make the first line of each doc block identify the Excel function name rather than its name in PhpSpreadsheet. I think it makes things more comprehensible.
Some tests call Settings::setLocale, but there was no Settings::getLocale. At the end of the tests which do it, they invoke setLocale('EN-US'), which, in a practical sense, is sufficient. However, in theory it would be better for them to get the current locale before changing it, then changing it back to the original when the time came. I have added getLocale and made the appropriate testing change.
The CHAR function took an interesting turn. One can set the value of a cell to, say, CHAR(2), the ASCII/UTF-8 representation of a control character, which is not legal in certain contexts. The only Reader/Writer that could handle this without problems is Xls, which deals with binary data all the time. However, if you tried to write it to Xlsx, Excel would not be able to open the resulting file because of what it considers an illegal character. I changed the Xlsx writer to escape such characters when writing the value of a string function. I did not make any other changes to the Xlsx writer - it seems to me that setting a cell to CHAR(2) is legitimate, but setting it to say `"\x02"` seems less likely to be legitimate, so the latter will still fail (although `="\x02"` should work). The Xlsx reader already supports the escape mechanism that I added to the writer.
CHAR control character and Ods - not supported by either Reader or Writer. I did not attempt to add this now. There is lots still missing from ODS, and this item just can't be a high priority amongst all of those.
CHAR control character and Csv - it is supported by reader and writer if the file has a csv extension. However, trying to guess the mime type without an extension - the control character makes mime_get_type guess application/octet-stream, and PhpSpreadsheet therefore thinks that Csv can't read it.
CHAR control character and Html. Actual use of the control character in the file is subject to the same problems as Xml (i.e. Xlsx and Ods). It wasn't terribly difficult to get the Html Writer to change `"\x02"` to "``". I believe that this is technically legal; however, DOMDocument.loadHTML rejects it as an illegal entity, and I am not convinced that it is wrong to do so, so I haven't changed the Html writer.
* Scrutinizer
Correct 3 minor errors.
This commit is contained in:
parent
55b95201ab
commit
4f06d84248
|
|
@ -1320,11 +1320,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\:\\:TRIMSPACES\\(\\) should return string but returns string\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\:\\:CONCATENATE\\(\\) has parameter \\$args with no typehint specified\\.$#"
|
||||
count: 1
|
||||
|
|
@ -1340,96 +1335,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\\\CharacterConvert\\:\\:character\\(\\) should return string but returns string\\|false\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/CharacterConvert.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\\\CharacterConvert\\:\\:unicodeToOrd\\(\\) has no return typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/CharacterConvert.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\\\CharacterConvert\\:\\:unicodeToOrd\\(\\) has parameter \\$character with no typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/CharacterConvert.php
|
||||
|
||||
-
|
||||
message: "#^Cannot access offset 1 on array\\|false\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/CharacterConvert.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$data of function unpack expects string, string\\|false given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/CharacterConvert.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\\\CharacterConvert\\:\\:convertBooleanValue\\(\\) has no return typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/CharacterConvert.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\\\CharacterConvert\\:\\:convertBooleanValue\\(\\) has parameter \\$value with no typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/CharacterConvert.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\\\Concatenate\\:\\:CONCATENATE\\(\\) has parameter \\$args with no typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/Concatenate.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\\\Concatenate\\:\\:convertBooleanValue\\(\\) has no return typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/Concatenate.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\\\Concatenate\\:\\:convertBooleanValue\\(\\) has parameter \\$value with no typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/Concatenate.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$length of function mb_substr expects int\\|null, float\\|int\\<0, max\\>\\|string given\\.$#"
|
||||
count: 3
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/Extract.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$start of function mb_substr expects int, float\\|int given\\.$#"
|
||||
count: 2
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/Extract.php
|
||||
|
||||
-
|
||||
message: "#^Cannot cast array\\|float\\|int\\|string to float\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/Format.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$offset of function mb_strpos expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/Search.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$offset of function mb_stripos expects int, float\\|int given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/Search.php
|
||||
|
||||
-
|
||||
message: "#^Property PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\TextData\\\\Trim\\:\\:\\$invalidChars has no typehint specified\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/Trim.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$str of function trim expects string, float\\|int\\|string given\\.$#"
|
||||
count: 2
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/Trim.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$str of function trim expects string, string\\|null given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/TextData/Trim.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Token\\\\Stack\\:\\:getStackItem\\(\\) has no return typehint specified\\.$#"
|
||||
count: 1
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
|
||||
|
|
@ -18,10 +17,7 @@ class CaseConvert
|
|||
public static function lower($mixedCaseValue): string
|
||||
{
|
||||
$mixedCaseValue = Functions::flattenSingleValue($mixedCaseValue);
|
||||
|
||||
if (is_bool($mixedCaseValue)) {
|
||||
$mixedCaseValue = ($mixedCaseValue === true) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
$mixedCaseValue = Helpers::extractString($mixedCaseValue);
|
||||
|
||||
return StringHelper::strToLower($mixedCaseValue);
|
||||
}
|
||||
|
|
@ -36,10 +32,7 @@ class CaseConvert
|
|||
public static function upper($mixedCaseValue): string
|
||||
{
|
||||
$mixedCaseValue = Functions::flattenSingleValue($mixedCaseValue);
|
||||
|
||||
if (is_bool($mixedCaseValue)) {
|
||||
$mixedCaseValue = ($mixedCaseValue === true) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
$mixedCaseValue = Helpers::extractString($mixedCaseValue);
|
||||
|
||||
return StringHelper::strToUpper($mixedCaseValue);
|
||||
}
|
||||
|
|
@ -54,10 +47,7 @@ class CaseConvert
|
|||
public static function proper($mixedCaseValue): string
|
||||
{
|
||||
$mixedCaseValue = Functions::flattenSingleValue($mixedCaseValue);
|
||||
|
||||
if (is_bool($mixedCaseValue)) {
|
||||
$mixedCaseValue = ($mixedCaseValue === true) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
$mixedCaseValue = Helpers::extractString($mixedCaseValue);
|
||||
|
||||
return StringHelper::strToTitle($mixedCaseValue);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,34 +2,29 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class CharacterConvert
|
||||
{
|
||||
/**
|
||||
* CHARACTER.
|
||||
* CHAR.
|
||||
*
|
||||
* @param mixed $character Integer Value to convert to its character representation
|
||||
*/
|
||||
public static function character($character): string
|
||||
{
|
||||
$character = Functions::flattenSingleValue($character);
|
||||
|
||||
if (!is_numeric($character)) {
|
||||
$character = Helpers::validateInt($character);
|
||||
$min = Functions::getCompatibilityMode() === Functions::COMPATIBILITY_OPENOFFICE ? 0 : 1;
|
||||
if ($character < $min || $character > 255) {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
$result = iconv('UCS-4LE', 'UTF-8', pack('V', $character));
|
||||
|
||||
$character = (int) $character;
|
||||
if ($character < 1 || $character > 255) {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
return iconv('UCS-4LE', 'UTF-8', pack('V', $character));
|
||||
return ($result === false) ? '' : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ASCIICODE.
|
||||
* CODE.
|
||||
*
|
||||
* @param mixed $characters String character to convert to its ASCII value
|
||||
*
|
||||
|
|
@ -37,13 +32,10 @@ class CharacterConvert
|
|||
*/
|
||||
public static function code($characters)
|
||||
{
|
||||
if (($characters === null) || ($characters === '')) {
|
||||
$characters = Helpers::extractString($characters);
|
||||
if ($characters === '') {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
$characters = Functions::flattenSingleValue($characters);
|
||||
if (is_bool($characters)) {
|
||||
$characters = self::convertBooleanValue($characters);
|
||||
}
|
||||
|
||||
$character = $characters;
|
||||
if (mb_strlen($characters, 'UTF-8') > 1) {
|
||||
|
|
@ -53,17 +45,17 @@ class CharacterConvert
|
|||
return self::unicodeToOrd($character);
|
||||
}
|
||||
|
||||
private static function unicodeToOrd($character)
|
||||
private static function unicodeToOrd(string $character): int
|
||||
{
|
||||
return unpack('V', iconv('UTF-8', 'UCS-4LE', $character))[1];
|
||||
$retVal = 0;
|
||||
$iconv = iconv('UTF-8', 'UCS-4LE', $character);
|
||||
if ($iconv !== false) {
|
||||
$result = unpack('V', $iconv);
|
||||
if (is_array($result) && isset($result[1])) {
|
||||
$retVal = $result[1];
|
||||
}
|
||||
}
|
||||
|
||||
private static function convertBooleanValue($value)
|
||||
{
|
||||
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
return ($value) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
return $retVal;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class Concatenate
|
||||
{
|
||||
/**
|
||||
* CONCATENATE.
|
||||
*
|
||||
* @param array $args
|
||||
*/
|
||||
public static function CONCATENATE(...$args): string
|
||||
{
|
||||
|
|
@ -16,11 +17,9 @@ class Concatenate
|
|||
|
||||
// Loop through arguments
|
||||
$aArgs = Functions::flattenArray($args);
|
||||
|
||||
foreach ($aArgs as $arg) {
|
||||
if (is_bool($arg)) {
|
||||
$arg = self::convertBooleanValue($arg);
|
||||
}
|
||||
$returnValue .= $arg;
|
||||
$returnValue .= Helpers::extractString($arg);
|
||||
}
|
||||
|
||||
return $returnValue;
|
||||
|
|
@ -35,13 +34,15 @@ class Concatenate
|
|||
*/
|
||||
public static function TEXTJOIN($delimiter, $ignoreEmpty, ...$args): string
|
||||
{
|
||||
$delimiter = Functions::flattenSingleValue($delimiter);
|
||||
$ignoreEmpty = Functions::flattenSingleValue($ignoreEmpty);
|
||||
// Loop through arguments
|
||||
$aArgs = Functions::flattenArray($args);
|
||||
foreach ($aArgs as $key => &$arg) {
|
||||
if ($ignoreEmpty === true && is_string($arg) && trim($arg) === '') {
|
||||
unset($aArgs[$key]);
|
||||
} elseif (is_bool($arg)) {
|
||||
$arg = self::convertBooleanValue($arg);
|
||||
$arg = Helpers::convertBooleanValue($arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -59,24 +60,12 @@ class Concatenate
|
|||
public static function builtinREPT($stringValue, $repeatCount): string
|
||||
{
|
||||
$repeatCount = Functions::flattenSingleValue($repeatCount);
|
||||
$stringValue = Helpers::extractString($stringValue);
|
||||
|
||||
if (!is_numeric($repeatCount) || $repeatCount < 0) {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
if (is_bool($stringValue)) {
|
||||
$stringValue = self::convertBooleanValue($stringValue);
|
||||
}
|
||||
|
||||
return str_repeat($stringValue, (int) $repeatCount);
|
||||
}
|
||||
|
||||
private static function convertBooleanValue($value)
|
||||
{
|
||||
if (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_OPENOFFICE) {
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
return ($value) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
||||
|
||||
class Extract
|
||||
{
|
||||
|
|
@ -13,17 +12,13 @@ class Extract
|
|||
* @param mixed $value String value from which to extract characters
|
||||
* @param mixed $chars The number of characters to extract (as an integer)
|
||||
*/
|
||||
public static function left($value = '', $chars = 1): string
|
||||
public static function left($value, $chars = 1): string
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
$chars = Functions::flattenSingleValue($chars);
|
||||
|
||||
if (!is_numeric($chars) || $chars < 0) {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
if (is_bool($value)) {
|
||||
$value = ($value) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
try {
|
||||
$value = Helpers::extractString($value);
|
||||
$chars = Helpers::extractInt($chars, 0, 1);
|
||||
} catch (CalcExp $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
return mb_substr($value ?? '', 0, $chars, 'UTF-8');
|
||||
|
|
@ -36,18 +31,14 @@ class Extract
|
|||
* @param mixed $start Integer offset of the first character that we want to extract
|
||||
* @param mixed $chars The number of characters to extract (as an integer)
|
||||
*/
|
||||
public static function mid($value = '', $start = 1, $chars = null): string
|
||||
public static function mid($value, $start, $chars): string
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
$start = Functions::flattenSingleValue($start);
|
||||
$chars = Functions::flattenSingleValue($chars);
|
||||
|
||||
if (!is_numeric($start) || $start < 1 || !is_numeric($chars) || $chars < 0) {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
if (is_bool($value)) {
|
||||
$value = ($value) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
try {
|
||||
$value = Helpers::extractString($value);
|
||||
$start = Helpers::extractInt($start, 1);
|
||||
$chars = Helpers::extractInt($chars, 0);
|
||||
} catch (CalcExp $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
return mb_substr($value ?? '', --$start, $chars, 'UTF-8');
|
||||
|
|
@ -59,17 +50,13 @@ class Extract
|
|||
* @param mixed $value String value from which to extract characters
|
||||
* @param mixed $chars The number of characters to extract (as an integer)
|
||||
*/
|
||||
public static function right($value = '', $chars = 1): string
|
||||
public static function right($value, $chars = 1): string
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
$chars = Functions::flattenSingleValue($chars);
|
||||
|
||||
if (!is_numeric($chars) || $chars < 0) {
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
if (is_bool($value)) {
|
||||
$value = ($value) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
try {
|
||||
$value = Helpers::extractString($value);
|
||||
$chars = Helpers::extractInt($chars, 0, 1);
|
||||
} catch (CalcExp $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
return mb_substr($value ?? '', mb_strlen($value ?? '', 'UTF-8') - $chars, $chars, 'UTF-8');
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
|||
|
||||
use DateTimeInterface;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||
|
|
@ -25,14 +26,12 @@ class Format
|
|||
*/
|
||||
public static function DOLLAR($value = 0, $decimals = 2): string
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
$decimals = $decimals === null ? 2 : Functions::flattenSingleValue($decimals);
|
||||
|
||||
// Validate parameters
|
||||
if (!is_numeric($value) || !is_numeric($decimals)) {
|
||||
return Functions::VALUE();
|
||||
try {
|
||||
$value = Helpers::extractFloat($value);
|
||||
$decimals = Helpers::extractInt($decimals, -100, 0, true);
|
||||
} catch (CalcExp $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
$decimals = (int) $decimals;
|
||||
|
||||
$mask = '$#,##0';
|
||||
if ($decimals > 0) {
|
||||
|
|
@ -50,7 +49,7 @@ class Format
|
|||
}
|
||||
|
||||
/**
|
||||
* FIXEDFORMAT.
|
||||
* FIXED.
|
||||
*
|
||||
* @param mixed $value The value to format
|
||||
* @param mixed $decimals Integer value for the number of decimal places that should be formatted
|
||||
|
|
@ -58,17 +57,13 @@ class Format
|
|||
*/
|
||||
public static function FIXEDFORMAT($value, $decimals = 2, $noCommas = false): string
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
$decimals = $decimals === null ? 2 : Functions::flattenSingleValue($decimals);
|
||||
try {
|
||||
$value = Helpers::extractFloat($value);
|
||||
$decimals = Helpers::extractInt($decimals, -100, 0, true);
|
||||
$noCommas = Functions::flattenSingleValue($noCommas);
|
||||
|
||||
// Validate parameters
|
||||
if (!is_numeric($value) || !is_numeric($decimals)) {
|
||||
return Functions::VALUE();
|
||||
} catch (CalcExp $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
$decimals = (float) $decimals;
|
||||
$value = (float) $value;
|
||||
$decimals = (int) floor($decimals);
|
||||
|
||||
$valueResult = round($value, $decimals);
|
||||
if ($decimals < 0) {
|
||||
|
|
@ -87,23 +82,42 @@ class Format
|
|||
}
|
||||
|
||||
/**
|
||||
* TEXTFORMAT.
|
||||
* TEXT.
|
||||
*
|
||||
* @param mixed $value The value to format
|
||||
* @param mixed $format A string with the Format mask that should be used
|
||||
*/
|
||||
public static function TEXTFORMAT($value, $format): string
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
$format = Functions::flattenSingleValue($format);
|
||||
$value = Helpers::extractString($value);
|
||||
$format = Helpers::extractString($format);
|
||||
|
||||
if ((is_string($value)) && (!is_numeric($value)) && Date::isDateTimeFormatCode($format)) {
|
||||
if (!is_numeric($value) && Date::isDateTimeFormatCode($format)) {
|
||||
$value = DateTimeExcel\DateValue::fromString($value);
|
||||
}
|
||||
|
||||
return (string) NumberFormat::toFormattedString($value, $format);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value Value to check
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private static function convertValue($value)
|
||||
{
|
||||
$value = ($value === null) ? 0 : Functions::flattenSingleValue($value);
|
||||
if (is_bool($value)) {
|
||||
if (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_OPENOFFICE) {
|
||||
$value = (int) $value;
|
||||
} else {
|
||||
throw new CalcExp(Functions::VALUE());
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* VALUE.
|
||||
*
|
||||
|
|
@ -113,8 +127,11 @@ class Format
|
|||
*/
|
||||
public static function VALUE($value = '')
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
|
||||
try {
|
||||
$value = self::convertValue($value);
|
||||
} catch (CalcExp $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
if (!is_numeric($value)) {
|
||||
$numberValue = str_replace(
|
||||
StringHelper::getThousandsSeparator(),
|
||||
|
|
@ -150,6 +167,26 @@ class Format
|
|||
return (float) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $decimalSeparator
|
||||
*/
|
||||
private static function getDecimalSeparator($decimalSeparator): string
|
||||
{
|
||||
$decimalSeparator = Functions::flattenSingleValue($decimalSeparator);
|
||||
|
||||
return empty($decimalSeparator) ? StringHelper::getDecimalSeparator() : (string) $decimalSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $groupSeparator
|
||||
*/
|
||||
private static function getGroupSeparator($groupSeparator): string
|
||||
{
|
||||
$groupSeparator = Functions::flattenSingleValue($groupSeparator);
|
||||
|
||||
return empty($groupSeparator) ? StringHelper::getThousandsSeparator() : (string) $groupSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* NUMBERVALUE.
|
||||
*
|
||||
|
|
@ -161,14 +198,15 @@ class Format
|
|||
*/
|
||||
public static function NUMBERVALUE($value = '', $decimalSeparator = null, $groupSeparator = null)
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
$decimalSeparator = Functions::flattenSingleValue($decimalSeparator);
|
||||
$groupSeparator = Functions::flattenSingleValue($groupSeparator);
|
||||
try {
|
||||
$value = self::convertValue($value);
|
||||
$decimalSeparator = self::getDecimalSeparator($decimalSeparator);
|
||||
$groupSeparator = self::getGroupSeparator($groupSeparator);
|
||||
} catch (CalcExp $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
if (!is_numeric($value)) {
|
||||
$decimalSeparator = empty($decimalSeparator) ? StringHelper::getDecimalSeparator() : $decimalSeparator;
|
||||
$groupSeparator = empty($groupSeparator) ? StringHelper::getThousandsSeparator() : $groupSeparator;
|
||||
|
||||
$decimalPositions = preg_match_all('/' . preg_quote($decimalSeparator) . '/', $value, $matches, PREG_OFFSET_CAPTURE);
|
||||
if ($decimalPositions > 1) {
|
||||
return Functions::VALUE();
|
||||
|
|
@ -193,6 +231,6 @@ class Format
|
|||
}
|
||||
}
|
||||
|
||||
return (float) $value;
|
||||
return is_array($value) ? Functions::VALUE() : (float) $value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class Helpers
|
||||
{
|
||||
public static function convertBooleanValue(bool $value): string
|
||||
{
|
||||
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
|
||||
return $value ? '1' : '0';
|
||||
}
|
||||
|
||||
return ($value) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value String value from which to extract characters
|
||||
*/
|
||||
public static function extractString($value): string
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
if (is_bool($value)) {
|
||||
return self::convertBooleanValue($value);
|
||||
}
|
||||
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function extractInt($value, int $minValue, int $gnumericNull = 0, bool $ooBoolOk = false): int
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
if ($value === null) {
|
||||
// usually 0, but sometimes 1 for Gnumeric
|
||||
$value = (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_GNUMERIC) ? $gnumericNull : 0;
|
||||
}
|
||||
if (is_bool($value) && ($ooBoolOk || Functions::getCompatibilityMode() !== Functions::COMPATIBILITY_OPENOFFICE)) {
|
||||
$value = (int) $value;
|
||||
}
|
||||
if (!is_numeric($value)) {
|
||||
throw new CalcExp(Functions::VALUE());
|
||||
}
|
||||
$value = (int) $value;
|
||||
if ($value < $minValue) {
|
||||
throw new CalcExp(Functions::VALUE());
|
||||
}
|
||||
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function extractFloat($value): float
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
if ($value === null) {
|
||||
$value = 0.0;
|
||||
}
|
||||
if (is_bool($value)) {
|
||||
$value = (float) $value;
|
||||
}
|
||||
if (!is_numeric($value)) {
|
||||
throw new CalcExp(Functions::VALUE());
|
||||
}
|
||||
|
||||
return (float) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function validateInt($value): int
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
if ($value === null) {
|
||||
$value = 0;
|
||||
} elseif (is_bool($value)) {
|
||||
$value = (int) $value;
|
||||
}
|
||||
|
||||
return (int) $value;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class Replace
|
||||
|
|
@ -16,13 +17,17 @@ class Replace
|
|||
*/
|
||||
public static function replace($oldText, $start, $chars, $newText): string
|
||||
{
|
||||
$oldText = Functions::flattenSingleValue($oldText);
|
||||
$start = Functions::flattenSingleValue($start);
|
||||
$chars = Functions::flattenSingleValue($chars);
|
||||
$newText = Functions::flattenSingleValue($newText);
|
||||
try {
|
||||
$start = Helpers::extractInt($start, 1, 0, true);
|
||||
$chars = Helpers::extractInt($chars, 0, 0, true);
|
||||
$oldText = Helpers::extractString($oldText);
|
||||
$newText = Helpers::extractString($newText);
|
||||
$left = mb_substr($oldText, 0, $start - 1, 'UTF-8');
|
||||
|
||||
$left = Extract::left($oldText, $start - 1);
|
||||
$right = Extract::right($oldText, Text::length($oldText) - ($start + $chars) + 1);
|
||||
$right = mb_substr($oldText, $start + $chars - 1, null, 'UTF-8');
|
||||
} catch (CalcExp $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
return $left . $newText . $right;
|
||||
}
|
||||
|
|
@ -35,16 +40,26 @@ class Replace
|
|||
* @param mixed $toText The string value that we want to replace with in $text
|
||||
* @param mixed $instance Integer instance Number for the occurrence of frmText to change
|
||||
*/
|
||||
public static function substitute($text = '', $fromText = '', $toText = '', $instance = 0): string
|
||||
public static function substitute($text = '', $fromText = '', $toText = '', $instance = null): string
|
||||
{
|
||||
$text = Functions::flattenSingleValue($text);
|
||||
$fromText = Functions::flattenSingleValue($fromText);
|
||||
$toText = Functions::flattenSingleValue($toText);
|
||||
$instance = floor(Functions::flattenSingleValue($instance));
|
||||
|
||||
if ($instance == 0) {
|
||||
try {
|
||||
$text = Helpers::extractString($text);
|
||||
$fromText = Helpers::extractString($fromText);
|
||||
$toText = Helpers::extractString($toText);
|
||||
$instance = Functions::flattenSingleValue($instance);
|
||||
if ($instance === null) {
|
||||
return str_replace($fromText, $toText, $text);
|
||||
}
|
||||
if (is_bool($instance)) {
|
||||
if ($instance === false || Functions::getCompatibilityMode() !== Functions::COMPATIBILITY_OPENOFFICE) {
|
||||
return Functions::Value();
|
||||
}
|
||||
$instance = 1;
|
||||
}
|
||||
$instance = Helpers::extractInt($instance, 1, 0, true);
|
||||
} catch (CalcExp $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
$pos = -1;
|
||||
while ($instance > 0) {
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
|
||||
class Search
|
||||
{
|
||||
/**
|
||||
* SEARCHSENSITIVE.
|
||||
* FIND (case sensitive search).
|
||||
*
|
||||
* @param mixed $needle The string to look for
|
||||
* @param mixed $haystack The string in which to look
|
||||
|
|
@ -19,16 +19,15 @@ class Search
|
|||
*/
|
||||
public static function sensitive($needle, $haystack, $offset = 1)
|
||||
{
|
||||
$needle = Functions::flattenSingleValue($needle);
|
||||
$haystack = Functions::flattenSingleValue($haystack);
|
||||
$offset = Functions::flattenSingleValue($offset);
|
||||
|
||||
if (!is_bool($needle)) {
|
||||
if (is_bool($haystack)) {
|
||||
$haystack = ($haystack) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
try {
|
||||
$needle = Helpers::extractString($needle);
|
||||
$haystack = Helpers::extractString($haystack);
|
||||
$offset = Helpers::extractInt($offset, 1, 0, true);
|
||||
} catch (CalcExp $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
if (($offset > 0) && (StringHelper::countCharacters($haystack) > $offset)) {
|
||||
if (StringHelper::countCharacters($haystack) >= $offset) {
|
||||
if (StringHelper::countCharacters($needle) === 0) {
|
||||
return $offset;
|
||||
}
|
||||
|
|
@ -38,13 +37,12 @@ class Search
|
|||
return ++$pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
||||
/**
|
||||
* SEARCHINSENSITIVE.
|
||||
* SEARCH (case insensitive search).
|
||||
*
|
||||
* @param mixed $needle The string to look for
|
||||
* @param mixed $haystack The string in which to look
|
||||
|
|
@ -54,16 +52,15 @@ class Search
|
|||
*/
|
||||
public static function insensitive($needle, $haystack, $offset = 1)
|
||||
{
|
||||
$needle = Functions::flattenSingleValue($needle);
|
||||
$haystack = Functions::flattenSingleValue($haystack);
|
||||
$offset = Functions::flattenSingleValue($offset);
|
||||
|
||||
if (!is_bool($needle)) {
|
||||
if (is_bool($haystack)) {
|
||||
$haystack = ($haystack) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
try {
|
||||
$needle = Helpers::extractString($needle);
|
||||
$haystack = Helpers::extractString($haystack);
|
||||
$offset = Helpers::extractInt($offset, 1, 0, true);
|
||||
} catch (CalcExp $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
if (($offset > 0) && (StringHelper::countCharacters($haystack) > $offset)) {
|
||||
if (StringHelper::countCharacters($haystack) >= $offset) {
|
||||
if (StringHelper::countCharacters($needle) === 0) {
|
||||
return $offset;
|
||||
}
|
||||
|
|
@ -73,7 +70,6 @@ class Search
|
|||
return ++$pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Functions::VALUE();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,23 +2,18 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class Text
|
||||
{
|
||||
/**
|
||||
* STRINGLENGTH.
|
||||
* LEN.
|
||||
*
|
||||
* @param mixed $value String Value
|
||||
*/
|
||||
public static function length($value = ''): int
|
||||
{
|
||||
$value = Functions::flattenSingleValue($value);
|
||||
|
||||
if (is_bool($value)) {
|
||||
$value = ($value) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
$value = Helpers::extractString($value);
|
||||
|
||||
return mb_strlen($value ?? '', 'UTF-8');
|
||||
}
|
||||
|
|
@ -33,10 +28,10 @@ class Text
|
|||
*/
|
||||
public static function exact($value1, $value2): bool
|
||||
{
|
||||
$value1 = Functions::flattenSingleValue($value1);
|
||||
$value2 = Functions::flattenSingleValue($value2);
|
||||
$value1 = Helpers::extractString($value1);
|
||||
$value2 = Helpers::extractString($value2);
|
||||
|
||||
return ((string) $value2) === ((string) $value1);
|
||||
return $value2 === $value1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,15 +2,10 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class Trim
|
||||
{
|
||||
private static $invalidChars;
|
||||
|
||||
/**
|
||||
* TRIMNONPRINTABLE.
|
||||
* CLEAN.
|
||||
*
|
||||
* @param mixed $stringValue String Value to check
|
||||
*
|
||||
|
|
@ -18,41 +13,22 @@ class Trim
|
|||
*/
|
||||
public static function nonPrintable($stringValue = '')
|
||||
{
|
||||
$stringValue = Functions::flattenSingleValue($stringValue);
|
||||
$stringValue = Helpers::extractString($stringValue);
|
||||
|
||||
if (is_bool($stringValue)) {
|
||||
return ($stringValue) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
|
||||
if (self::$invalidChars === null) {
|
||||
self::$invalidChars = range(chr(0), chr(31));
|
||||
}
|
||||
|
||||
if (is_string($stringValue) || is_numeric($stringValue)) {
|
||||
return str_replace(self::$invalidChars, '', trim($stringValue, "\x00..\x1F"));
|
||||
}
|
||||
|
||||
return null;
|
||||
return preg_replace('/[\\x00-\\x1f]/', '', "$stringValue");
|
||||
}
|
||||
|
||||
/**
|
||||
* TRIMSPACES.
|
||||
* TRIM.
|
||||
*
|
||||
* @param mixed $stringValue String Value to check
|
||||
*
|
||||
* @return null|string
|
||||
* @return string
|
||||
*/
|
||||
public static function spaces($stringValue = '')
|
||||
{
|
||||
$stringValue = Functions::flattenSingleValue($stringValue);
|
||||
if (is_bool($stringValue)) {
|
||||
return ($stringValue) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
}
|
||||
$stringValue = Helpers::extractString($stringValue);
|
||||
|
||||
if (is_string($stringValue) || is_numeric($stringValue)) {
|
||||
return trim(preg_replace('/ +/', ' ', trim($stringValue, ' ')), ' ');
|
||||
}
|
||||
|
||||
return null;
|
||||
return trim(preg_replace('/ +/', ' ', trim("$stringValue", ' ')) ?? '', ' ');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,11 @@ class Settings
|
|||
return Calculation::getInstance()->setLocale($locale);
|
||||
}
|
||||
|
||||
public static function getLocale(): string
|
||||
{
|
||||
return Calculation::getInstance()->getLocale();
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify to PhpSpreadsheet the external library to use for rendering charts.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1234,6 +1234,7 @@ class Worksheet extends WriterPart
|
|||
return;
|
||||
}
|
||||
$objWriter->writeAttribute('t', 'str');
|
||||
$calculatedValue = StringHelper::controlCharacterPHP2OOXML($calculatedValue);
|
||||
} elseif (is_bool($calculatedValue)) {
|
||||
$objWriter->writeAttribute('t', 'b');
|
||||
$calculatedValue = (int) $calculatedValue;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcException;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Settings;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class AllSetupTeardown extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $compatibilityMode;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $locale;
|
||||
|
||||
/**
|
||||
* @var ?Spreadsheet
|
||||
*/
|
||||
private $spreadsheet;
|
||||
|
||||
/**
|
||||
* @var ?Worksheet
|
||||
*/
|
||||
private $sheet;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->locale = Settings::getLocale();
|
||||
$this->compatibilityMode = Functions::getCompatibilityMode();
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Functions::setCompatibilityMode($this->compatibilityMode);
|
||||
Settings::setLocale($this->locale);
|
||||
$this->sheet = null;
|
||||
if ($this->spreadsheet !== null) {
|
||||
$this->spreadsheet->disconnectWorksheets();
|
||||
$this->spreadsheet = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected static function setOpenOffice(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_OPENOFFICE);
|
||||
}
|
||||
|
||||
protected static function setGnumeric(): void
|
||||
{
|
||||
Functions::setCompatibilityMode(Functions::COMPATIBILITY_GNUMERIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $expectedResult
|
||||
*/
|
||||
protected function mightHaveException($expectedResult): void
|
||||
{
|
||||
if ($expectedResult === 'exception') {
|
||||
$this->expectException(CalcException::class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
protected function setCell(string $cell, $value): void
|
||||
{
|
||||
if ($value !== null) {
|
||||
if (is_string($value) && is_numeric($value)) {
|
||||
$this->getSheet()->getCell($cell)->setValueExplicit($value, DataType::TYPE_STRING);
|
||||
} else {
|
||||
$this->getSheet()->getCell($cell)->setValue($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getSpreadsheet(): Spreadsheet
|
||||
{
|
||||
if ($this->spreadsheet !== null) {
|
||||
return $this->spreadsheet;
|
||||
}
|
||||
$this->spreadsheet = new Spreadsheet();
|
||||
|
||||
return $this->spreadsheet;
|
||||
}
|
||||
|
||||
protected function getSheet(): Worksheet
|
||||
{
|
||||
if ($this->sheet !== null) {
|
||||
return $this->sheet;
|
||||
}
|
||||
$this->sheet = $this->getSpreadsheet()->getActiveSheet();
|
||||
|
||||
return $this->sheet;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
|
||||
|
||||
class CharNonPrintableTest extends AbstractFunctional
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerType
|
||||
*/
|
||||
public function testNotPrintable(string $type): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->getCell('B1')->setValue('=CHAR(2)');
|
||||
$sheet->getCell('C1')->setValue('=CHAR(127)');
|
||||
$hello = "hello\nthere";
|
||||
$sheet->getCell('D2')->setValue($hello);
|
||||
$sheet->getCell('D1')->setValue('=D2');
|
||||
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, $type);
|
||||
$result = $reloadedSpreadsheet->getActiveSheet()->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals("\x02", $result);
|
||||
$result = $reloadedSpreadsheet->getActiveSheet()->getCell('C1')->getCalculatedValue();
|
||||
self::assertEquals("\x7f", $result);
|
||||
$result = $reloadedSpreadsheet->getActiveSheet()->getCell('D1')->getCalculatedValue();
|
||||
self::assertEquals($hello, $result);
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
$reloadedSpreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
public function providerType(): array
|
||||
{
|
||||
return [
|
||||
['Xlsx'],
|
||||
['Xls'],
|
||||
//['Ods'], // no support yet in Reader or Writer
|
||||
// without csv suffix, Reader/Csv decides type via mime_get_type,
|
||||
// and control character makes it guess application/octet-stream,
|
||||
// so Reader/Csv decides it can't read it.
|
||||
//['Csv'],
|
||||
// DOMDocument.loadHTML() rejects '' even though legal html.
|
||||
//['Html'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CharTest extends TestCase
|
||||
class CharTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerCHAR
|
||||
|
|
@ -13,9 +10,17 @@ class CharTest extends TestCase
|
|||
* @param mixed $expectedResult
|
||||
* @param mixed $character
|
||||
*/
|
||||
public function testCHAR($expectedResult, $character): void
|
||||
public function testCHAR($expectedResult, $character = 'omitted'): void
|
||||
{
|
||||
$result = TextData::CHARACTER($character);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($character === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=CHAR()');
|
||||
} else {
|
||||
$this->setCell('A1', $character);
|
||||
$sheet->getCell('B1')->setValue('=CHAR(A1)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CleanTest extends TestCase
|
||||
class CleanTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerCLEAN
|
||||
|
|
@ -13,9 +10,17 @@ class CleanTest extends TestCase
|
|||
* @param mixed $expectedResult
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function testCLEAN($expectedResult, $value): void
|
||||
public function testCLEAN($expectedResult, $value = 'omitted'): void
|
||||
{
|
||||
$result = TextData::TRIMNONPRINTABLE($value);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($value === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=CLEAN()');
|
||||
} else {
|
||||
$this->setCell('A1', $value);
|
||||
$sheet->getCell('B1')->setValue('=CLEAN(A1)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CodeTest extends TestCase
|
||||
class CodeTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerCODE
|
||||
|
|
@ -13,9 +10,17 @@ class CodeTest extends TestCase
|
|||
* @param mixed $expectedResult
|
||||
* @param mixed $character
|
||||
*/
|
||||
public function testCODE($expectedResult, $character): void
|
||||
public function testCODE($expectedResult, $character = 'omitted'): void
|
||||
{
|
||||
$result = TextData::ASCIICODE($character);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($character === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=CODE()');
|
||||
} else {
|
||||
$this->setCell('A1', $character);
|
||||
$sheet->getCell('B1')->setValue('=CODE(A1)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,19 +2,27 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ConcatenateTest extends TestCase
|
||||
class ConcatenateTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerCONCATENATE
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param array $args
|
||||
*/
|
||||
public function testCONCATENATE($expectedResult, ...$args): void
|
||||
{
|
||||
$result = TextData::CONCATENATE(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
$finalArg = '';
|
||||
$row = 0;
|
||||
foreach ($args as $arg) {
|
||||
++$row;
|
||||
$this->setCell("A$row", $arg);
|
||||
$finalArg = "A1:A$row";
|
||||
}
|
||||
$this->setCell('B1', "=CONCAT($finalArg)");
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
// Sanity tests for functions which have been moved out of TextData
|
||||
// to their own classes. A deprecated version remains in TextData;
|
||||
// this class contains cursory tests to ensure that those work properly.
|
||||
// If Scrutinizer fails the PR because of these deprecations, I will
|
||||
// remove this class from the PR.
|
||||
|
||||
class DeprecatedTest extends TestCase
|
||||
{
|
||||
public function testDeprecated(): void
|
||||
{
|
||||
self::assertSame('x', TextData::TRIMNONPRINTABLE('x'));
|
||||
self::assertSame('x y', TextData::TRIMSPACES('x y'));
|
||||
self::assertSame(48, TextData::ASCIICODE('0'));
|
||||
self::assertSame('abc', TextData::CONCATENATE('a', 'b', 'c'));
|
||||
self::assertSame('$1.00', TextData::DOLLAR(1));
|
||||
self::assertEquals(2, TextData::SEARCHSENSITIVE('b', 'abc'));
|
||||
self::assertEquals(2, TextData::SEARCHINSENSITIVE('b', 'abc'));
|
||||
self::assertSame('1.00', TextData::FIXEDFORMAT(1));
|
||||
self::assertSame('xyz', TextData::LEFT('xyzw', 3));
|
||||
self::assertSame('yz', TextData::MID('xyzw', 2, 2));
|
||||
self::assertSame('zw', TextData::RIGHT('xyzw', 2));
|
||||
self::assertSame(4, TextData::STRINGLENGTH('xyzw'));
|
||||
self::assertSame('xyzw', TextData::LOWERCASE('Xyzw'));
|
||||
self::assertSame('XYZW', TextData::UPPERCASE('Xyzw'));
|
||||
self::assertSame('Xyzw', TextData::PROPERCASE('xyzw'));
|
||||
self::assertSame('xabw', TextData::REPLACE('xyzw', 2, 2, 'ab'));
|
||||
self::assertSame('xyzw', TextData::TEXTFORMAT('xyzw', '@'));
|
||||
self::assertEquals(3, TextData::VALUE('3'));
|
||||
self::assertEquals(3, TextData::NUMBERVALUE('3'));
|
||||
self::assertTrue(TextData::EXACT('3', '3'));
|
||||
self::assertSame('a,b,c', TextData::TEXTJOIN(',', true, 'a', 'b', 'c'));
|
||||
self::assertSame('aaa', TextData::builtinREPT('a', 3));
|
||||
self::assertSame('ayxw', TextData::SUBSTITUTE('xyxw', 'x', 'a', 1));
|
||||
self::assertSame('1', TextData::CHARACTER('49'));
|
||||
self::assertSame('0', TextData::CHARACTER('48'));
|
||||
}
|
||||
}
|
||||
|
|
@ -2,19 +2,30 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DollarTest extends TestCase
|
||||
class DollarTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerDOLLAR
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $amount
|
||||
* @param mixed $decimals
|
||||
*/
|
||||
public function testDOLLAR($expectedResult, ...$args): void
|
||||
public function testDOLLAR($expectedResult, $amount = 'omitted', $decimals = 'omitted'): void
|
||||
{
|
||||
$result = TextData::DOLLAR(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($amount === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=DOLLAR()');
|
||||
} elseif ($decimals === 'omitted') {
|
||||
$this->setCell('A1', $amount);
|
||||
$sheet->getCell('B1')->setValue('=DOLLAR(A1)');
|
||||
} else {
|
||||
$this->setCell('A1', $amount);
|
||||
$this->setCell('A2', $decimals);
|
||||
$sheet->getCell('B1')->setValue('=DOLLAR(A1, A2)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,21 +2,31 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ExactTest extends TestCase
|
||||
class ExactTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerEXACT
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param array $args
|
||||
* @param mixed $string1
|
||||
* @param mixed $string2
|
||||
*/
|
||||
public function testEXACT($expectedResult, ...$args): void
|
||||
public function testEXACT($expectedResult, $string1 = 'omitted', $string2 = 'omitted'): void
|
||||
{
|
||||
$result = TextData::EXACT(...$args);
|
||||
self::assertSame($expectedResult, $result);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($string1 === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=EXACT()');
|
||||
} elseif ($string2 === 'omitted') {
|
||||
$this->setCell('A1', $string1);
|
||||
$sheet->getCell('B1')->setValue('=EXACT(A1)');
|
||||
} else {
|
||||
$this->setCell('A1', $string1);
|
||||
$this->setCell('A2', $string2);
|
||||
$sheet->getCell('B1')->setValue('=EXACT(A1, A2)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function providerEXACT(): array
|
||||
|
|
|
|||
|
|
@ -2,19 +2,36 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FindTest extends TestCase
|
||||
class FindTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerFIND
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $string1
|
||||
* @param mixed $string2
|
||||
* @param mixed $start
|
||||
*/
|
||||
public function testFIND($expectedResult, ...$args): void
|
||||
public function testFIND($expectedResult, $string1 = 'omitted', $string2 = 'omitted', $start = 'omitted'): void
|
||||
{
|
||||
$result = TextData::SEARCHSENSITIVE(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($string1 === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=FIND()');
|
||||
} elseif ($string2 === 'omitted') {
|
||||
$this->setCell('A1', $string1);
|
||||
$sheet->getCell('B1')->setValue('=FIND(A1)');
|
||||
} elseif ($start === 'omitted') {
|
||||
$this->setCell('A1', $string1);
|
||||
$this->setCell('A2', $string2);
|
||||
$sheet->getCell('B1')->setValue('=FIND(A1, A2)');
|
||||
} else {
|
||||
$this->setCell('A1', $string1);
|
||||
$this->setCell('A2', $string2);
|
||||
$this->setCell('A3', $start);
|
||||
$sheet->getCell('B1')->setValue('=FIND(A1, A2, A3)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,19 +2,36 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FixedTest extends TestCase
|
||||
class FixedTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerFIXED
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $number
|
||||
* @param mixed $decimals
|
||||
* @param mixed $noCommas
|
||||
*/
|
||||
public function testFIXED($expectedResult, ...$args): void
|
||||
public function testFIXED($expectedResult, $number = 'omitted', $decimals = 'omitted', $noCommas = 'omitted'): void
|
||||
{
|
||||
$result = TextData::FIXEDFORMAT(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($number === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=FIXED()');
|
||||
} elseif ($decimals === 'omitted') {
|
||||
$this->setCell('A1', $number);
|
||||
$sheet->getCell('B1')->setValue('=FIXED(A1)');
|
||||
} elseif ($noCommas === 'omitted') {
|
||||
$this->setCell('A1', $number);
|
||||
$this->setCell('A2', $decimals);
|
||||
$sheet->getCell('B1')->setValue('=FIXED(A1, A2)');
|
||||
} else {
|
||||
$this->setCell('A1', $number);
|
||||
$this->setCell('A2', $decimals);
|
||||
$this->setCell('A3', $noCommas);
|
||||
$sheet->getCell('B1')->setValue('=FIXED(A1, A2, A3)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,25 +2,33 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Settings;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class LeftTest extends TestCase
|
||||
class LeftTest extends AllSetupTeardown
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Settings::setLocale('en_US');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerLEFT
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $str string from which to extract
|
||||
* @param mixed $cnt number of characters to extract
|
||||
*/
|
||||
public function testLEFT($expectedResult, ...$args): void
|
||||
public function testLEFT($expectedResult, $str = 'omitted', $cnt = 'omitted'): void
|
||||
{
|
||||
$result = TextData::LEFT(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($str === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=LEFT()');
|
||||
} elseif ($cnt === 'omitted') {
|
||||
$this->setCell('A1', $str);
|
||||
$sheet->getCell('B1')->setValue('=LEFT(A1)');
|
||||
} else {
|
||||
$this->setCell('A1', $str);
|
||||
$this->setCell('A2', $cnt);
|
||||
$sheet->getCell('B1')->setValue('=LEFT(A1, A2)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
@ -41,14 +49,15 @@ class LeftTest extends TestCase
|
|||
{
|
||||
$newLocale = Settings::setLocale($locale);
|
||||
if ($newLocale === false) {
|
||||
Settings::setLocale('en_US');
|
||||
self::markTestSkipped('Unable to set locale for locale-specific test');
|
||||
}
|
||||
|
||||
$result = TextData::LEFT($value, $characters);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', $value);
|
||||
$this->setCell('A2', $characters);
|
||||
$sheet->getCell('B1')->setValue('=LEFT(A1, A2)');
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
|
||||
Settings::setLocale('en_US');
|
||||
}
|
||||
|
||||
public function providerLocaleLEFT(): array
|
||||
|
|
@ -64,4 +73,111 @@ class LeftTest extends TestCase
|
|||
['ЛОЖ', 'bg', false, 3],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerCalculationTypeLEFTTrue
|
||||
*/
|
||||
public function testCalculationTypeTrue(string $type, string $resultB1, string $resultB2): void
|
||||
{
|
||||
Functions::setCompatibilityMode($type);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', true);
|
||||
$this->setCell('A2', 'Hello');
|
||||
$this->setCell('B1', '=LEFT(A1, 1)');
|
||||
$this->setCell('B2', '=LEFT(A2, A1)');
|
||||
self::assertEquals($resultB1, $sheet->getCell('B1')->getCalculatedValue());
|
||||
self::assertEquals($resultB2, $sheet->getCell('B2')->getCalculatedValue());
|
||||
}
|
||||
|
||||
public function providerCalculationTypeLEFTTrue(): array
|
||||
{
|
||||
return [
|
||||
'Excel LEFT(true, 1) AND LEFT("hello", true)' => [
|
||||
Functions::COMPATIBILITY_EXCEL,
|
||||
'T',
|
||||
'H',
|
||||
],
|
||||
'Gnumeric LEFT(true, 1) AND LEFT("hello", true)' => [
|
||||
Functions::COMPATIBILITY_GNUMERIC,
|
||||
'T',
|
||||
'H',
|
||||
],
|
||||
'OpenOffice LEFT(true, 1) AND LEFT("hello", true)' => [
|
||||
Functions::COMPATIBILITY_OPENOFFICE,
|
||||
'1',
|
||||
'#VALUE!',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerCalculationTypeLEFTFalse
|
||||
*/
|
||||
public function testCalculationTypeFalse(string $type, string $resultB1, string $resultB2): void
|
||||
{
|
||||
Functions::setCompatibilityMode($type);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', false);
|
||||
$this->setCell('A2', 'Hello');
|
||||
$this->setCell('B1', '=LEFT(A1, 1)');
|
||||
$this->setCell('B2', '=LEFT(A2, A1)');
|
||||
self::assertEquals($resultB1, $sheet->getCell('B1')->getCalculatedValue());
|
||||
self::assertEquals($resultB2, $sheet->getCell('B2')->getCalculatedValue());
|
||||
}
|
||||
|
||||
public function providerCalculationTypeLEFTFalse(): array
|
||||
{
|
||||
return [
|
||||
'Excel LEFT(false, 1) AND LEFT("hello", false)' => [
|
||||
Functions::COMPATIBILITY_EXCEL,
|
||||
'F',
|
||||
'',
|
||||
],
|
||||
'Gnumeric LEFT(false, 1) AND LEFT("hello", false)' => [
|
||||
Functions::COMPATIBILITY_GNUMERIC,
|
||||
'F',
|
||||
'',
|
||||
],
|
||||
'OpenOffice LEFT(false, 1) AND LEFT("hello", false)' => [
|
||||
Functions::COMPATIBILITY_OPENOFFICE,
|
||||
'0',
|
||||
'#VALUE!',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerCalculationTypeLEFTNull
|
||||
*/
|
||||
public function testCalculationTypeNull(string $type, string $resultB1, string $resultB2): void
|
||||
{
|
||||
Functions::setCompatibilityMode($type);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A2', 'Hello');
|
||||
$this->setCell('B1', '=LEFT(A1, 1)');
|
||||
$this->setCell('B2', '=LEFT(A2, A1)');
|
||||
self::assertEquals($resultB1, $sheet->getCell('B1')->getCalculatedValue());
|
||||
self::assertEquals($resultB2, $sheet->getCell('B2')->getCalculatedValue());
|
||||
}
|
||||
|
||||
public function providerCalculationTypeLEFTNull(): array
|
||||
{
|
||||
return [
|
||||
'Excel LEFT(null, 1) AND LEFT("hello", null)' => [
|
||||
Functions::COMPATIBILITY_EXCEL,
|
||||
'',
|
||||
'',
|
||||
],
|
||||
'Gnumeric LEFT(null, 1) AND LEFT("hello", null)' => [
|
||||
Functions::COMPATIBILITY_GNUMERIC,
|
||||
'',
|
||||
'H',
|
||||
],
|
||||
'OpenOffice LEFT(null, 1) AND LEFT("hello", null)' => [
|
||||
Functions::COMPATIBILITY_OPENOFFICE,
|
||||
'',
|
||||
'',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,20 +2,25 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class LenTest extends TestCase
|
||||
class LenTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerLEN
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $value
|
||||
* @param mixed $str
|
||||
*/
|
||||
public function testLEN($expectedResult, $value): void
|
||||
public function testLEN($expectedResult, $str = 'omitted'): void
|
||||
{
|
||||
$result = TextData::STRINGLENGTH($value);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($str === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=LEN()');
|
||||
} else {
|
||||
$this->setCell('A1', $str);
|
||||
$sheet->getCell('B1')->setValue('=LEN(A1)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,26 +2,27 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PhpOffice\PhpSpreadsheet\Settings;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class LowerTest extends TestCase
|
||||
class LowerTest extends AllSetupTeardown
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Settings::setLocale('en_US');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerLOWER
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $value
|
||||
* @param mixed $str
|
||||
*/
|
||||
public function testLOWER($expectedResult, $value): void
|
||||
public function testLOWER($expectedResult, $str = 'omitted'): void
|
||||
{
|
||||
$result = TextData::LOWERCASE($value);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($str === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=LOWER()');
|
||||
} else {
|
||||
$this->setCell('A1', $str);
|
||||
$sheet->getCell('B1')->setValue('=LOWER(A1)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
@ -41,14 +42,13 @@ class LowerTest extends TestCase
|
|||
{
|
||||
$newLocale = Settings::setLocale($locale);
|
||||
if ($newLocale === false) {
|
||||
Settings::setLocale('en_US');
|
||||
self::markTestSkipped('Unable to set locale for locale-specific test');
|
||||
}
|
||||
|
||||
$result = TextData::LOWERCASE($value);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', $value);
|
||||
$sheet->getCell('B1')->setValue('=LOWER(A1)');
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
|
||||
Settings::setLocale('en_US');
|
||||
}
|
||||
|
||||
public function providerLocaleLOWER(): array
|
||||
|
|
|
|||
|
|
@ -2,25 +2,39 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Settings;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class MidTest extends TestCase
|
||||
class MidTest extends AllSetupTeardown
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Settings::setLocale('en_US');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerMID
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $str string from which to extract
|
||||
* @param mixed $start position at which to start
|
||||
* @param mixed $cnt number of characters to extract
|
||||
*/
|
||||
public function testMID($expectedResult, ...$args): void
|
||||
public function testMID($expectedResult, $str = 'omitted', $start = 'omitted', $cnt = 'omitted'): void
|
||||
{
|
||||
$result = TextData::MID(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($str === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=MID()');
|
||||
} elseif ($start === 'omitted') {
|
||||
$this->setCell('A1', $str);
|
||||
$sheet->getCell('B1')->setValue('=MID(A1)');
|
||||
} elseif ($cnt === 'omitted') {
|
||||
$this->setCell('A1', $str);
|
||||
$this->setCell('A2', $start);
|
||||
$sheet->getCell('B1')->setValue('=MID(A1, A2)');
|
||||
} else {
|
||||
$this->setCell('A1', $str);
|
||||
$this->setCell('A2', $start);
|
||||
$this->setCell('A3', $cnt);
|
||||
$sheet->getCell('B1')->setValue('=MID(A1, A2, A3)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
@ -38,18 +52,20 @@ class MidTest extends TestCase
|
|||
* @param mixed $offset
|
||||
* @param mixed $characters
|
||||
*/
|
||||
public function testLowerWithLocaleBoolean($expectedResult, $locale, $value, $offset, $characters): void
|
||||
public function testMiddleWithLocaleBoolean($expectedResult, $locale, $value, $offset, $characters): void
|
||||
{
|
||||
$newLocale = Settings::setLocale($locale);
|
||||
if ($newLocale === false) {
|
||||
Settings::setLocale('en_US');
|
||||
self::markTestSkipped('Unable to set locale for locale-specific test');
|
||||
}
|
||||
|
||||
$result = TextData::MID($value, $offset, $characters);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', $value);
|
||||
$this->setCell('A2', $offset);
|
||||
$this->setCell('A3', $characters);
|
||||
$sheet->getCell('B1')->setValue('=MID(A1, A2, A3)');
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
|
||||
Settings::setLocale('en_US');
|
||||
}
|
||||
|
||||
public function providerLocaleMID(): array
|
||||
|
|
@ -65,4 +81,125 @@ class MidTest extends TestCase
|
|||
['ОЖ', 'bg', false, 2, 2],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerCalculationTypeMIDTrue
|
||||
*/
|
||||
public function testCalculationTypeTrue(string $type, string $resultB1, string $resultB2, string $resultB3): void
|
||||
{
|
||||
Functions::setCompatibilityMode($type);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', true);
|
||||
$this->setCell('A2', 'hello');
|
||||
$this->setCell('B1', '=MID(A1, 3, 1)');
|
||||
$this->setCell('B2', '=MID(A2, A1, 1)');
|
||||
$this->setCell('B3', '=MID(A2, 2, A1)');
|
||||
self::assertEquals($resultB1, $sheet->getCell('B1')->getCalculatedValue());
|
||||
self::assertEquals($resultB2, $sheet->getCell('B2')->getCalculatedValue());
|
||||
self::assertEquals($resultB3, $sheet->getCell('B3')->getCalculatedValue());
|
||||
}
|
||||
|
||||
public function providerCalculationTypeMIDTrue(): array
|
||||
{
|
||||
return [
|
||||
'Excel MID(true,3,1), MID("hello",true, 1), MID("hello", 2, true)' => [
|
||||
Functions::COMPATIBILITY_EXCEL,
|
||||
'U',
|
||||
'h',
|
||||
'e',
|
||||
],
|
||||
'Gnumeric MID(true,3,1), MID("hello",true, 1), MID("hello", 2, true)' => [
|
||||
Functions::COMPATIBILITY_GNUMERIC,
|
||||
'U',
|
||||
'h',
|
||||
'e',
|
||||
],
|
||||
'OpenOffice MID(true,3,1), MID("hello",true, 1), MID("hello", 2, true)' => [
|
||||
Functions::COMPATIBILITY_OPENOFFICE,
|
||||
'',
|
||||
'#VALUE!',
|
||||
'#VALUE!',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerCalculationTypeMIDFalse
|
||||
*/
|
||||
public function testCalculationTypeFalse(string $type, string $resultB1, string $resultB2): void
|
||||
{
|
||||
Functions::setCompatibilityMode($type);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', false);
|
||||
$this->setCell('A2', 'Hello');
|
||||
$this->setCell('B1', '=MID(A1, 3, 1)');
|
||||
$this->setCell('B2', '=MID(A2, A1, 1)');
|
||||
$this->setCell('B3', '=MID(A2, 2, A1)');
|
||||
self::assertEquals($resultB1, $sheet->getCell('B1')->getCalculatedValue());
|
||||
self::assertEquals($resultB2, $sheet->getCell('B2')->getCalculatedValue());
|
||||
}
|
||||
|
||||
public function providerCalculationTypeMIDFalse(): array
|
||||
{
|
||||
return [
|
||||
'Excel MID(false,3,1), MID("hello", false, 1), MID("hello", 2, false)' => [
|
||||
Functions::COMPATIBILITY_EXCEL,
|
||||
'L',
|
||||
'#VALUE!',
|
||||
'',
|
||||
],
|
||||
'Gnumeric MID(false,3,1), MID("hello", false, 1), MID("hello", 2, false)' => [
|
||||
Functions::COMPATIBILITY_GNUMERIC,
|
||||
'L',
|
||||
'#VALUE!',
|
||||
'',
|
||||
],
|
||||
'OpenOffice MID(false,3,1), MID("hello", false, 1), MID("hello", 2, false)' => [
|
||||
Functions::COMPATIBILITY_OPENOFFICE,
|
||||
'',
|
||||
'#VALUE!',
|
||||
'#VALUE!',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerCalculationTypeMIDNull
|
||||
*/
|
||||
public function testCalculationTypeNull(string $type, string $resultB1, string $resultB2, string $resultB3): void
|
||||
{
|
||||
Functions::setCompatibilityMode($type);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A2', 'Hello');
|
||||
$this->setCell('B1', '=MID(A1, 3, 1)');
|
||||
$this->setCell('B2', '=MID(A2, A1, 1)');
|
||||
$this->setCell('B3', '=MID(A2, 2, A1)');
|
||||
self::assertEquals($resultB1, $sheet->getCell('B1')->getCalculatedValue());
|
||||
self::assertEquals($resultB2, $sheet->getCell('B2')->getCalculatedValue());
|
||||
self::assertEquals($resultB3, $sheet->getCell('B3')->getCalculatedValue());
|
||||
}
|
||||
|
||||
public function providerCalculationTypeMIDNull(): array
|
||||
{
|
||||
return [
|
||||
'Excel MID(null,3,1), MID("hello", null, 1), MID("hello", 2, null)' => [
|
||||
Functions::COMPATIBILITY_EXCEL,
|
||||
'',
|
||||
'#VALUE!',
|
||||
'',
|
||||
],
|
||||
'Gnumeric MID(null,3,1), MID("hello", null, 1), MID("hello", 2, null)' => [
|
||||
Functions::COMPATIBILITY_GNUMERIC,
|
||||
'',
|
||||
'#VALUE!',
|
||||
'',
|
||||
],
|
||||
'OpenOffice MID(null,3,1), MID("hello", null, 1), MID("hello", 2, null)' => [
|
||||
Functions::COMPATIBILITY_OPENOFFICE,
|
||||
'',
|
||||
'#VALUE!',
|
||||
'',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,19 +2,36 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class NumberValueTest extends TestCase
|
||||
class NumberValueTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerNUMBERVALUE
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $number
|
||||
* @param mixed $decimal
|
||||
* @param mixed $group
|
||||
*/
|
||||
public function testNUMBERVALUE($expectedResult, array $args): void
|
||||
public function testNUMBERVALUE($expectedResult, $number = 'omitted', $decimal = 'omitted', $group = 'omitted'): void
|
||||
{
|
||||
$result = TextData::NUMBERVALUE(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($number === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=NUMBERVALUE()');
|
||||
} elseif ($decimal === 'omitted') {
|
||||
$this->setCell('A1', $number);
|
||||
$sheet->getCell('B1')->setValue('=NUMBERVALUE(A1)');
|
||||
} elseif ($group === 'omitted') {
|
||||
$this->setCell('A1', $number);
|
||||
$this->setCell('A2', $decimal);
|
||||
$sheet->getCell('B1')->setValue('=NUMBERVALUE(A1, A2)');
|
||||
} else {
|
||||
$this->setCell('A1', $number);
|
||||
$this->setCell('A2', $decimal);
|
||||
$this->setCell('A3', $group);
|
||||
$sheet->getCell('B1')->setValue('=NUMBERVALUE(A1, A2, A3)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
class OpenOfficeTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerOpenOffice
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
*/
|
||||
public function testOpenOffice($expectedResult, string $formula): void
|
||||
{
|
||||
$this->setOpenOffice();
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', $formula);
|
||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
public function providerOpenOffice(): array
|
||||
{
|
||||
return require 'tests/data/Calculation/TextData/OpenOffice.php';
|
||||
}
|
||||
}
|
||||
|
|
@ -2,26 +2,27 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PhpOffice\PhpSpreadsheet\Settings;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ProperTest extends TestCase
|
||||
class ProperTest extends AllSetupTeardown
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Settings::setLocale('en_US');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerPROPER
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $value
|
||||
* @param mixed $str
|
||||
*/
|
||||
public function testPROPER($expectedResult, $value): void
|
||||
public function testPROPER($expectedResult, $str = 'omitted'): void
|
||||
{
|
||||
$result = TextData::PROPERCASE($value);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($str === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=PROPER()');
|
||||
} else {
|
||||
$this->setCell('A1', $str);
|
||||
$sheet->getCell('B1')->setValue('=PROPER(A1)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
@ -41,14 +42,13 @@ class ProperTest extends TestCase
|
|||
{
|
||||
$newLocale = Settings::setLocale($locale);
|
||||
if ($newLocale === false) {
|
||||
Settings::setLocale('en_US');
|
||||
self::markTestSkipped('Unable to set locale for locale-specific test');
|
||||
}
|
||||
|
||||
$result = TextData::PROPERCASE($value);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', $value);
|
||||
$sheet->getCell('B1')->setValue('=PROPER(A1)');
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
|
||||
Settings::setLocale('en_US');
|
||||
}
|
||||
|
||||
public function providerLocaleLOWER(): array
|
||||
|
|
|
|||
|
|
@ -2,19 +2,43 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ReplaceTest extends TestCase
|
||||
class ReplaceTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerREPLACE
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $oldText
|
||||
* @param mixed $start
|
||||
* @param mixed $count
|
||||
* @param mixed $newText
|
||||
*/
|
||||
public function testREPLACE($expectedResult, ...$args): void
|
||||
public function testREPLACE($expectedResult, $oldText = 'omitted', $start = 'omitted', $count = 'omitted', $newText = 'omitted'): void
|
||||
{
|
||||
$result = TextData::REPLACE(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($oldText === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=REPLACE()');
|
||||
} elseif ($start === 'omitted') {
|
||||
$this->setCell('A1', $oldText);
|
||||
$sheet->getCell('B1')->setValue('=REPLACE(A1)');
|
||||
} elseif ($count === 'omitted') {
|
||||
$this->setCell('A1', $oldText);
|
||||
$this->setCell('A2', $start);
|
||||
$sheet->getCell('B1')->setValue('=REPLACE(A1, A2)');
|
||||
} elseif ($newText === 'omitted') {
|
||||
$this->setCell('A1', $oldText);
|
||||
$this->setCell('A2', $start);
|
||||
$this->setCell('A3', $count);
|
||||
$sheet->getCell('B1')->setValue('=REPLACE(A1, A2, A3)');
|
||||
} else {
|
||||
$this->setCell('A1', $oldText);
|
||||
$this->setCell('A2', $start);
|
||||
$this->setCell('A3', $count);
|
||||
$this->setCell('A4', $newText);
|
||||
$sheet->getCell('B1')->setValue('=REPLACE(A1, A2, A3, A4)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,7 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ReptTest extends TestCase
|
||||
class ReptTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerREPT
|
||||
|
|
@ -17,37 +11,21 @@ class ReptTest extends TestCase
|
|||
* @param mixed $val
|
||||
* @param mixed $rpt
|
||||
*/
|
||||
public function testReptDirect($expectedResult, $val = null, $rpt = null): void
|
||||
public function testReptThroughEngine($expectedResult, $val = 'omitted', $rpt = 'omitted'): void
|
||||
{
|
||||
$result = TextData::builtinREPT(is_string($val) ? trim($val, '"') : $val, $rpt);
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerREPT
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $val
|
||||
* @param mixed $rpt
|
||||
*/
|
||||
public function testReptThroughEngine($expectedResult, $val = null, $rpt = null): void
|
||||
{
|
||||
if ($val === null) {
|
||||
$this->expectException(CalcExp::class);
|
||||
$formula = '=REPT()';
|
||||
} elseif ($rpt === null) {
|
||||
$this->expectException(CalcExp::class);
|
||||
$formula = "=REPT($val)";
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($val === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=REPT()');
|
||||
} elseif ($rpt === 'omitted') {
|
||||
$this->setCell('A1', $val);
|
||||
$sheet->getCell('B1')->setValue('=REPT(A1)');
|
||||
} else {
|
||||
if (is_bool($val)) {
|
||||
$val = ($val) ? Calculation::getTRUE() : Calculation::getFALSE();
|
||||
$this->setCell('A1', $val);
|
||||
$this->setCell('A2', $rpt);
|
||||
$sheet->getCell('B1')->setValue('=REPT(A1, A2)');
|
||||
}
|
||||
$formula = "=REPT($val, $rpt)";
|
||||
}
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$sheet->getCell('A1')->setValue($formula);
|
||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,25 +2,33 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Settings;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class RightTest extends TestCase
|
||||
class RightTest extends AllSetupTeardown
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Settings::setLocale('en_US');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerRIGHT
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $str string from which to extract
|
||||
* @param mixed $cnt number of characters to extract
|
||||
*/
|
||||
public function testRIGHT($expectedResult, ...$args): void
|
||||
public function testRIGHT($expectedResult, $str = 'omitted', $cnt = 'omitted'): void
|
||||
{
|
||||
$result = TextData::RIGHT(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($str === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=RIGHT()');
|
||||
} elseif ($cnt === 'omitted') {
|
||||
$this->setCell('A1', $str);
|
||||
$sheet->getCell('B1')->setValue('=RIGHT(A1)');
|
||||
} else {
|
||||
$this->setCell('A1', $str);
|
||||
$this->setCell('A2', $cnt);
|
||||
$sheet->getCell('B1')->setValue('=RIGHT(A1, A2)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
@ -41,14 +49,15 @@ class RightTest extends TestCase
|
|||
{
|
||||
$newLocale = Settings::setLocale($locale);
|
||||
if ($newLocale === false) {
|
||||
Settings::setLocale('en_US');
|
||||
self::markTestSkipped('Unable to set locale for locale-specific test');
|
||||
}
|
||||
|
||||
$result = TextData::RIGHT($value, $characters);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', $value);
|
||||
$this->setCell('A2', $characters);
|
||||
$sheet->getCell('B1')->setValue('=RIGHT(A1, A2)');
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
|
||||
Settings::setLocale('en_US');
|
||||
}
|
||||
|
||||
public function providerLocaleRIGHT(): array
|
||||
|
|
@ -64,4 +73,111 @@ class RightTest extends TestCase
|
|||
['ЖЬ', 'bg', false, 2],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerCalculationTypeRIGHTTrue
|
||||
*/
|
||||
public function testCalculationTypeTrue(string $type, string $resultB1, string $resultB2): void
|
||||
{
|
||||
Functions::setCompatibilityMode($type);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', true);
|
||||
$this->setCell('A2', 'Hello');
|
||||
$this->setCell('B1', '=RIGHT(A1, 1)');
|
||||
$this->setCell('B2', '=RIGHT(A2, A1)');
|
||||
self::assertEquals($resultB1, $sheet->getCell('B1')->getCalculatedValue());
|
||||
self::assertEquals($resultB2, $sheet->getCell('B2')->getCalculatedValue());
|
||||
}
|
||||
|
||||
public function providerCalculationTypeRIGHTTrue(): array
|
||||
{
|
||||
return [
|
||||
'Excel RIGHT(true, 1) AND RIGHT("hello", true)' => [
|
||||
Functions::COMPATIBILITY_EXCEL,
|
||||
'E',
|
||||
'o',
|
||||
],
|
||||
'Gnumeric RIGHT(true, 1) AND RIGHT("hello", true)' => [
|
||||
Functions::COMPATIBILITY_GNUMERIC,
|
||||
'E',
|
||||
'o',
|
||||
],
|
||||
'OpenOffice RIGHT(true, 1) AND RIGHT("hello", true)' => [
|
||||
Functions::COMPATIBILITY_OPENOFFICE,
|
||||
'1',
|
||||
'#VALUE!',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerCalculationTypeRIGHTFalse
|
||||
*/
|
||||
public function testCalculationTypeFalse(string $type, string $resultB1, string $resultB2): void
|
||||
{
|
||||
Functions::setCompatibilityMode($type);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', false);
|
||||
$this->setCell('A2', 'Hello');
|
||||
$this->setCell('B1', '=RIGHT(A1, 1)');
|
||||
$this->setCell('B2', '=RIGHT(A2, A1)');
|
||||
self::assertEquals($resultB1, $sheet->getCell('B1')->getCalculatedValue());
|
||||
self::assertEquals($resultB2, $sheet->getCell('B2')->getCalculatedValue());
|
||||
}
|
||||
|
||||
public function providerCalculationTypeRIGHTFalse(): array
|
||||
{
|
||||
return [
|
||||
'Excel RIGHT(false, 1) AND RIGHT("hello", false)' => [
|
||||
Functions::COMPATIBILITY_EXCEL,
|
||||
'E',
|
||||
'',
|
||||
],
|
||||
'Gnumeric RIGHT(false, 1) AND RIGHT("hello", false)' => [
|
||||
Functions::COMPATIBILITY_GNUMERIC,
|
||||
'E',
|
||||
'',
|
||||
],
|
||||
'OpenOffice RIGHT(false, 1) AND RIGHT("hello", false)' => [
|
||||
Functions::COMPATIBILITY_OPENOFFICE,
|
||||
'0',
|
||||
'#VALUE!',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerCalculationTypeRIGHTNull
|
||||
*/
|
||||
public function testCalculationTypeNull(string $type, string $resultB1, string $resultB2): void
|
||||
{
|
||||
Functions::setCompatibilityMode($type);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A2', 'Hello');
|
||||
$this->setCell('B1', '=RIGHT(A1, 1)');
|
||||
$this->setCell('B2', '=RIGHT(A2, A1)');
|
||||
self::assertEquals($resultB1, $sheet->getCell('B1')->getCalculatedValue());
|
||||
self::assertEquals($resultB2, $sheet->getCell('B2')->getCalculatedValue());
|
||||
}
|
||||
|
||||
public function providerCalculationTypeRIGHTNull(): array
|
||||
{
|
||||
return [
|
||||
'Excel RIGHT(null, 1) AND RIGHT("hello", null)' => [
|
||||
Functions::COMPATIBILITY_EXCEL,
|
||||
'',
|
||||
'',
|
||||
],
|
||||
'Gnumeric RIGHT(null, 1) AND RIGHT("hello", null)' => [
|
||||
Functions::COMPATIBILITY_GNUMERIC,
|
||||
'',
|
||||
'o',
|
||||
],
|
||||
'OpenOffice RIGHT(null, 1) AND RIGHT("hello", null)' => [
|
||||
Functions::COMPATIBILITY_OPENOFFICE,
|
||||
'',
|
||||
'',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,19 +2,36 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SearchTest extends TestCase
|
||||
class SearchTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerSEARCH
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $findText
|
||||
* @param mixed $withinText
|
||||
* @param mixed $start
|
||||
*/
|
||||
public function testSEARCH($expectedResult, ...$args): void
|
||||
public function testSEARCH($expectedResult, $findText = 'omitted', $withinText = 'omitted', $start = 'omitted'): void
|
||||
{
|
||||
$result = TextData::SEARCHINSENSITIVE(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($findText === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=SEARCH()');
|
||||
} elseif ($withinText === 'omitted') {
|
||||
$this->setCell('A1', $findText);
|
||||
$sheet->getCell('B1')->setValue('=SEARCH(A1)');
|
||||
} elseif ($start === 'omitted') {
|
||||
$this->setCell('A1', $findText);
|
||||
$this->setCell('A2', $withinText);
|
||||
$sheet->getCell('B1')->setValue('=SEARCH(A1, A2)');
|
||||
} else {
|
||||
$this->setCell('A1', $findText);
|
||||
$this->setCell('A2', $withinText);
|
||||
$this->setCell('A3', $start);
|
||||
$sheet->getCell('B1')->setValue('=SEARCH(A1, A2, A3)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,19 +2,43 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SubstituteTest extends TestCase
|
||||
class SubstituteTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerSUBSTITUTE
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $text
|
||||
* @param mixed $oldText
|
||||
* @param mixed $newText
|
||||
* @param mixed $instance
|
||||
*/
|
||||
public function testSUBSTITUTE($expectedResult, ...$args): void
|
||||
public function testSUBSTITUTE($expectedResult, $text = 'omitted', $oldText = 'omitted', $newText = 'omitted', $instance = 'omitted'): void
|
||||
{
|
||||
$result = TextData::SUBSTITUTE(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($text === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=SUBSTITUTE()');
|
||||
} elseif ($oldText === 'omitted') {
|
||||
$this->setCell('A1', $text);
|
||||
$sheet->getCell('B1')->setValue('=SUBSTITUTE(A1)');
|
||||
} elseif ($newText === 'omitted') {
|
||||
$this->setCell('A1', $text);
|
||||
$this->setCell('A2', $oldText);
|
||||
$sheet->getCell('B1')->setValue('=SUBSTITUTE(A1, A2)');
|
||||
} elseif ($instance === 'omitted') {
|
||||
$this->setCell('A1', $text);
|
||||
$this->setCell('A2', $oldText);
|
||||
$this->setCell('A3', $newText);
|
||||
$sheet->getCell('B1')->setValue('=SUBSTITUTE(A1, A2, A3)');
|
||||
} else {
|
||||
$this->setCell('A1', $text);
|
||||
$this->setCell('A2', $oldText);
|
||||
$this->setCell('A3', $newText);
|
||||
$this->setCell('A4', $instance);
|
||||
$sheet->getCell('B1')->setValue('=SUBSTITUTE(A1, A2, A3, A4)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class TextJoinTest extends TestCase
|
||||
class TextJoinTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerTEXTJOIN
|
||||
|
|
@ -14,7 +11,20 @@ class TextJoinTest extends TestCase
|
|||
*/
|
||||
public function testTEXTJOIN($expectedResult, array $args): void
|
||||
{
|
||||
$result = TextData::TEXTJOIN(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
$b1Formula = '=TEXTJOIN(';
|
||||
$comma = '';
|
||||
$row = 0;
|
||||
foreach ($args as $arg) {
|
||||
++$row;
|
||||
$this->setCell("A$row", $arg);
|
||||
$b1Formula .= $comma . "A$row";
|
||||
$comma = ',';
|
||||
}
|
||||
$b1Formula .= ')';
|
||||
$this->setCell('B1', $b1Formula);
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,19 +2,30 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class TextTest extends TestCase
|
||||
class TextTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerTEXT
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $value
|
||||
* @param mixed $format
|
||||
*/
|
||||
public function testTEXT($expectedResult, ...$args): void
|
||||
public function testTEXT($expectedResult, $value = 'omitted', $format = 'omitted'): void
|
||||
{
|
||||
$result = TextData::TEXTFORMAT(...$args);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($value === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=TEXT()');
|
||||
} elseif ($format === 'omitted') {
|
||||
$this->setCell('A1', $value);
|
||||
$sheet->getCell('B1')->setValue('=TEXT(A1)');
|
||||
} else {
|
||||
$this->setCell('A1', $value);
|
||||
$this->setCell('A2', $format);
|
||||
$sheet->getCell('B1')->setValue('=TEXT(A1, A2)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class TrimTest extends TestCase
|
||||
class TrimTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @dataProvider providerTRIM
|
||||
|
|
@ -13,9 +10,17 @@ class TrimTest extends TestCase
|
|||
* @param mixed $expectedResult
|
||||
* @param mixed $character
|
||||
*/
|
||||
public function testTRIM($expectedResult, $character): void
|
||||
public function testTRIM($expectedResult, $character = 'omitted'): void
|
||||
{
|
||||
$result = TextData::TRIMSPACES($character);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($character === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=TRIM()');
|
||||
} else {
|
||||
$this->setCell('A1', $character);
|
||||
$sheet->getCell('B1')->setValue('=TRIM(A1)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,26 +2,27 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PhpOffice\PhpSpreadsheet\Settings;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class UpperTest extends TestCase
|
||||
class UpperTest extends AllSetupTeardown
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Settings::setLocale('en_US');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerUPPER
|
||||
*
|
||||
* @param mixed $expectedResult
|
||||
* @param mixed $value
|
||||
* @param mixed $str
|
||||
*/
|
||||
public function testUPPER($expectedResult, $value): void
|
||||
public function testUPPER($expectedResult, $str = 'omitted'): void
|
||||
{
|
||||
$result = TextData::UPPERCASE($value);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($str === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=UPPER()');
|
||||
} else {
|
||||
$this->setCell('A1', $str);
|
||||
$sheet->getCell('B1')->setValue('=UPPER(A1)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
|
|
@ -41,14 +42,13 @@ class UpperTest extends TestCase
|
|||
{
|
||||
$newLocale = Settings::setLocale($locale);
|
||||
if ($newLocale === false) {
|
||||
Settings::setLocale('en_US');
|
||||
self::markTestSkipped('Unable to set locale for locale-specific test');
|
||||
}
|
||||
|
||||
$result = TextData::UPPERCASE($value);
|
||||
$sheet = $this->getSheet();
|
||||
$this->setCell('A1', $value);
|
||||
$sheet->getCell('B1')->setValue('=UPPER(A1)');
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
|
||||
Settings::setLocale('en_US');
|
||||
}
|
||||
|
||||
public function providerLocaleLOWER(): array
|
||||
|
|
|
|||
|
|
@ -2,11 +2,9 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\TextData;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ValueTest extends TestCase
|
||||
class ValueTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
|
|
@ -25,6 +23,7 @@ class ValueTest extends TestCase
|
|||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->currencyCode = StringHelper::getCurrencyCode();
|
||||
$this->decimalSeparator = StringHelper::getDecimalSeparator();
|
||||
$this->thousandsSeparator = StringHelper::getThousandsSeparator();
|
||||
|
|
@ -32,6 +31,7 @@ class ValueTest extends TestCase
|
|||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
StringHelper::setCurrencyCode($this->currencyCode);
|
||||
StringHelper::setDecimalSeparator($this->decimalSeparator);
|
||||
StringHelper::setThousandsSeparator($this->thousandsSeparator);
|
||||
|
|
@ -43,13 +43,21 @@ class ValueTest extends TestCase
|
|||
* @param mixed $expectedResult
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function testVALUE($expectedResult, $value): void
|
||||
public function testVALUE($expectedResult, $value = 'omitted'): void
|
||||
{
|
||||
StringHelper::setDecimalSeparator('.');
|
||||
StringHelper::setThousandsSeparator(' ');
|
||||
StringHelper::setCurrencyCode('$');
|
||||
|
||||
$result = TextData::VALUE($value);
|
||||
$this->mightHaveException($expectedResult);
|
||||
$sheet = $this->getSheet();
|
||||
if ($value === 'omitted') {
|
||||
$sheet->getCell('B1')->setValue('=VALUE()');
|
||||
} else {
|
||||
$this->setCell('A1', $value);
|
||||
$sheet->getCell('B1')->setValue('=VALUE(A1)');
|
||||
}
|
||||
$result = $sheet->getCell('B1')->getCalculatedValue();
|
||||
self::assertEqualsWithDelta($expectedResult, $result, 1E-8);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,4 +61,10 @@ return [
|
|||
'#VALUE!', // '†',
|
||||
0x2020,
|
||||
],
|
||||
'omitted argument' => ['exception'],
|
||||
'non-printable' => ["\x02", 2],
|
||||
'bool argument' => ["\x01", true],
|
||||
'null argument' => ['#VALUE!', null],
|
||||
'ascii 1 is 49' => ['1', 49],
|
||||
'ascii 0 is 48' => ['0', 48],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -25,4 +25,5 @@ return [
|
|||
null,
|
||||
null,
|
||||
],
|
||||
'omitted argument' => ['exception'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -69,4 +69,5 @@ return [
|
|||
0x2020,
|
||||
'†',
|
||||
],
|
||||
'omitted argument' => ['exception'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -18,4 +18,5 @@ return [
|
|||
'-',
|
||||
true,
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -45,4 +45,10 @@ return [
|
|||
123.456,
|
||||
'ABC',
|
||||
],
|
||||
'omitted amount' => ['exception'],
|
||||
'omitted decimals' => ['$123.46', 123.456],
|
||||
'null decimals' => ['$123', 123.456, null],
|
||||
'boolean decimals' => ['$123.5', 123.456, true],
|
||||
'boolean value' => ['$1.00', true],
|
||||
'null value' => ['$0.00', null],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -36,4 +36,6 @@ return [
|
|||
' ',
|
||||
'',
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
'one argument1' => ['exception', 'abc'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -106,4 +106,6 @@ return [
|
|||
true,
|
||||
'Mark Baker',
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
'one argument' => ['exception', 'a'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -59,4 +59,9 @@ return [
|
|||
'ABC',
|
||||
null,
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
'just one argument is okay' => ['123.00', 123],
|
||||
'null second argument' => ['123', 123, null],
|
||||
'false second argument' => ['123', 123, false],
|
||||
'true second argument' => ['123.0', 123, true],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -26,11 +26,15 @@ return [
|
|||
'QWERTYUIOP',
|
||||
'NaN',
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
'null length defaults to 0' => [
|
||||
'',
|
||||
'QWERTYUIOP',
|
||||
null,
|
||||
],
|
||||
'omitted length defaults to 1' => [
|
||||
'Q',
|
||||
'QWERTYUIOP',
|
||||
],
|
||||
[
|
||||
'ABC',
|
||||
'ABCDEFGHI',
|
||||
|
|
@ -61,4 +65,7 @@ return [
|
|||
false,
|
||||
2,
|
||||
],
|
||||
'string not specified' => [
|
||||
'exception',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -25,4 +25,5 @@ return [
|
|||
5,
|
||||
false,
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -29,4 +29,5 @@ return [
|
|||
'false',
|
||||
false,
|
||||
],
|
||||
'no argument' => ['exception'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -37,11 +37,24 @@ return [
|
|||
2,
|
||||
'NaN',
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
'length null treated as zero' => [
|
||||
'',
|
||||
'QWERTYUIOP',
|
||||
2,
|
||||
null,
|
||||
],
|
||||
'length not specified' => [
|
||||
'exception',
|
||||
'QWERTYUIOP',
|
||||
5,
|
||||
],
|
||||
'start not specified' => [
|
||||
'exception',
|
||||
'QWERTYUIOP',
|
||||
],
|
||||
'string not specified' => [
|
||||
'exception',
|
||||
],
|
||||
[
|
||||
'IOP',
|
||||
'QWERTYUIOP',
|
||||
|
|
|
|||
|
|
@ -3,50 +3,52 @@
|
|||
return [
|
||||
[
|
||||
1234567.89,
|
||||
['1,234,567.890'],
|
||||
'1,234,567.890',
|
||||
],
|
||||
[
|
||||
1234567.89,
|
||||
['1 234 567,890', ',', ' '],
|
||||
'1 234 567,890', ',', ' ',
|
||||
],
|
||||
[
|
||||
-1234567.89,
|
||||
['-1 234 567,890', ',', ' '],
|
||||
'-1 234 567,890', ',', ' ',
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
['1 234 567,890-', ',', ' '],
|
||||
'1 234 567,890-', ',', ' ',
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
['1,234,567.890,123'],
|
||||
'1,234,567.890,123',
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
['1.234.567.890,123'],
|
||||
'1.234.567.890,123',
|
||||
],
|
||||
[
|
||||
1234567.890,
|
||||
['1.234.567,890', ',', '.'],
|
||||
'1.234.567,890', ',', '.',
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
['1.234.567,89'],
|
||||
'1.234.567,89',
|
||||
],
|
||||
[
|
||||
12345.6789,
|
||||
['1,234,567.89%'],
|
||||
'1,234,567.89%',
|
||||
],
|
||||
[
|
||||
123.456789,
|
||||
['1,234,567.89%%'],
|
||||
'1,234,567.89%%',
|
||||
],
|
||||
[
|
||||
1.23456789,
|
||||
['1,234,567.89%%%'],
|
||||
'1,234,567.89%%%',
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
['1,234,567.89-%'],
|
||||
'1,234,567.89-%',
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
'boolean argument' => ['#VALUE!', true],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'OO allows CHAR(0)' => ["\x00", '=CHAR(0)'],
|
||||
'OO treats CODE(bool) as 0/1' => ['48', '=CODE(FALSE)'],
|
||||
'OO treats bool as string as 0/1 to REPT' => ['111', '=REPT(true, 3)'],
|
||||
'OO treats bool as string as 0/1 to CLEAN' => ['0', '=CLEAN(false)'],
|
||||
'OO treats bool as string as 0/1 to TRIM' => ['1', '=TRIM(true)'],
|
||||
'OO treats bool as string as 0/1 to LEN' => ['1', '=LEN(false)'],
|
||||
'OO treats bool as string as 0/1 to EXACT parm 1' => [true, '=EXACT(true, 1)'],
|
||||
'OO treats bool as string as 0/1 to EXACT parm 2' => [true, '=EXACT(0, false)'],
|
||||
'OO treats bool as string as 0/1 to FIND parm 1' => [2, '=FIND(true, "210")'],
|
||||
'OO treats bool as string as 0/1 to FIND parm 2' => [1, '=FIND(0, false)'],
|
||||
'OO treats true as int 1 to FIND parm 3' => [1, '=FIND("a", "aba", true)'],
|
||||
'OO treats false as int 0 to FIND parm 3' => ['#VALUE!', '=FIND("a", "aba", false)'],
|
||||
'OO treats bool as string as 0/1 to SEARCH parm 1' => [2, '=SEARCH(true, "210")'],
|
||||
'OO treats bool as string as 0/1 to SEARCH parm 2' => [1, '=SEARCH(0, false)'],
|
||||
'OO treats true as int 1 to SEARCH parm 3' => [1, '=SEARCH("a", "aba", true)'],
|
||||
'OO treats false as int 0 to SEARCH parm 3' => ['#VALUE!', '=SEARCH("a", "aba", false)'],
|
||||
'OO treats true as 1 to REPLACE parm 1' => ['10', '=REPLACE(true, 3, 1, false)'],
|
||||
'OO treats false as 0 to REPLACE parm 4' => ['he0lo', '=REPLACE("hello", 3, 1, false)'],
|
||||
'OO treats false as 0 SUBSTITUTE parm 1' => ['6', '=SUBSTITUTE(true, "1", "6")'],
|
||||
'OO treats true as 1 SUBSTITUTE parm 4' => ['zbcade', '=SUBSTITUTE("abcade", "a", "z", true)'],
|
||||
'OO TEXT boolean in lieu of string' => ['0', '=TEXT(false, "@")'],
|
||||
'OO VALUE boolean in lieu of string' => ['0', '=VALUE(false)'],
|
||||
'OO NUMBERVALUE boolean in lieu of string' => ['1', '=NUMBERVALUE(true)'],
|
||||
'OO TEXTJOIN boolean in lieu of string' => ['1-0-1', '=TEXTJOIN("-", true, true, false, true)'],
|
||||
];
|
||||
|
|
@ -25,4 +25,5 @@ return [
|
|||
'False',
|
||||
false,
|
||||
],
|
||||
'no argument' => ['exception'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -57,4 +57,12 @@ return [
|
|||
0,
|
||||
' ',
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
'one argument' => ['exception', 'hello'],
|
||||
'two arguments' => ['exception', 'hello', 2],
|
||||
'three arguments' => ['exception', 'hello', 2, 2],
|
||||
'position zero' => ['#VALUE!', 'hello', 0, 2, 'xyz'],
|
||||
'negative length' => ['#VALUE!', 'hello', 3, -1, 'xyz'],
|
||||
'boolean 1st parm' => ['TRDFGE', true, 3, 1, 'DFG'],
|
||||
'boolean 4th parm' => ['heFALSElo', 'hello', 3, 1, false],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
['#VALUE!'], // exception not enough args
|
||||
['#VALUE!', '"ABC"'], // exception not enough args
|
||||
['#VALUE!', '"ABC"', '"DEF"'],
|
||||
['ABCABCABC', '"ABC"', 3],
|
||||
['ABCABC', '"ABC"', 2.2],
|
||||
['', '"ABC"', 0],
|
||||
'no arguments' => ['exception'],
|
||||
'one argument' => ['exception', 'ABC'],
|
||||
['#VALUE!', 'ABC', 'DEF'],
|
||||
['ABCABCABC', 'ABC', 3],
|
||||
['ABCABC', 'ABC', 2.2],
|
||||
['', 'ABC', 0],
|
||||
['TRUETRUE', true, 2],
|
||||
['111', 1, 3],
|
||||
['δύο δύο ', '"δύο "', 2],
|
||||
['#VALUE!', '"ABC"', -1],
|
||||
['δύο δύο ', 'δύο ', 2],
|
||||
['#VALUE!', 'ABC', -1],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -21,11 +21,15 @@ return [
|
|||
'QWERTYUIOP',
|
||||
'NaN',
|
||||
],
|
||||
[
|
||||
'#VALUE!',
|
||||
'null length defaults to 0' => [
|
||||
'',
|
||||
'QWERTYUIOP',
|
||||
null,
|
||||
],
|
||||
'omitted length defaults to 1' => [
|
||||
'P',
|
||||
'QWERTYUIOP',
|
||||
],
|
||||
[
|
||||
'GHI',
|
||||
'ABCDEFGHI',
|
||||
|
|
@ -61,4 +65,7 @@ return [
|
|||
false,
|
||||
2,
|
||||
],
|
||||
'string not specified' => [
|
||||
'exception',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -99,4 +99,6 @@ return [
|
|||
true,
|
||||
'Mark Baker',
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
'one argument' => ['exception', 'string'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -73,4 +73,16 @@ return [
|
|||
"\u{00E5}",
|
||||
'x',
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
'one argument' => ['exception', 'a'],
|
||||
'two arguments' => ['exception', 'a', 'b'],
|
||||
'negative instance' => ['#VALUE!', 'abcdefg', 'def', 123, -1],
|
||||
'non-numeric instance' => ['#VALUE!', 'abcdefg', 'def', 123, 'xyz'],
|
||||
'null instance' => ['abc123g', 'abcdefg', 'def', 123],
|
||||
'0 instance' => ['#VALUE!', 'abcdefg', 'def', 123, 0],
|
||||
'1 instance' => ['abc123g', 'abcdefg', 'def', 123, 1],
|
||||
'past last instance' => ['abcdefg', 'abcdefg', 'def', 123, 2],
|
||||
'bool false instance' => ['#VALUE!', 'abcdefg', 'def', '123', false],
|
||||
'bool true instance' => ['#VALUE!', 'abcdefg', 'def', '123', true],
|
||||
'bool text' => ['FA-SE', false, 'L', '-'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -66,4 +66,7 @@ return [
|
|||
1.75,
|
||||
'# ?/?',
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
'one argument' => ['exception', 1.75],
|
||||
'boolean in lieu of string' => ['TRUE', true, '@'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -37,4 +37,9 @@ return [
|
|||
'C:\\Users\\Mark\\Documents\\notes.doc',
|
||||
['\\', true, 'C:', 'Users', 'Mark', 'Documents', 'notes.doc'],
|
||||
],
|
||||
'no argument' => ['exception', []],
|
||||
'one argument' => ['exception', ['-']],
|
||||
'two arguments' => ['exception', ['-', true]],
|
||||
'three arguments' => ['a', ['-', true, 'a']],
|
||||
'boolean as string' => ['TRUE-FALSE-TRUE', ['-', true, true, false, true]],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -29,4 +29,5 @@ return [
|
|||
null,
|
||||
null,
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -29,4 +29,5 @@ return [
|
|||
'FALSE',
|
||||
false,
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -41,4 +41,7 @@ return [
|
|||
'0.11527777777778',
|
||||
'2:46 AM',
|
||||
],
|
||||
'no arguments' => ['exception'],
|
||||
'bool argument' => ['#VALUE!', false],
|
||||
'null argument' => ['0', null],
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in New Issue