# Formatting Presets
URL: https://pro.rv-grid.com/guides/pivot/concepts/formatting-presets/
Source: src/content/docs/guides/pivot/concepts/formatting-presets.mdx
Description: Format Pivot values with locale-aware number, currency, percent, and date presets, then highlight analytical cells with conditional formatting.
Formatting presets help Pivot reports show numbers, money, percentages, and dates in a readable way. Conditional formatting presets then help users spot high revenue, low margin, or other important analytical values.

## Basic Setup

Import the helpers from Enterprise and create reusable formatters for the value types in your report:

```ts
import {
  createPivotValueFormatter,
  formatPivotValue,
  pivotConditionalFormattingPresets,
  createPivotConditionalCellProperties,
  PivotPlugin,
  type PivotConfig,
} from '@revolist/revogrid-enterprise';

const revenueFormatter = createPivotValueFormatter({
  preset: 'currency',
  currency: 'USD',
  locale: 'en-US',
  options: { maximumFractionDigits: 0 },
});

const marginFormatter = createPivotValueFormatter({
  preset: 'percent',
  locale: 'en-US',
  options: { minimumFractionDigits: 1, maximumFractionDigits: 1 },
});
```

`createPivotValueFormatter()` returns a function. Use it when the same formatting rule is reused by many cells. Use `formatPivotValue()` when you only need to format one value:

```ts
const formattedLabel = formatPivotValue(null, {
  preset: 'date',
  nullDisplay: 'No close date',
});
```

## Value Formatters

Pivot formatters are display helpers. They do not change the original source data or the aggregated number that Pivot calculates. Keep your source values as real numbers and dates, then format them at render time.

```ts
const columnTypes = {
  pivotCurrency: {
    cellTemplate: (_h, props) => revenueFormatter(props.value),
    cellProperties: () => ({ class: { 'align-right': true } }),
  },
  pivotPercent: {
    cellTemplate: (_h, props) => marginFormatter(props.value),
    cellProperties: () => ({ class: { 'align-right': true } }),
  },
};
```

Attach those column types to the Pivot dimensions that produce analytical value cells:

```ts
const pivot: PivotConfig = {
  dimensions: [
    { prop: 'region', name: 'Region' },
    { prop: 'closeDate', name: 'Close date', columnType: 'pivotDate' },
    { prop: 'segment', name: 'Segment' },
    { prop: 'revenue', name: 'Revenue', columnType: 'pivotCurrency' },
    { prop: 'marginRate', name: 'Margin', columnType: 'pivotPercent' },
  ],
  rows: ['region', 'closeDate'],
  columns: ['segment'],
  values: [
    { prop: 'revenue', aggregator: 'sum', label: 'Revenue' },
    { prop: 'marginRate', aggregator: 'avg', label: 'Avg margin' },
  ],
};
```

## Locale And Presets

The formatter presets use the browser `Intl` formatters. Choose the preset that matches the value:

- `number`: plain numeric values such as counts, units, or scores.
- `currency`: money values. Always provide `currency`, for example `"USD"` or `"EUR"`.
- `percent`: ratio values such as `0.315`, displayed as `31.5%`.
- `date`: date-only values.
- `datetime`: date and time values.

```ts
const integerFormatter = createPivotValueFormatter({
  preset: 'number',
  locale: 'en-US',
  options: { maximumFractionDigits: 0 },
});

const eurFormatter = createPivotValueFormatter({
  preset: 'currency',
  currency: 'EUR',
  locale: 'de-DE',
});

const dateFormatter = createPivotValueFormatter({
  preset: 'date',
  locale: 'en-US',
  options: { month: 'short', day: '2-digit', year: 'numeric' },
});
```

## Conditional Formatting Presets

Use `pivotConditionalFormattingPresets` to describe matching rules, and `createPivotConditionalCellProperties()` to turn those rules into a RevoGrid `cellProperties` function.

```ts
const conditionalCellProperties = createPivotConditionalCellProperties(
  [
    pivotConditionalFormattingPresets.gt(300000, {
      field: 'revenue',
      style: {
        backgroundColor: 'rgba(22, 163, 74, 0.16)',
        color: '#166534',
        fontWeight: '600',
      },
    }),
    pivotConditionalFormattingPresets.lt(0.28, {
      field: 'marginRate',
      style: {
        backgroundColor: 'rgba(220, 38, 38, 0.14)',
        color: '#991b1b',
        fontWeight: '600',
      },
    }),
    pivotConditionalFormattingPresets.between(0.28, 0.34, {
      field: 'marginRate',
      style: {
        backgroundColor: 'rgba(234, 179, 8, 0.14)',
        color: '#854d0e',
      },
    }),
  ],
  { match: 'all' },
);
```

Available presets:

- `gt(value, props)`: greater than a number.
- `lt(value, props)`: less than a number.
- `between(min, max, props)`: between two numbers, including both bounds.
- `equal(value, props)`: equal to a value.
- `textContains(value, props)`: contains text.

The optional `field` narrows a rule to a generated value field. For example, `field: 'revenue'` applies to generated revenue cells even when Pivot creates column paths such as `Software|revenue`.

## Analytical Cells

By default, `createPivotConditionalCellProperties()` only formats Pivot analytical cells. These are generated cells from the `values` area, not row header fields such as `region` or `closeDate`.

This default prevents a rule like `gt(300000)` from accidentally styling row dimensions that happen to contain comparable values. If you intentionally want rules to apply outside analytical value cells, enable `includeNonAnalytical`:

```ts
const allCellProperties = createPivotConditionalCellProperties(rules, {
  includeNonAnalytical: true,
});
```

Most Pivot reports should keep the default and attach conditional formatting to value dimensions:

```ts
const pivot: PivotConfig = {
  dimensions: [
    { prop: 'region', name: 'Region' },
    {
      prop: 'revenue',
      name: 'Revenue',
      columnType: 'pivotCurrency',
      cellProperties: conditionalCellProperties,
    },
    {
      prop: 'marginRate',
      name: 'Margin',
      columnType: 'pivotPercent',
      cellProperties: conditionalCellProperties,
    },
  ],
  rows: ['region'],
  columns: ['segment'],
  values: [
    { prop: 'revenue', aggregator: 'sum' },
    { prop: 'marginRate', aggregator: 'avg' },
  ],
};
```

## Practical Example

This report groups opportunities by region and close date, splits generated value columns by segment, formats revenue as currency, formats margin as a percent, and highlights high revenue or weak margin.

```ts
const rows = [
  { region: 'North America', closeDate: '2026-01-16', segment: 'Software', revenue: 184000, marginRate: 0.37 },
  { region: 'North America', closeDate: '2026-01-22', segment: 'Services', revenue: 126000, marginRate: 0.31 },
  { region: 'EMEA', closeDate: '2026-02-06', segment: 'Services', revenue: 118000, marginRate: 0.28 },
];

const pivot: PivotConfig = {
  dimensions: [
    { prop: 'region', name: 'Region' },
    { prop: 'closeDate', name: 'Close date', columnType: 'pivotDate' },
    {
      prop: 'revenue',
      name: 'Revenue',
      columnType: 'pivotCurrency',
      cellProperties: conditionalCellProperties,
    },
    {
      prop: 'marginRate',
      name: 'Margin',
      columnType: 'pivotPercent',
      cellProperties: conditionalCellProperties,
    },
  ],
  rows: ['region', 'closeDate'],
  columns: ['segment'],
  values: [
    { prop: 'revenue', aggregator: 'sum', label: 'Revenue' },
    { prop: 'marginRate', aggregator: 'avg', label: 'Avg margin' },
  ],
  totals: {
    subtotals: true,
    grandTotal: true,
  },
  groupLabels: {
    null: formatPivotValue(null, { preset: 'date', nullDisplay: 'No close date' }),
  },
};

const grid = document.querySelector('revo-grid');
grid.columnTypes = columnTypes;
grid.plugins = [PivotPlugin];
grid.pivot = pivot;
grid.source = rows;
```

## Common Mistakes

- Formatting the source data before Pivot aggregates it. Keep values numeric so `sum`, `avg`, and comparisons work correctly.
- Using `preset: 'percent'` with whole percentages. `31.5%` should usually be stored as `0.315`, not `31.5`.
- Forgetting `currency` when using the `currency` preset.
- Expecting conditional formatting to affect row fields by default. It targets analytical value cells unless `includeNonAnalytical` is enabled.
- Omitting `field` on a conditional rule when the report has several value fields. Without `field`, the rule can match every analytical value cell.
- Expecting `cellTemplate` formatting to change conditional comparisons. Conditional rules evaluate the raw cell value, not the formatted display string.

## Next

Continue with [Sorting And Filtering](../sorting-filtering/) or [Configuration Reference](/guides/pivot/configuration-reference/).
