Calculated Columns let your end users add read-only values to the grid without storing those values in row data. Each calculated column has an expression, such as [revenue] - [cost], that derives its value from other columns.
Declare calculated columns in your column definitions, or let users add their own from the column menu. To let users write expressions in individual cells instead, see Formulas.
Enabling Calculated Columns Copy Link
Set the calculatedColumns grid option to true, and set calculatedExpression on a column definition:
const calculatedColumns = true;
const [columnDefs, setColumnDefs] = useState([
{ field: 'revenue' },
{ field: 'cost' },
{
colId: 'profit',
calculatedExpression: '[revenue] - [cost]',
cellDataType: 'number',
sortable: true,
filter: true,
},
]);
<AgGridReact
calculatedColumns={calculatedColumns}
columnDefs={columnDefs}
/>Calculated columns declared in columnDefs must define a colId explicitly.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
CalculatedColumnsGridOption,
ClientSideRowModelModule,
ColDef,
ColGroupDef,
DataTypeDefinitions,
GridOptions,
ModuleRegistry,
NumberEditorModule,
NumberFilterModule,
ValueFormatterLiteParams,
enableDevValidations,
} from "ag-grid-community";
import { CalculatedColumnsModule, ColumnMenuModule } from "ag-grid-enterprise";
import { SalesRow } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [
ClientSideRowModelModule,
CalculatedColumnsModule,
ColumnMenuModule,
NumberEditorModule,
NumberFilterModule,
];
const currencyFormatter = (
params: ValueFormatterLiteParams<SalesRow, number>,
): string => {
const { value } = params;
if (value == null) {
return "";
}
if (String(value).startsWith("#")) {
return String(value);
}
return `$${value.toLocaleString()}`;
};
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [rowData, setRowData] = useState<SalesRow[]>([
{ product: "Solar panel kit", revenue: 142000, cost: 96000 },
{ product: "Smart thermostat", revenue: 78000, cost: 52000 },
{ product: "Battery pack", revenue: 126000, cost: 101000 },
{ product: "EV charger", revenue: 92000, cost: 61000 },
{ product: "Heat pump", revenue: 168000, cost: 119000 },
{ product: "Inverter unit", revenue: 88000, cost: 57000 },
{ product: "Wind turbine kit", revenue: 232000, cost: 171000 },
{ product: "Solar tile roof", revenue: 198000, cost: 144000 },
{ product: "Power optimiser", revenue: 64000, cost: 41000 },
{ product: "Charge controller", revenue: 53000, cost: 33000 },
{ product: "Energy monitor", revenue: 47000, cost: 29000 },
{ product: "Storage cabinet", revenue: 71000, cost: 52000 },
{ product: "Microinverter", revenue: 59000, cost: 37000 },
{ product: "Heat recovery unit", revenue: 124000, cost: 88000 },
{ product: "Hybrid boiler", revenue: 156000, cost: 117000 },
{ product: "Smart meter", revenue: 39000, cost: 24000 },
{ product: "Insulation pack", revenue: 44000, cost: 27000 },
{ product: "EV cable set", revenue: 31000, cost: 18000 },
{ product: "Solar pump", revenue: 67000, cost: 45000 },
{ product: "Backup generator", revenue: 173000, cost: 131000 },
]);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "product", flex: 1 },
{
field: "revenue",
editable: true,
cellDataType: "currency",
},
{
field: "cost",
editable: true,
cellDataType: "currency",
},
{
colId: "profit",
headerName: "Profit",
calculatedExpression: "[revenue] - [cost]",
cellDataType: "currency",
sortable: true,
filter: "agNumberColumnFilter",
},
]);
const dataTypeDefinitions = useMemo<DataTypeDefinitions>(() => {
return {
currency: {
baseDataType: "number",
extendsDataType: "number",
valueFormatter: currencyFormatter,
},
};
}, []);
const calculatedColumns = useMemo<CalculatedColumnsGridOption>(() => {
return {
dataTypes: ["currency", "number", "text", "boolean"],
};
}, []);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 130,
};
}, []);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={{ height: "100%", boxSizing: "border-box" }}>
<div style={gridStyle}>
<AgGridReact<SalesRow>
rowData={rowData}
columnDefs={columnDefs}
dataTypeDefinitions={dataTypeDefinitions}
calculatedColumns={calculatedColumns}
defaultColDef={defaultColDef}
/>
</div>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
In the example, Profit is a calculated column. To create your own, choose Add Calculated Column from any column's header menu.
Writing Expressions Copy Link
In calculatedExpression, a reference in square brackets, such as [revenue], resolves to the same-row value from the column with that colId. The value inside the brackets must match a column colId, which defaults to the field when no explicit colId is provided. Calculated expressions do not need a leading equals sign (=).
Calculated columns can use the same Mathematical Operators, Provided Functions and Custom Functions as formulas.
Chaining Calculated Columns Copy Link
Calculated columns can reference other calculated columns in the same row, which lets you chain derived values such as profit, margin and status:
const calculatedColumns = true;
const [columnDefs, setColumnDefs] = useState([
{ field: 'revenue' },
{ field: 'cost' },
{
colId: 'profit',
calculatedExpression: '[revenue] - [cost]',
cellDataType: 'currency',
},
{
colId: 'margin',
calculatedExpression: '[profit] / [revenue]',
cellDataType: 'percentage',
},
{
colId: 'status',
calculatedExpression: 'IF([margin] >= 0.25, "Healthy", "Review")',
cellDataType: 'text',
},
]);
<AgGridReact
calculatedColumns={calculatedColumns}
columnDefs={columnDefs}
/>The currency and percentage types are registered with dataTypeDefinitions, as shown in Data Types.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
CalculatedColumnsGridOption,
ClientSideRowModelModule,
ColDef,
ColGroupDef,
DataTypeDefinitions,
GridOptions,
ModuleRegistry,
NumberFilterModule,
TextFilterModule,
ValueFormatterLiteParams,
enableDevValidations,
} from "ag-grid-community";
import { CalculatedColumnsModule, ColumnMenuModule } from "ag-grid-enterprise";
import { SalesRow } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [
ClientSideRowModelModule,
CalculatedColumnsModule,
ColumnMenuModule,
NumberFilterModule,
TextFilterModule,
];
const formatter = (
params: ValueFormatterLiteParams<SalesRow, number>,
format: (value: number) => string,
): string => {
const { value } = params;
if (value == null) {
return "";
}
if (String(value).startsWith("#")) {
return String(value);
}
return format(value);
};
const currencyFormatter = (
params: ValueFormatterLiteParams<SalesRow, number>,
) => formatter(params, (value) => `$${value.toLocaleString()}`);
const percentageFormatter = (
params: ValueFormatterLiteParams<SalesRow, number>,
) => formatter(params, (value) => `${Math.round(value * 100)}%`);
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [rowData, setRowData] = useState<SalesRow[]>([
{ account: "Northwind Energy", revenue: 245000, cost: 172000 },
{ account: "Summit Retail", revenue: 186000, cost: 151000 },
{ account: "Pioneer Logistics", revenue: 214000, cost: 139000 },
{ account: "Apex Manufacturing", revenue: 198000, cost: 158000 },
{ account: "Blue River Telecom", revenue: 276000, cost: 192000 },
{ account: "Crestline Foods", revenue: 167000, cost: 121000 },
{ account: "Harbor Freight Co", revenue: 142000, cost: 99000 },
{ account: "Atlas Mining", revenue: 251000, cost: 197000 },
{ account: "Veridian Health", revenue: 173000, cost: 128000 },
{ account: "Quantum Software", revenue: 298000, cost: 176000 },
{ account: "Redwood Hotels", revenue: 132000, cost: 104000 },
{ account: "Ironbridge Steel", revenue: 221000, cost: 183000 },
{ account: "Lakeside Media", revenue: 96000, cost: 71000 },
{ account: "Polar Shipping", revenue: 188000, cost: 142000 },
{ account: "Granite Insurance", revenue: 204000, cost: 149000 },
{ account: "Cobalt Mining", revenue: 243000, cost: 186000 },
{ account: "Meridian Airlines", revenue: 312000, cost: 268000 },
{ account: "Oakfield Farms", revenue: 87000, cost: 62000 },
{ account: "Silverline Bank", revenue: 265000, cost: 191000 },
{ account: "Horizon Telecom", revenue: 154000, cost: 112000 },
]);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "account", flex: 1.4 },
{
field: "revenue",
cellDataType: "currency",
},
{
field: "cost",
cellDataType: "currency",
},
{
colId: "profit",
headerName: "Profit",
calculatedExpression: "[revenue] - [cost]",
cellDataType: "currency",
sortable: true,
filter: "agNumberColumnFilter",
},
{
colId: "margin",
headerName: "Margin",
calculatedExpression: "[profit] / [revenue]",
cellDataType: "percentage",
sortable: true,
filter: "agNumberColumnFilter",
},
{
colId: "status",
headerName: "Status",
calculatedExpression: 'IF([margin] >= 0.25, "Healthy", "Review")',
cellDataType: "text",
sortable: true,
filter: "agTextColumnFilter",
},
]);
const dataTypeDefinitions = useMemo<DataTypeDefinitions>(() => {
return {
currency: {
baseDataType: "number",
extendsDataType: "number",
valueFormatter: currencyFormatter,
},
percentage: {
baseDataType: "number",
extendsDataType: "number",
valueFormatter: percentageFormatter,
},
};
}, []);
const calculatedColumns = useMemo<CalculatedColumnsGridOption>(() => {
return {
dataTypes: ["currency", "percentage", "number", "text", "boolean"],
};
}, []);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 130,
};
}, []);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={{ height: "100%", boxSizing: "border-box" }}>
<div style={gridStyle}>
<AgGridReact<SalesRow>
rowData={rowData}
columnDefs={columnDefs}
dataTypeDefinitions={dataTypeDefinitions}
calculatedColumns={calculatedColumns}
defaultColDef={defaultColDef}
/>
</div>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
Letting Users Add Columns Copy Link
Register the Column Menu so users can add, edit and remove calculated columns from the grid:
- Add Calculated Column, in the header menu of any column, opens the dialog to add a calculated column. It is not shown in pivot mode.
- Edit Calculated Column, in the header menu of a calculated column, opens the dialog to change its title, type and expression. A read-only column shows View Calculated Column instead.
- Remove Calculated Column, in the header menu of a calculated column and the context menu of its cells, removes the column. It is disabled when the column is read-only.
When adding a calculated column from a header menu or via the API with a source column, the new column uses the source column's current pinning. The new column appears next to the source: on the right in LTR and on the left in RTL.
In the dialog, users refer to columns by title instead of colId, for example [Revenue]. See Referencing Columns for how the dialog handles duplicate titles. Custom functions registered through formulaFuncs appear in the dialog's Functions picker and in autocomplete.
Register Cell Data Types to give users formatting options to pick from when they create a column. The first example on this page provides a currency type; see Data Types.
Calculated cell values cannot be changed through cell editing, paste, fill handle or delete operations. Users can still change a calculated column's title, type and expression through its dialog. To prevent these dialog edits and removal through the grid's menus, see Read-Only Calculated Columns.
Feature Interactions Copy Link
Calculated Columns are supported with all row models. Calculated columns are full columns, so Row Grouping, Tree Data, Pivoting, Sorting, Filtering, Text Formatting and Cell Components apply to them the same way as any other column.
For Server-Side, Infinite and Viewport Row Models, sorting and filtering are datasource or server responsibilities. The grid displays calculated values for loaded rows, but does not client-sort or client-filter remote datasets by calculated results.
Row Groups and Tree Data Copy Link
A calculated column evaluates on leaf rows and on Tree Data parents that carry data. It stays blank on rows without data: row group rows, group footers, the grand total row and Tree Data filler nodes.
To show a value on group rows, give the calculated column an aggFunc. Each leaf evaluates the expression, and the group aggregates those per-leaf results with the chosen function, the same as a column with a valueGetter. For example, { calculatedExpression: '[revenue] - [cost]', aggFunc: 'sum' } shows the total of its rows' profits on a group. A ratio has no meaningful aggregation, so a column like [profit] / [revenue] is left without an aggFunc and stays blank on group rows.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
AutoGroupColumnDef,
CalculatedColumnsGridOption,
ClientSideRowModelModule,
ColDef,
ColGroupDef,
DataTypeDefinitions,
GridOptions,
ModuleRegistry,
NumberFilterModule,
ValueFormatterLiteParams,
enableDevValidations,
} from "ag-grid-community";
import {
CalculatedColumnsModule,
ColumnMenuModule,
RowGroupingModule,
} from "ag-grid-enterprise";
import { SalesRow } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [
ClientSideRowModelModule,
CalculatedColumnsModule,
ColumnMenuModule,
RowGroupingModule,
NumberFilterModule,
];
const formatter = (
params: ValueFormatterLiteParams<SalesRow, number>,
format: (value: number) => string,
): string => {
const { value } = params;
if (value == null) {
return "";
}
if (String(value).startsWith("#")) {
return String(value);
}
return format(value);
};
const currencyFormatter = (
params: ValueFormatterLiteParams<SalesRow, number>,
) => formatter(params, (value) => `$${value.toLocaleString()}`);
const percentageFormatter = (
params: ValueFormatterLiteParams<SalesRow, number>,
) => formatter(params, (value) => `${Math.round(value * 100)}%`);
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [rowData, setRowData] = useState<SalesRow[]>([
{
productType: "Solar",
product: "Solar panel kit",
revenue: 142000,
cost: 96000,
},
{
productType: "Solar",
product: "Smart thermostat",
revenue: 78000,
cost: 52000,
},
{
productType: "Charging",
product: "Battery pack",
revenue: 126000,
cost: 101000,
},
{
productType: "Charging",
product: "EV charger",
revenue: 92000,
cost: 61000,
},
{
productType: "Heating",
product: "Heat pump",
revenue: 168000,
cost: 119000,
},
{
productType: "Heating",
product: "Hybrid boiler",
revenue: 156000,
cost: 117000,
},
{
productType: "Heating",
product: "Heat recovery unit",
revenue: 124000,
cost: 88000,
},
{
productType: "Storage",
product: "Storage cabinet",
revenue: 71000,
cost: 52000,
},
{
productType: "Storage",
product: "Lithium rack",
revenue: 143000,
cost: 112000,
},
{
productType: "Storage",
product: "Flow battery",
revenue: 187000,
cost: 149000,
},
{
productType: "Storage",
product: "Backup generator",
revenue: 173000,
cost: 131000,
},
{
productType: "Wind",
product: "Wind turbine kit",
revenue: 232000,
cost: 171000,
},
{
productType: "Wind",
product: "Micro turbine",
revenue: 76000,
cost: 49000,
},
{
productType: "Wind",
product: "Tower mount",
revenue: 41000,
cost: 26000,
},
{
productType: "Monitoring",
product: "Energy monitor",
revenue: 47000,
cost: 29000,
},
{
productType: "Monitoring",
product: "Smart meter",
revenue: 39000,
cost: 24000,
},
{
productType: "Monitoring",
product: "Grid analyser",
revenue: 58000,
cost: 36000,
},
{
productType: "Efficiency",
product: "Insulation pack",
revenue: 44000,
cost: 27000,
},
{
productType: "Efficiency",
product: "LED retrofit",
revenue: 36000,
cost: 21000,
},
{
productType: "Efficiency",
product: "Window film",
revenue: 28000,
cost: 16000,
},
]);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "productType", rowGroup: true, hide: true },
{ field: "product", flex: 1.4 },
{
field: "revenue",
aggFunc: "sum",
cellDataType: "currency",
},
{
field: "cost",
aggFunc: "sum",
cellDataType: "currency",
},
{
colId: "profit",
headerName: "Profit",
calculatedExpression: "[revenue] - [cost]",
// aggFunc lets the calculated column aggregate its per-leaf results onto group rows.
aggFunc: "sum",
cellDataType: "currency",
filter: "agNumberColumnFilter",
},
{
colId: "margin",
headerName: "Margin",
// No aggFunc: a ratio does not aggregate, so margin evaluates on leaf rows and is blank on groups.
calculatedExpression: "[profit] / [revenue]",
cellDataType: "percentage",
},
]);
const dataTypeDefinitions = useMemo<DataTypeDefinitions>(() => {
return {
currency: {
baseDataType: "number",
extendsDataType: "number",
valueFormatter: currencyFormatter,
},
percentage: {
baseDataType: "number",
extendsDataType: "number",
valueFormatter: percentageFormatter,
},
};
}, []);
const calculatedColumns = useMemo<CalculatedColumnsGridOption>(() => {
return {
dataTypes: ["currency", "percentage", "number", "text", "boolean"],
};
}, []);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 130,
};
}, []);
const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
return {
headerName: "Product Type",
minWidth: 180,
};
}, []);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={{ height: "100%", boxSizing: "border-box" }}>
<div style={gridStyle}>
<AgGridReact<SalesRow>
rowData={rowData}
columnDefs={columnDefs}
dataTypeDefinitions={dataTypeDefinitions}
calculatedColumns={calculatedColumns}
defaultColDef={defaultColDef}
autoGroupColumnDef={autoGroupColumnDef}
groupDefaultExpanded={-1}
/>
</div>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
In the example, Profit has an aggFunc and shows a total on each group row, while Margin stays blank there.
Letting Users Choose an Aggregation Copy Link
The dialog has no aggregation field. Setting enableValue, for example in defaultColDef, lets users choose an aggregation for any calculated column, including one created in the dialog. To allow it only on the columns users create, return enableValue from processColDef instead.
Users choose the aggregation from Value Aggregation in the column menu while rows are grouped, or by adding the column to the Values section of the Columns Tool Panel. To limit the choice, set allowedAggFuncs as in the example below. Configuring via the UI covers this and defaultAggFunc.
const calculatedColumns = true;
const defaultColDef = useMemo(() => {
return {
enableValue: true,
allowedAggFuncs: ['sum', 'avg', 'min', 'max'],
};
}, []);
const sideBar = 'columns';
<AgGridReact
calculatedColumns={calculatedColumns}
defaultColDef={defaultColDef}
sideBar={sideBar}
/>"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
AutoGroupColumnDef,
CalculatedColumnsGridOption,
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridOptions,
ModuleRegistry,
SideBarDef,
enableDevValidations,
} from "ag-grid-community";
import {
CalculatedColumnsModule,
ColumnMenuModule,
ColumnsToolPanelModule,
RowGroupingModule,
} from "ag-grid-enterprise";
import { SalesRow } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [
ClientSideRowModelModule,
CalculatedColumnsModule,
ColumnMenuModule,
ColumnsToolPanelModule,
RowGroupingModule,
];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [rowData, setRowData] = useState<SalesRow[]>([
{
productType: "Solar",
product: "Solar panel kit",
revenue: 142000,
cost: 96000,
},
{
productType: "Solar",
product: "Smart thermostat",
revenue: 78000,
cost: 52000,
},
{
productType: "Charging",
product: "Battery pack",
revenue: 126000,
cost: 101000,
},
{
productType: "Charging",
product: "EV charger",
revenue: 92000,
cost: 61000,
},
{
productType: "Heating",
product: "Heat pump",
revenue: 168000,
cost: 119000,
},
{
productType: "Heating",
product: "Hybrid boiler",
revenue: 156000,
cost: 117000,
},
{
productType: "Heating",
product: "Heat recovery unit",
revenue: 124000,
cost: 88000,
},
{
productType: "Storage",
product: "Storage cabinet",
revenue: 71000,
cost: 52000,
},
{
productType: "Storage",
product: "Lithium rack",
revenue: 143000,
cost: 112000,
},
{
productType: "Storage",
product: "Flow battery",
revenue: 187000,
cost: 149000,
},
{
productType: "Wind",
product: "Wind turbine kit",
revenue: 232000,
cost: 171000,
},
{
productType: "Wind",
product: "Micro turbine",
revenue: 76000,
cost: 49000,
},
]);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "productType", rowGroup: true, hide: true },
{ field: "product", flex: 1.4 },
{ field: "revenue", aggFunc: "sum" },
{ field: "cost", aggFunc: "sum" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 130,
// Lets users choose an aggregation for every column, including calculated columns created in the dialog.
enableValue: true,
allowedAggFuncs: ["sum", "avg", "min", "max"],
};
}, []);
const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
return {
headerName: "Product Type",
minWidth: 180,
};
}, []);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={{ height: "100%", boxSizing: "border-box" }}>
<div style={gridStyle}>
<AgGridReact<SalesRow>
rowData={rowData}
columnDefs={columnDefs}
calculatedColumns={true}
defaultColDef={defaultColDef}
autoGroupColumnDef={autoGroupColumnDef}
sideBar={"columns"}
groupDefaultExpanded={-1}
/>
</div>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
In the example, choose Add Calculated Column from the Cost header menu and enter [Revenue] - [Cost] as the expression. Close the dialog, then open Value Aggregation in the new column's header menu. It offers only None, Sum, Average, Min and Max.
Pivoting Copy Link
Under Pivoting, a calculated column behaves the same as a column with a valueGetter:
- With an
aggFunc, it is a value column. It evaluates per leaf, and its results aggregate into the pivot result columns. - Without an
aggFunc, it is not a value column, so it has no pivot result column and is absent from the cross-tab, like any other non-value column. - As a pivot column (
pivot: true), its per-row result becomes the pivot key, so the grid creates a result column for each distinct calculated value.
Users cannot add calculated columns while pivot mode is on.
Styling Copy Link
Header cells and grid cells for calculated columns include the ag-calculated-column CSS class; use it for custom styling. To change the highlight shown while a column's dialog is open, see Column Highlighting.
Next Steps Copy Link
- Dialog & Customisation: opening the dialog, column references, the expression editor, data types, when edits apply, and customising the columns users create.
- Restrictions & Validation: read-only columns, hidden menu items, restricted column references, custom validation and refreshing.
- API, Events & State: managing calculated columns in code, saving and restoring them, events, and the API reference.