Files
PhpSpreadsheet/samples/PivotTable/05_PivotTable_Group_Item_Counts.php
T
saifulislamferoz 97b895ecd8 Add sample for pivot field group item counts
Demonstrates the three ways a pivot field's item count is derived: a
fractional numeric range, a date grouping, and an ungrouped field taking
its items from the distinct source values.

The fractional interval (0..1 by 0.1) is the case worth showing, since
it is the one where computing bucket boundaries by index rather than by
repeated addition matters: repeated addition drifts past the last
boundary and emits a spurious zero-width "1-1" bucket, which leaves the
pivot field and cache item counts disagreeing.

SampleTest discovers and executes samples automatically, so this runs
as part of the suite.
2026-08-28 10:10:13 +06:00

84 lines
3.5 KiB
PHP

<?php
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\PivotTable\PivotField;
use PhpOffice\PhpSpreadsheet\Worksheet\PivotTable\PivotFieldGroup;
use PhpOffice\PhpSpreadsheet\Worksheet\PivotTable\PivotTableBuilder;
require __DIR__ . '/../Header.php';
/** @var PhpOffice\PhpSpreadsheet\Helper\Sample $helper */
$helper->log('Create new Spreadsheet object');
$spreadsheet = new Spreadsheet();
$spreadsheet->getProperties()->setTitle('PhpSpreadsheet PivotTable Group Item Counts Sample');
$helper->log('Add source data');
$dataSheet = $spreadsheet->getActiveSheet();
$dataSheet->setTitle('Data');
$dataSheet->fromArray(
[
['Customer', 'Score', 'OrderDate', 'Amount'],
['Alice', 0.15, '2024-01-15', 100],
['Bob', 0.35, '2024-06-20', 150],
['Carol', 0.55, '2025-02-10', 200],
['Dan', 0.75, '2025-11-05', 250],
['Erin', 0.95, '2024-09-01', 175],
],
null,
'A1'
);
// Older releases of Excel validate a pivot table strictly: every item that a
// pivot field can display must be enumerated in the pivotTableDefinition, and
// the number of those items has to agree with the group items recorded in the
// pivot cache. When the two disagree the workbook is reported as damaged and
// the pivot table is dropped, so both parts are derived from one enumeration.
// --- Fractional interval: Score bucketed 0..1 in steps of 0.1 ---
// A fractional interval is the interesting case. The bucket boundaries are
// computed by index (start + i * interval) rather than by repeatedly adding
// the interval, because repeated addition drifts: the tenth boundary would
// land just under 1.0 and produce a spurious zero-width "1-1" bucket.
$helper->log('Build pivot table grouping Score into fractional numeric ranges');
$scoreSheet = $spreadsheet->createSheet();
$scoreSheet->setTitle('ByScoreBand');
$scoreBuilder = new PivotTableBuilder($dataSheet, 'A1:D6');
$scoreBuilder
->groupFieldByNumericRange('Score', 0.1, 0.0, 1.0)
->addRowField('Score')
->addDataField('Amount', PivotField::SUBTOTAL_SUM);
$scoreBuilder->build($scoreSheet, 'A3', 'SalesByScoreBand');
$helper->log('Score yields 10 buckets (0-0.1 ... 0.9-1) plus the "<0" and ">1" bounds');
// --- Date grouping: OrderDate by quarter ---
// Date groups use the fixed labels Excel expects for the chosen unit, so the
// item count is the length of that label set.
$helper->log('Build pivot table grouping OrderDate by quarter');
$quarterSheet = $spreadsheet->createSheet();
$quarterSheet->setTitle('ByQuarter');
$quarterBuilder = new PivotTableBuilder($dataSheet, 'A1:D6');
$quarterBuilder
->groupFieldByDate('OrderDate', PivotFieldGroup::GROUP_BY_QUARTERS)
->addRowField('OrderDate')
->addDataField('Amount', PivotField::SUBTOTAL_SUM);
$quarterBuilder->build($quarterSheet, 'A3', 'SalesByQuarter');
$helper->log('OrderDate yields 6 items (<1/1/1900, Qtr1..Qtr4, >12/31/9999)');
// --- Ungrouped field: item count comes from the distinct source values ---
$helper->log('Build pivot table on an ungrouped field');
$customerSheet = $spreadsheet->createSheet();
$customerSheet->setTitle('ByCustomer');
$customerBuilder = new PivotTableBuilder($dataSheet, 'A1:D6');
$customerBuilder
->addRowField('Customer')
->addDataField('Amount', PivotField::SUBTOTAL_SUM);
$customerBuilder->build($customerSheet, 'A3', 'SalesByCustomer');
$helper->log('Customer yields one item per distinct value in the source column');
$helper->write($spreadsheet, __FILE__, ['Xlsx']);