---
title: "Excel Export - Customising Content"
enterprise: true
framework: vue
version: "36.1.0"
---

# Excel Export - Customising Content

## Customising Cell and Row Group values

By default, the values exported to Excel will be formatted via the [Using the Value Formatter for Export](https://www.ag-grid.com/vue-data-grid/value-formatters/#formatting-for-export) feature.

The grid cell and row group values can be customised specifically for Excel export using the following function params for a call to `exportDataAsExcel` API method or in the `defaultExcelExportParams`.

```ts
gridApi.exportDataAsExcel({
    processCellCallback(params) {
        const value = params.value
        return value === undefined ? '' : `_${value}_`
    },
    processRowGroupCallback(params) {
        return `row group: ${params.node.key}`
    }
})
```

See below the functions on the `ExcelExportParams` interface to customise exported grid cell and row group values.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `processCellCallback` | `Function` |  |  | A callback function invoked once per cell in the grid. Return a string value to be displayed in the export. For example this is useful for formatting date values. |
| `processRowGroupCallback` | `Function` |  |  | A callback function invoked once per row group. Return a `string` to be displayed in the group cell. |

The following example shows Excel customisations where the exported document has the following:

- All row groups with the prefix `row group: `
- All cell values surrounded by `_`, unless they are `undefined`, in which case they are empty

> **Note**
>
> When using row grouping while [hiding open parents](https://www.ag-grid.com/vue-data-grid/grouping-multiple-group-columns/#hiding-expanded-parent-rows) (`groupHideOpenParents=true`), export to Excel doesn't export the group rows as collapsible groups in Excel. Instead, all exported rows are on the same level and cannot be expanded/collapsed in Excel.

#### Excel Export - Customising Row Groups

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  CsvExportModule,
  ExcelExportParams,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberFilterModule,
  ProcessCellForExportParams,
  ProcessRowGroupForExportParams,
  UseGroupTotalRow,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  ExcelExportModule,
  RowGroupingModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  NumberFilterModule,
  ClientSideRowModelModule,
  CsvExportModule,
  ExcelExportModule,
  ColumnMenuModule,
  ContextMenuModule,
  RowGroupingModule,
  SetFilterModule,
]);

const getParams: () => ExcelExportParams = () => ({
  processCellCallback(params: ProcessCellForExportParams): string {
    const value = params.value;
    return value === undefined ? "" : `_${value}_`;
  },
  processRowGroupCallback(params: ProcessRowGroupForExportParams): string {
    const { node } = params;
    if (!node.footer) {
      return `row group: ${node.key}`;
    }
    const isRootLevel = node.level === -1;
    if (isRootLevel) {
      return "Grand Total";
    }
    return `Sub Total (${node.key})`;
  },
});

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="container">
      <div>
        <button v-on:click="onBtExport()" style="margin: 5px 0px; font-weight: bold">Export to Excel</button>
      </div>
      <div class="grid-wrapper">
        <ag-grid-vue
          style="width: 100%; height: 100%;"
          @grid-ready="onGridReady"
          :columnDefs="columnDefs"
          :defaultColDef="defaultColDef"
          :groupTotalRow="groupTotalRow"
          :grandTotalRow="grandTotalRow"
          :popupParent="popupParent"
          :defaultExcelExportParams="defaultExcelExportParams"
          :rowData="rowData"></ag-grid-vue>
        </div>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", minWidth: 200 },
      { field: "country", minWidth: 200, rowGroup: true, hide: true },
      { field: "sport", minWidth: 150 },
      { field: "gold", aggFunc: "sum" },
    ]);
    const defaultColDef = ref<ColDef>({
      filter: true,
      minWidth: 150,
      flex: 1,
    });
    const groupTotalRow = ref<"top" | "bottom" | UseGroupTotalRow>("bottom");
    const grandTotalRow = ref<"top" | "bottom" | "pinnedTop" | "pinnedBottom">(
      "bottom",
    );
    const popupParent = ref<HTMLElement | null>(document.body);
    const defaultExcelExportParams = ref<ExcelExportParams>(getParams());
    const rowData = ref<IOlympicData[]>(null);

    function onBtExport() {
      gridApi.value!.exportDataAsExcel(getParams());
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) =>
        (rowData.value = data.filter((rec: any) => rec.country != null));

      fetch("https://www.ag-grid.com/example-assets/small-olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      groupTotalRow,
      grandTotalRow,
      popupParent,
      defaultExcelExportParams,
      rowData,
      onGridReady,
      onBtExport,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Excel Export - Customising Row Groups](https://www.ag-grid.com/examples/excel-export-customising-content/excel-export-customising-row-groups/vue3)

## Customising Column Headers and Group Header Values

The column headers and group headers exported to Excel can be customised using the following function params for a call to `exportDataAsExcel` API method or in the `defaultExcelExportParams`.

```ts
gridApi.exportDataAsExcel({
    processGroupHeaderCallback(params) {
        return `group header: ${params.this.gridApi.getDisplayNameForColumnGroup(params.columnGroup, null)}`
    },
    processHeaderCallback(params) {
        return `header: ${params.api.getDisplayNameForColumn(params.column, null)}`
    }
});
```

See below the functions on the `ExcelExportParams` interface to customise exported column group headers and headers.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `processHeaderCallback` | `Function` |  |  | A callback function invoked once per column. Return a string to be displayed in the column header. |
| `processGroupHeaderCallback` | `Function` |  |  | A callback function invoked once per column group. Return a `string` to be displayed in the column group header. Note that column groups are exported by default, this option will not work with `skipColumnGroupHeaders=true`. |

The following example shows Excel customisations where the exported document has the following:

- Group headers with the prefix `group header: `
- Headers with the prefix `header: `

#### Excel Export - Customising Column Group Headers

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  ColumnApiModule,
  CsvExportModule,
  ExcelExportParams,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberFilterModule,
  ProcessGroupHeaderForExportParams,
  ProcessHeaderForExportParams,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  ExcelExportModule,
  RowGroupingModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ColumnApiModule,
  NumberFilterModule,
  ClientSideRowModelModule,
  CsvExportModule,
  ExcelExportModule,
  ColumnMenuModule,
  ContextMenuModule,
  RowGroupingModule,
  SetFilterModule,
]);

const getParams: () => ExcelExportParams = () => ({
  processHeaderCallback(params: ProcessHeaderForExportParams): string {
    return `header: ${params.api.getDisplayNameForColumn(params.column, null)}`;
  },
  processGroupHeaderCallback(
    params: ProcessGroupHeaderForExportParams,
  ): string {
    return `group header: ${params.api.getDisplayNameForColumnGroup(params.columnGroup, null)}`;
  },
});

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="container">
      <div>
        <button v-on:click="onBtExport()" style="margin: 5px 0px; font-weight: bold">Export to Excel</button>
      </div>
      <div class="grid-wrapper">
        <ag-grid-vue
          style="width: 100%; height: 100%;"
          @grid-ready="onGridReady"
          :columnDefs="columnDefs"
          :defaultColDef="defaultColDef"
          :popupParent="popupParent"
          :rowData="rowData"></ag-grid-vue>
        </div>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<(ColDef | ColGroupDef)[]>([
      {
        headerName: "Athlete details",
        children: [
          { field: "athlete", minWidth: 200 },
          { field: "country", minWidth: 150 },
          { field: "sport", minWidth: 150 },
        ],
      },
      {
        headerName: "Medal results",
        children: [{ field: "gold" }, { field: "silver" }, { field: "bronze" }],
      },
    ]);
    const defaultColDef = ref<ColDef>({
      filter: true,
      minWidth: 100,
      flex: 1,
    });
    const popupParent = ref<HTMLElement | null>(document.body);
    const rowData = ref<IOlympicData[]>(null);

    function onBtExport() {
      gridApi.value!.exportDataAsExcel(getParams());
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) =>
        (rowData.value = data.filter((rec: any) => rec.country != null));

      fetch("https://www.ag-grid.com/example-assets/small-olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      popupParent,
      rowData,
      onGridReady,
      onBtExport,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Excel Export - Customising Column Group Headers](https://www.ag-grid.com/examples/excel-export-customising-content/excel-export-customising-column-group-headers/vue3)

## Custom Metadata

Use `customMetadata` to write custom document properties to the exported file. The values are added as metadata to the Excel file and serialised as strings.

This is useful for attaching internal identifiers, workflow hints, or metadata consumed by downstream systems.

Use cases for custom metadata may include:

- Internal workflow tagging (for example, adding `ExportID` or `GeneratedBy` for tracking in automation scripts).
- Integration with document management systems (for example, embedding `ContractType` or `ExpirationDate` for indexing in SharePoint or similar tools).
- Integration with third-party analytics tools (for example, passing `CampaignID` for BI dashboard automation).

```ts
gridApi.exportDataAsExcel({
    customMetadata: {
        ExportID: 'EXP-2026-001',
        ExpirationDate: '2025-01-01T12:00:00Z',
        Disclaimer: 'Preliminary data; subject to audit',
    },
});
```

Properties available on the `ExcelExportParams` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `customMetadata` | `ExcelCustomMetadata` |  |  | Custom metadata to write to `docProps/custom.xml` in the exported file. Values are serialised as strings. |

> **Note**
>
> The Grid does not interpret these values or apply labels; it only writes the custom properties provided in the `customMetadata` parameter. This feature does not replace or integrate with officially endorsed labelling systems, such as Microsoft Purview Sensitivity Labels, which require specific SDKs or APIs for enforcement, encryption, and compliance.

#### Excel Export - Custom Metadata

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  CsvExportModule,
  ExcelExportParams,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import { ExcelExportModule } from "ag-grid-enterprise";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  CsvExportModule,
  ExcelExportModule,
  NumberFilterModule,
  TextFilterModule,
]);

interface ReportRow {
  department: string;
  reportId: string;
  owner: string;
  cost: number;
}

const customMetadata = {
  ExportID: "EXP-2026-001",
  ExpirationDate: "2025-01-01T12:00:00Z",
  Disclaimer: "Preliminary data; subject to audit",
};

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="container">
      <div>
        <button v-on:click="onBtExport()" style="margin: 5px 0px; font-weight: bold">Export to Excel</button>
      </div>
      <div class="grid-wrapper">
        <ag-grid-vue
          style="width: 100%; height: 100%;"
          @grid-ready="onGridReady"
          :rowData="rowData"
          :columnDefs="columnDefs"
          :defaultColDef="defaultColDef"
          :defaultExcelExportParams="defaultExcelExportParams"></ag-grid-vue>
        </div>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<ReportRow> | null>(null);
    const rowData = ref<ReportRow[] | null>([
      {
        department: "Security",
        reportId: "RPT-001",
        owner: "Morgan",
        cost: 1200,
      },
      {
        department: "Finance",
        reportId: "RPT-014",
        owner: "Avery",
        cost: 5400,
      },
      {
        department: "Operations",
        reportId: "RPT-082",
        owner: "Jordan",
        cost: 3100,
      },
      { department: "Legal", reportId: "RPT-109", owner: "Taylor", cost: 2700 },
    ]);
    const columnDefs = ref<ColDef[]>([
      { field: "department", minWidth: 160 },
      { field: "reportId", minWidth: 140 },
      { field: "owner", minWidth: 140 },
      { field: "cost", filter: "agNumberColumnFilter", minWidth: 120 },
    ]);
    const defaultColDef = ref<ColDef>({
      filter: true,
      flex: 1,
      minWidth: 120,
    });
    const defaultExcelExportParams = ref<ExcelExportParams>({
      customMetadata: customMetadata,
    });

    function onBtExport() {
      gridApi.value!.exportDataAsExcel();
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;
    };

    return {
      gridApi,
      rowData,
      columnDefs,
      defaultColDef,
      defaultExcelExportParams,
      onGridReady,
      onBtExport,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Excel Export - Custom Metadata](https://www.ag-grid.com/examples/excel-export-customising-content/excel-export-customising-custom-metadata/vue3)
