Skip to content

Commit

Permalink
Merge pull request #4283 from oleibman/groupby
Browse files Browse the repository at this point in the history
Extremely Limited Support for GROUPBY Function
  • Loading branch information
oleibman authored Jan 9, 2025
2 parents 7456b46 + bfcfaee commit 51b1d1c
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).

- Xlsx Reader Shared Formula with Boolean Result. Partial solution for [Issue #4280](https://github.com/PHPOffice/PhpSpreadsheet/issues/4280) [PR #4281](https://github.com/PHPOffice/PhpSpreadsheet/pull/4281)
- Retitling cloned Worksheets. [Issue #641](https://github.com/PHPOffice/PhpSpreadsheet/issues/641) [PR #4302](https://github.com/PHPOffice/PhpSpreadsheet/pull/4302)
- Extremely limited support for GROUPBY function. Partial response to [Issue #4282](https://github.com/PHPOffice/PhpSpreadsheet/issues/4282) [PR #4283](https://github.com/PHPOffice/PhpSpreadsheet/pull/4283)

## 2024-12-26 - 3.7.0

Expand Down
1 change: 1 addition & 0 deletions docs/references/function-list-by-category.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ EXPAND | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Choos
FILTER | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Filter::filter
FORMULATEXT | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Formula::text
GETPIVOTDATA | **Not yet Implemented**
GROUPBY | **Not yet Implemented**
HLOOKUP | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\HLookup::lookup
HYPERLINK | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Hyperlink::set
INDEX | \PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Matrix::index
Expand Down
1 change: 1 addition & 0 deletions docs/references/function-list-by-name.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ GCD | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpread
GEOMEAN | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Averages\Mean::geometric
GESTEP | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\Compare::GESTEP
GETPIVOTDATA | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented**
GROUPBY | CATEGORY_LOOKUP_AND_REFERENCE | **Not yet Implemented**
GROWTH | CATEGORY_STATISTICAL | \PhpOffice\PhpSpreadsheet\Calculation\Statistical\Trends::GROWTH

## H
Expand Down
11 changes: 10 additions & 1 deletion src/PhpSpreadsheet/Calculation/Calculation.php
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,11 @@ public static function getExcelConstants(string $key): bool|null
'functionCall' => [Functions::class, 'DUMMY'],
'argumentCount' => '2+',
],
'GROUPBY' => [
'category' => Category::CATEGORY_LOOKUP_AND_REFERENCE,
'functionCall' => [Functions::class, 'DUMMY'],
'argumentCount' => '3-7',
],
'GROWTH' => [
'category' => Category::CATEGORY_STATISTICAL,
'functionCall' => [Statistical\Trends::class, 'GROWTH'],
Expand Down Expand Up @@ -4601,7 +4606,7 @@ private static function dataTestReference(array &$operandData): mixed
private static int $matchIndex10 = 10;

/**
* @return array<int, mixed>|false
* @return array<int, mixed>|false|string
*/
private function processTokenStack(mixed $tokens, ?string $cellID = null, ?Cell $cell = null)
{
Expand Down Expand Up @@ -5182,6 +5187,9 @@ private function processTokenStack(mixed $tokens, ?string $cellID = null, ?Cell
} elseif (preg_match('/^' . self::CALCULATION_REGEXP_DEFINEDNAME . '$/miu', $token, $matches)) {
// if the token is a named range or formula, evaluate it and push the result onto the stack
$definedName = $matches[6];
if (str_starts_with($definedName, '_xleta')) {
return Functions::NOT_YET_IMPLEMENTED;
}
if ($cell === null || $pCellWorksheet === null) {
return $this->raiseFormulaError("undefined name '$token'");
}
Expand Down Expand Up @@ -5214,6 +5222,7 @@ private function processTokenStack(mixed $tokens, ?string $cellID = null, ?Cell
}

$result = $this->evaluateDefinedName($cell, $namedRange, $pCellWorksheet, $stack, $specifiedWorksheet !== '');

if (isset($storeKey)) {
$branchStore[$storeKey] = $result;
}
Expand Down
6 changes: 5 additions & 1 deletion src/PhpSpreadsheet/Worksheet/Worksheet.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class Worksheet
public const MERGE_CELL_CONTENT_HIDE = 'hide';
public const MERGE_CELL_CONTENT_MERGE = 'merge';

public const FUNCTION_LIKE_GROUPBY = '/\\b(groupby|_xleta)\\b/i'; // weird new syntax

protected const SHEET_NAME_REQUIRES_NO_QUOTES = '/^[_\p{L}][_\p{L}\p{N}]*$/mui';

/**
Expand Down Expand Up @@ -3701,7 +3703,9 @@ public function calculateArrays(bool $preCalculateFormulas = true): void
$keys = $this->cellCollection->getCoordinates();
foreach ($keys as $key) {
if ($this->getCell($key)->getDataType() === DataType::TYPE_FORMULA) {
$this->getCell($key)->getCalculatedValue();
if (preg_match(self::FUNCTION_LIKE_GROUPBY, $this->getCell($key)->getValue()) !== 1) {
$this->getCell($key)->getCalculatedValue();
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/PhpSpreadsheet/Writer/Xlsx/FunctionPrefix.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ class FunctionPrefix
. '|drop'
. '|expand'
. '|filter'
. '|groupby'
. '|hstack'
. '|isomitted'
. '|lambda'
Expand Down
6 changes: 5 additions & 1 deletion src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php
Original file line number Diff line number Diff line change
Expand Up @@ -1578,7 +1578,11 @@ private function writeCell(XMLWriter $objWriter, PhpspreadsheetWorksheet $worksh
$mappedType = $pCell->getDataType();
if ($mappedType === DataType::TYPE_FORMULA) {
if ($this->useDynamicArrays) {
$tempCalc = $pCell->getCalculatedValue();
if (preg_match(PhpspreadsheetWorksheet::FUNCTION_LIKE_GROUPBY, $cellValue) === 1) {
$tempCalc = [];
} else {
$tempCalc = $pCell->getCalculatedValue();
}
if (is_array($tempCalc)) {
$objWriter->writeAttribute('cm', '1');
}
Expand Down
33 changes: 33 additions & 0 deletions tests/PhpSpreadsheetTests/Reader/Xlsx/GroupByLimitedTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace PhpOffice\PhpSpreadsheetTests\Reader\Xlsx;

use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;

class GroupByLimitedTest extends AbstractFunctional
{
private static string $testbook = 'tests/data/Reader/XLSX/excel-groupby-one.xlsx';

public function testRowBreaks(): void
{
$reader = new Xlsx();
$spreadsheet = $reader->load(self::$testbook);
$reloadedSpreadsheet = $this->writeAndReload($spreadsheet, 'Xlsx');
$spreadsheet->disconnectWorksheets();
$reloadedSheet = $reloadedSpreadsheet->getActiveSheet();
self::assertSame(['t' => 'array', 'ref' => 'E3:F7'], $reloadedSheet->getCell('E3')->getFormulaAttributes());
$expected = [
['Design', '$505,000 '],
['Development', '$346,000 '],
['Marketing', '$491,000 '],
['Research', '$573,000 '],
['Total', '$1,915,000 '],
[null, null],
];
self::assertSame($expected, $reloadedSheet->rangeToArray('E3:F8'));
$reloadedSpreadsheet->disconnectWorksheets();
}
}
Binary file added tests/data/Reader/XLSX/excel-groupby-one.xlsx
Binary file not shown.

0 comments on commit 51b1d1c

Please sign in to comment.