DataTable: add summary statistics for selected cells#8326
DataTable: add summary statistics for selected cells#8326mscolnick merged 26 commits intomarimo-team:mainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR adds Excel-like summary statistics (Count, Sum, Average) to the DataTable component that appear when users select two or more cells. The feature filters numeric values intelligently, excluding non-numeric data from Sum and Average calculations while including all data cells in the Count. The statistics display is positioned below the table and only appears when multiple cells are selected.
Changes:
- Added
getNumericValuesFromSelectedCellsandcountDataCellsInSelectionutility functions to extract and count cell data - Created
CellSelectionStatscomponent to display Count, Sum, and Average statistics - Moved
CellSelectionProviderto wrap both the table and the new stats component, enabling state sharing
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/components/data-table/range-focus/utils.ts | Added utility functions to count selected cells and extract numeric values, filtering out checkbox columns and non-numeric data |
| frontend/src/components/data-table/range-focus/cell-selection-stats.tsx | New component displaying statistics (Count, Sum, Average) for selected cells with 8 decimal place rounding |
| frontend/src/components/data-table/range-focus/tests/utils.test.ts | Added comprehensive tests for new utility functions and refactored existing test helpers into test-utils.ts |
| frontend/src/components/data-table/range-focus/tests/test-utils.ts | Extracted reusable mock helper functions (createMockCell, createMockRow, createMockTable) for test consistency |
| frontend/src/components/data-table/range-focus/tests/cell-selection-stats.test.tsx | Added thorough tests covering various scenarios: numeric/non-numeric values, rounding, checkbox exclusion, and edge cases |
| frontend/src/components/data-table/data-table.tsx | Repositioned CellSelectionProvider to wrap both table and stats component, added CellSelectionStats below the table |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
This looks really cool! Some of the team may be out (& I'm unwell), but happy to review soon. |
| continue; | ||
| } | ||
|
|
||
| const tableCell = row.getAllCells().find((c) => c.id === cellId); |
There was a problem hiding this comment.
I think this may be slightly unoptimized (I see it in old code too, and maybe we can replace it). The code below uses row.getValue instead of iterating through all the cells in a row.
export function getNumericValuesFromSelectedCells<TData>(
table: Table<TData>,
selectedCellIds: Set<string>,
): number[] {
const numericValues: number[] = [];
for (const cellId of selectedCellIds) {
if (cellId.includes(SELECT_COLUMN_ID)) {
continue;
}
const { rowId, columnId } = getRowAndColumnId(cellId);
const row = table.getRow(rowId);
if (!row) {
continue;
}
const value = row.getValue(columnId);
let num: number;
if (typeof value === "number") {
num = value;
} else if (typeof value === "string") {
if (value.trim() === "") {
continue;
}
num = Number(value);
} else {
continue;
}
if (Number.isFinite(num)) {
numericValues.push(num);
}
}
return numericValues;
}
// at the end of the file
function getRowAndColumnId(cellId: string) {
const sepIdx = cellId.indexOf("_");
const rowId = cellId.slice(0, sepIdx);
const columnId = cellId.slice(sepIdx + 1);
return { rowId, columnId };
}There was a problem hiding this comment.
I'll fix this along with the old code as well?
There was a problem hiding this comment.
Yeah, that would be good, you may need to update the tests as well.
There was a problem hiding this comment.
If we use this approach, it seems like there is no easy way to distinguish between missing cells and cells with value undefined. row.getValue(columnId) might return undefined both when the cell itself has value undefined. The tanstack table row also does not expose any methods like contains(columnId).
Do you have any suggestions? Was wondering whether a cell's value being undefined is possible in the first place, or will only empty cells have value of undefined?
There was a problem hiding this comment.
Yeah, I think it's impossible to be undefined in the first place. I assume it would be undefined if columnId is incorrect, which shouldn't happen. I believe the test checks for this impossible scenario?
There was a problem hiding this comment.
@Light2Dark Sorry havent got a chance to look at this yet. But last I checked, there was still some tests that failed in src/components/data-table/range-focus/__tests__/utils.test.ts related to null and undefined values. Will probably check those out by tomorrow.
There was a problem hiding this comment.
ah no worries, have fixed it for you. There were other CI failures as well so I jumped in.
|
6c414ed to
05f882d
Compare
Use selectedCellsAtom to get size of cell selection and display.
Accordingly reorder components such that CellSelectionProvider's scope covers new CellSelectionStats component for it to use the selectedCellsAtom.
Add a new test-utils.ts exporting shared mock helpers (createMockCell, createMockColumn, createMockRow, createMockTable, createSelectedCell) and update utils.test.ts to import and use those helpers.
CellSelectionStats counts checkbox column on the left indicating whether a row is selected. This is counter-intuitive. Introduce utility to count all cells excluding the checkbox column.
…stats.tsx Co-authored-by: Shahmir Varqha <Sham9871@gmail.com>
Getting values from selected cells uses iterating through all cells in a row. Use row.getValue(columnId) instead for faster lookup.
85dae48 to
9530992
Compare


📝 Summary
Closes #6015
Introduce summary statistics for selected cells to the data table component. When users select two or more cells, the UI now displays the count, sum, and average of the selected numeric values.
Demo:
cell-selection-data.mov
Works also with other components where DataTable is used, e.g., dataframes.
data-frame-selection-data.mov
🔍 Description of Changes
Decisions made:
CellSelectionStatscomponent only shows when 2 or more cells are selectedFuture considerations:
Implementation Details
CellSelectionStatscomponent that displays the count, sum, and average of selected cells when two or more are selected.CellSelectionStatsinto theDataTableInternalcomponent, position is below the table. Wrap it in theCellSelectionProvidercontext.getNumericValuesFromSelectedCellsutility function inutils.tsto extract numeric values from selected cells, filtering out non-numeric and special columns.📋 Checklist