Allow multiple delimiters for `TEXTBEFORE()` and `TEXTAFTER()` functions
This commit is contained in:
parent
641b6d0ccb
commit
290d0731fe
|
|
@ -104,7 +104,8 @@ class Extract
|
|||
*
|
||||
* @param mixed $text the text that you're searching
|
||||
* Or can be an array of values
|
||||
* @param ?string $delimiter the text that marks the point before which you want to extract
|
||||
* @param null|array|string $delimiter the text that marks the point before which you want to extract
|
||||
* Multiple delimiters can be passed as an array of string values
|
||||
* @param mixed $instance The instance of the delimiter after which you want to extract the text.
|
||||
* By default, this is the first instance (1).
|
||||
* A negative value means start searching from the end of the text string.
|
||||
|
|
@ -132,7 +133,6 @@ class Extract
|
|||
}
|
||||
|
||||
$text = Helpers::extractString($text ?? '');
|
||||
$delimiter = Helpers::extractString(Functions::flattenSingleValue($delimiter ?? ''));
|
||||
$instance = (int) $instance;
|
||||
$matchMode = (int) $matchMode;
|
||||
$matchEnd = (int) $matchEnd;
|
||||
|
|
@ -141,13 +141,14 @@ class Extract
|
|||
if (is_array($split) === false) {
|
||||
return $split;
|
||||
}
|
||||
if ($delimiter === '') {
|
||||
if (Helpers::extractString(Functions::flattenSingleValue($delimiter ?? '')) === '') {
|
||||
return ($instance > 0) ? '' : $text;
|
||||
}
|
||||
|
||||
// Adjustment for a match as the first element of the split
|
||||
$flags = self::matchFlags($matchMode);
|
||||
$adjust = preg_match('/^' . preg_quote($delimiter) . "\$/{$flags}", $split[0]);
|
||||
$delimiter = self::buildDelimiter($delimiter);
|
||||
$adjust = preg_match('/^' . $delimiter . "\$/{$flags}", $split[0]);
|
||||
$oddReverseAdjustment = count($split) % 2;
|
||||
|
||||
$split = ($instance < 0)
|
||||
|
|
@ -161,7 +162,8 @@ class Extract
|
|||
* TEXTAFTER.
|
||||
*
|
||||
* @param mixed $text the text that you're searching
|
||||
* @param ?string $delimiter the text that marks the point before which you want to extract
|
||||
* @param null|array|string $delimiter the text that marks the point before which you want to extract
|
||||
* Multiple delimiters can be passed as an array of string values
|
||||
* @param mixed $instance The instance of the delimiter after which you want to extract the text.
|
||||
* By default, this is the first instance (1).
|
||||
* A negative value means start searching from the end of the text string.
|
||||
|
|
@ -189,7 +191,6 @@ class Extract
|
|||
}
|
||||
|
||||
$text = Helpers::extractString($text ?? '');
|
||||
$delimiter = Helpers::extractString(Functions::flattenSingleValue($delimiter ?? ''));
|
||||
$instance = (int) $instance;
|
||||
$matchMode = (int) $matchMode;
|
||||
$matchEnd = (int) $matchEnd;
|
||||
|
|
@ -198,13 +199,14 @@ class Extract
|
|||
if (is_array($split) === false) {
|
||||
return $split;
|
||||
}
|
||||
if ($delimiter === '') {
|
||||
if (Helpers::extractString(Functions::flattenSingleValue($delimiter ?? '')) === '') {
|
||||
return ($instance < 0) ? '' : $text;
|
||||
}
|
||||
|
||||
// Adjustment for a match as the first element of the split
|
||||
$flags = self::matchFlags($matchMode);
|
||||
$adjust = preg_match('/^' . preg_quote($delimiter) . "\$/{$flags}", $split[0]);
|
||||
$delimiter = self::buildDelimiter($delimiter);
|
||||
$adjust = preg_match('/^' . $delimiter . "\$/{$flags}", $split[0]);
|
||||
$oddReverseAdjustment = count($split) % 2;
|
||||
|
||||
$split = ($instance < 0)
|
||||
|
|
@ -215,21 +217,23 @@ class Extract
|
|||
}
|
||||
|
||||
/**
|
||||
* @param null|array|string $delimiter
|
||||
* @param int $matchMode
|
||||
* @param int $matchEnd
|
||||
* @param mixed $ifNotFound
|
||||
*
|
||||
* @return string|string[]
|
||||
*/
|
||||
private static function validateTextBeforeAfter(string $text, string $delimiter, int $instance, $matchMode, $matchEnd, $ifNotFound)
|
||||
private static function validateTextBeforeAfter(string $text, $delimiter, int $instance, $matchMode, $matchEnd, $ifNotFound)
|
||||
{
|
||||
$flags = self::matchFlags($matchMode);
|
||||
$delimiter = self::buildDelimiter($delimiter);
|
||||
|
||||
if (preg_match('/' . preg_quote($delimiter) . "/{$flags}", $text) === 0 && $matchEnd === 0) {
|
||||
if (preg_match('/' . $delimiter . "/{$flags}", $text) === 0 && $matchEnd === 0) {
|
||||
return $ifNotFound;
|
||||
}
|
||||
|
||||
$split = preg_split('/(' . preg_quote($delimiter) . ")/{$flags}", $text, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
$split = preg_split('/' . $delimiter . "/{$flags}", $text, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
if ($split === false) {
|
||||
return ExcelError::NA();
|
||||
}
|
||||
|
|
@ -247,6 +251,28 @@ class Extract
|
|||
return $split;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|array|string $delimiter the text that marks the point before which you want to extract
|
||||
* Multiple delimiters can be passed as an array of string values
|
||||
*/
|
||||
private static function buildDelimiter($delimiter): string
|
||||
{
|
||||
if (is_array($delimiter)) {
|
||||
$delimiter = Functions::flattenArray($delimiter);
|
||||
$quotedDelimiters = array_map(
|
||||
function ($delimiter) {
|
||||
return preg_quote($delimiter ?? '');
|
||||
},
|
||||
$delimiter
|
||||
);
|
||||
$delimiters = implode('|', $quotedDelimiters);
|
||||
|
||||
return '(' . $delimiters . ')';
|
||||
}
|
||||
|
||||
return '(' . preg_quote($delimiter ?? '') . ')';
|
||||
}
|
||||
|
||||
private static function matchFlags(int $matchMode): string
|
||||
{
|
||||
return ($matchMode === 0) ? 'mu' : 'miu';
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
|
||||
class TextAfterTest extends AllSetupTeardown
|
||||
{
|
||||
/**
|
||||
|
|
@ -14,14 +12,17 @@ class TextAfterTest extends AllSetupTeardown
|
|||
$text = $arguments[0];
|
||||
$delimiter = $arguments[1];
|
||||
|
||||
$args = 'A1, A2';
|
||||
$args = (is_array($delimiter)) ? 'A1, {A2,A3}' : 'A1, A2';
|
||||
$args .= (isset($arguments[2])) ? ", {$arguments[2]}" : ',';
|
||||
$args .= (isset($arguments[3])) ? ", {$arguments[3]}" : ',';
|
||||
$args .= (isset($arguments[4])) ? ", {$arguments[4]}" : ',';
|
||||
|
||||
$worksheet = $this->getSheet();
|
||||
$worksheet->getCell('A1')->setValue($text);
|
||||
$worksheet->getCell('A2')->setValue($delimiter);
|
||||
$worksheet->getCell('A2')->setValue((is_array($delimiter)) ? $delimiter[0] : $delimiter);
|
||||
if (is_array($delimiter)) {
|
||||
$worksheet->getCell('A3')->setValue($delimiter[1]);
|
||||
}
|
||||
$worksheet->getCell('B1')->setValue("=TEXTAFTER({$args})");
|
||||
|
||||
$result = $worksheet->getCell('B1')->getCalculatedValue();
|
||||
|
|
@ -32,18 +33,4 @@ class TextAfterTest extends AllSetupTeardown
|
|||
{
|
||||
return require 'tests/data/Calculation/TextData/TEXTAFTER.php';
|
||||
}
|
||||
|
||||
public function testTextAfterWithArray(): void
|
||||
{
|
||||
$calculation = Calculation::getInstance();
|
||||
|
||||
$text = "Red Riding Hood's red riding hood";
|
||||
$delimiter = 'red';
|
||||
|
||||
$args = "\"{$text}\", \"{$delimiter}\", 1, {0;1}";
|
||||
|
||||
$formula = "=TEXTAFTER({$args})";
|
||||
$result = $calculation->_calculateFormulaValue($formula);
|
||||
self::assertEquals([[' riding hood'], [" Riding Hood's red riding hood"]], $result);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,14 +12,17 @@ class TextBeforeTest extends AllSetupTeardown
|
|||
$text = $arguments[0];
|
||||
$delimiter = $arguments[1];
|
||||
|
||||
$args = 'A1, A2';
|
||||
$args = (is_array($delimiter)) ? 'A1, {A2,A3}' : 'A1, A2';
|
||||
$args .= (isset($arguments[2])) ? ", {$arguments[2]}" : ',';
|
||||
$args .= (isset($arguments[3])) ? ", {$arguments[3]}" : ',';
|
||||
$args .= (isset($arguments[4])) ? ", {$arguments[4]}" : ',';
|
||||
|
||||
$worksheet = $this->getSheet();
|
||||
$worksheet->getCell('A1')->setValue($text);
|
||||
$worksheet->getCell('A2')->setValue($delimiter);
|
||||
$worksheet->getCell('A2')->setValue((is_array($delimiter)) ? $delimiter[0] : $delimiter);
|
||||
if (is_array($delimiter)) {
|
||||
$worksheet->getCell('A3')->setValue($delimiter[1]);
|
||||
}
|
||||
$worksheet->getCell('B1')->setValue("=TEXTBEFORE({$args})");
|
||||
|
||||
$result = $worksheet->getCell('B1')->getCalculatedValue();
|
||||
|
|
|
|||
|
|
@ -212,4 +212,40 @@ return [
|
|||
1,
|
||||
],
|
||||
],
|
||||
'Multi-delimiter Case-Insensitive Offset 1' => [
|
||||
" riding hood's red riding hood",
|
||||
[
|
||||
"Little Red riding hood's red riding hood",
|
||||
['HOOD', 'RED'],
|
||||
1,
|
||||
1,
|
||||
],
|
||||
],
|
||||
'Multi-delimiter Case-Insensitive Offset 2' => [
|
||||
"'s red riding hood",
|
||||
[
|
||||
"Little Red riding hood's red riding hood",
|
||||
['HOOD', 'RED'],
|
||||
2,
|
||||
1,
|
||||
],
|
||||
],
|
||||
'Multi-delimiter Case-Insensitive Offset 3' => [
|
||||
' riding hood',
|
||||
[
|
||||
"Little Red riding hood's red riding hood",
|
||||
['HOOD', 'RED'],
|
||||
3,
|
||||
1,
|
||||
],
|
||||
],
|
||||
'Multi-delimiter Case-Insensitive Offset -2' => [
|
||||
' riding hood',
|
||||
[
|
||||
"Little Red riding hood's red riding hood",
|
||||
['HOOD', 'RED'],
|
||||
-2,
|
||||
1,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -204,4 +204,40 @@ return [
|
|||
1,
|
||||
],
|
||||
],
|
||||
'Multi-delimiter Case-Insensitive Offset 1' => [
|
||||
'Little ',
|
||||
[
|
||||
"Little Red riding hood's red riding hood",
|
||||
['HOOD', 'RED'],
|
||||
1,
|
||||
1,
|
||||
],
|
||||
],
|
||||
'Multi-delimiter Case-Insensitive Offset 2' => [
|
||||
'Little Red riding ',
|
||||
[
|
||||
"Little Red riding hood's red riding hood",
|
||||
['HOOD', 'RED'],
|
||||
2,
|
||||
1,
|
||||
],
|
||||
],
|
||||
'Multi-delimiter Case-Insensitive Offset 3' => [
|
||||
"Little Red riding hood's ",
|
||||
[
|
||||
"Little Red riding hood's red riding hood",
|
||||
['HOOD', 'RED'],
|
||||
3,
|
||||
1,
|
||||
],
|
||||
],
|
||||
'Multi-delimiter Case-Insensitive Offset -2' => [
|
||||
"Little Red riding hood's ",
|
||||
[
|
||||
"Little Red riding hood's red riding hood",
|
||||
['HOOD', 'RED'],
|
||||
-2,
|
||||
1,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in New Issue