---
product: "AG Grid"
title: "Excel Export - Extra Content"
description: "The recommended way to prepend and append content, is by passing an array of ExcelCell objects to prependContent or appendContent . This ensures that the extra content is correctly escaped."
enterprise: true
framework: javascript
version: "36.2.0"
related:
    - title: "Styles"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-styles/"
    - title: "Formulas"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-formulas/"
    - title: "Notes"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-notes/"
    - title: "Customising Content"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-customising-content/"
    - title: "Images"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-images/"
    - title: "Excel Tables"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-tables/"
    - title: "Multiple Sheets"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-multiple-sheets/"
    - title: "Rows"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-rows/"
    - title: "Columns"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-columns/"
    - title: "Freezing Content"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-freeze/"
    - title: "Data Types"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-data-types/"
    - title: "Hyperlinks"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-hyperlinks/"
    - title: "Master Detail"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-master-detail/"
    - title: "Page Setup"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-page-setup/"
    - title: "Data Protection"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-data-protection/"
    - title: "API Reference"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-api/"
llms: "https://www.ag-grid.com/archive/36.2.0/llms.txt"
---

# Excel Export - Extra Content

## Prepending and Appending Custom Content

The recommended way to prepend and append content, is by passing an array of ExcelCell objects to `prependContent` or `appendContent`. This ensures that the extra content is correctly escaped.

For compatibility with earlier versions of the Grid you can also pass a string, which will be inserted into the file without any processing. You are responsible for formatting the string correctly.

Note the following:

- You can check and uncheck the checkboxes to add extra content before and after the grid via the `prependContent` and `appendContent` properties.
- With `prependContent=ExcelRow[]` or `appendContent=ExcelRow[]`, custom content will be inserted containing commas and quotes. These commas and quotes will be visible when opened in Excel because they have been escaped properly.

#### Excel Export - Prepend and Append Content

```ts
import {
  ClientSideRowModelModule,
  ExcelExportParams,
  ExcelRow,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  ExcelExportModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableDevValidations();
}

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

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs: [
    { field: "athlete", minWidth: 200 },
    { field: "country", minWidth: 200 },
    { field: "sport", minWidth: 150 },
    { field: "gold" },
    { field: "silver" },
    { field: "bronze" },
    { field: "total" },
  ],

  defaultColDef: {
    filter: true,
    minWidth: 100,
    flex: 1,
  },

  popupParent: document.body,
};

const getRows: () => ExcelRow[] = () => [
  { cells: [] },
  {
    cells: [
      {
        data: {
          value: 'Here is a comma, and a some "quotes".',
          type: "String",
        },
      },
    ],
  },
  {
    cells: [
      {
        data: {
          value:
            "They are visible when the downloaded file is opened in Excel because custom content is properly escaped.",
          type: "String",
        },
      },
    ],
  },
  {
    cells: [
      { data: { value: "this cell:", type: "String" }, mergeAcross: 1 },
      {
        data: {
          value: "is empty because the first cell has mergeAcross=1",
          type: "String",
        },
      },
    ],
  },
  { cells: [] },
];

const getBoolean = (inputSelector: string) =>
  !!(document.querySelector(inputSelector) as HTMLInputElement).checked;

const getParams: () => ExcelExportParams = () => ({
  prependContent: getBoolean("#prependContent") ? getRows() : undefined,
  appendContent: getBoolean("#appendContent") ? getRows() : undefined,
});

function onBtExport() {
  gridApi!.exportDataAsExcel(getParams());
}

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/small-olympic-winners.json")
  .then((response) => response.json())
  .then((data) =>
    gridApi!.setGridOption(
      "rowData",
      data.filter((rec: any) => rec.country != null),
    ),
  );

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).onBtExport = onBtExport;
}
```

[Live example: Excel Export - Prepend and Append Content](https://www.ag-grid.com/archive/36.2.0/examples/excel-export-extra-content/excel-export-prepend-append/typescript/)

## Export Cover Page

In addition to exporting the Grid in the Excel file, you can also provide additional content on a separate sheet of the Excel file. This can be useful when you'd like to add a cover page to provide your users additional details on the data in this file.

#### Excel Export - Cover Page

```ts
import {
  ClientSideRowModelModule,
  CsvExportModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  ExcelExportModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableDevValidations();
}

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

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  defaultColDef: {
    filter: true,
    minWidth: 100,
    flex: 1,
  },

  columnDefs: [
    { field: "athlete", minWidth: 200 },
    { field: "country", minWidth: 200 },
    { field: "sport", minWidth: 150 },
    { field: "gold", hide: true },
    { field: "silver", hide: true },
    { field: "bronze", hide: true },
    { field: "total", hide: true },
  ],

  excelStyles: [
    {
      id: "coverHeading",
      font: {
        size: 26,
        bold: true,
      },
    },
    {
      id: "coverText",
      font: {
        size: 14,
      },
    },
  ],
};

function onBtExport() {
  const performExport = async () => {
    const spreadsheets = [];

    //set a filter condition ensuring no records are returned so only the header content is exported
    await gridApi!.setColumnFilterModel("athlete", {
      values: [],
    });

    gridApi!.onFilterChanged();

    //export custom content for cover page
    spreadsheets.push(
      gridApi!.getSheetDataForExcel({
        prependContent: [
          {
            cells: [
              {
                styleId: "coverHeading",
                mergeAcross: 3,
                data: { value: "AG Grid", type: "String" },
              },
            ],
          },
          {
            cells: [
              {
                styleId: "coverHeading",
                mergeAcross: 3,
                data: { value: "", type: "String" },
              },
            ],
          },
          {
            cells: [
              {
                styleId: "coverText",
                mergeAcross: 3,
                data: {
                  value:
                    "Data shown lists Olympic medal winners for years 2000-2012",
                  type: "String",
                },
              },
            ],
          },
          {
            cells: [
              {
                styleId: "coverText",
                data: {
                  value:
                    "This data includes a row for each participation record - athlete name, country, year, sport, count of gold, silver, bronze medals won during the sports event",
                  type: "String",
                },
              },
            ],
          },
        ],
        processHeaderCallback: () => "",
        sheetName: "cover",
      })!,
    );

    //remove filter condition set above so all the grid data can be exported on a separate sheet
    await gridApi.setColumnFilterModel("athlete", null);
    gridApi!.onFilterChanged();

    spreadsheets.push(gridApi!.getSheetDataForExcel()!);

    gridApi!.exportMultipleSheetsAsExcel({
      data: spreadsheets,
      fileName: "ag-grid.xlsx",
    });
  };
  performExport();
}

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/small-olympic-winners.json")
  .then((response) => response.json())
  .then((data) =>
    gridApi!.setGridOption(
      "rowData",
      data.filter((rec: any) => rec.country != null),
    ),
  );

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).onBtExport = onBtExport;
}
```

[Live example: Excel Export - Cover Page](https://www.ag-grid.com/archive/36.2.0/examples/excel-export-extra-content/excel-export-cover-page/typescript/)

## Adding Header and Footer Content

Extra content can also be added in the form of Headers and Footers of the exported Excel file. Please note that this header and footer content is only visible when printing or exporting from Excel to PDF.

You can set header and footer content via the `headerFooterConfig: ExcelHeaderFooterConfig` object. See it documented further below.

The header and footer object accepts the following placeholders:

- `&[Page]`: Prints the current page number.
- `&[Pages]`: Prints the total number of pages.
- `&[Date]`: Prints the current date.
- `&[Time]`: Prints the current time.
- `&[Tab]`: Prints the current sheet name.
- `&[Path]`: Prints the file path.
- `&[File]`: Prints the file name.
- `&[Picture]`: Adds an image to the Header or Footer, see more [Adding Images to the Header or Footer](https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/excel-export-extra-content/#adding-images-to-the-header-or-footer).

#### Excel Export - Custom Header and Footer

```ts
import {
  ClientSideRowModelModule,
  ExcelExportParams,
  ExcelHeaderFooterConfig,
  ExcelHeaderFooterContent,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  ExcelExportModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableDevValidations();
}

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

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs: [
    { field: "athlete", minWidth: 200 },
    { field: "country", minWidth: 200 },
    { field: "sport", minWidth: 150 },
    { field: "gold" },
    { field: "silver" },
    { field: "bronze" },
    { field: "total" },
  ],
  defaultColDef: {
    filter: true,
    minWidth: 100,
    flex: 1,
  },

  popupParent: document.body,
};

const getValues = (type: string) => {
  const value = (
    document.querySelector("#" + type + "Value") as HTMLInputElement
  ).value;

  if (value == null) {
    return;
  }

  const obj: ExcelHeaderFooterContent = {
    value: value,
  };

  obj.position = (
    document.querySelector("#" + type + "Position") as HTMLInputElement
  ).value as "Left" | "Center" | "Right";

  const fontName = (
    document.querySelector("#" + type + "FontName") as HTMLInputElement
  ).value;
  const fontSize = (
    document.querySelector("#" + type + "FontSize") as HTMLInputElement
  ).value;
  const fontWeight = (
    document.querySelector("#" + type + "FontWeight") as HTMLInputElement
  ).value;
  const underline = (
    document.querySelector("#" + type + "Underline") as HTMLInputElement
  ).checked;

  if (
    fontName !== "Calibri" ||
    fontSize != "11" ||
    fontWeight !== "Regular" ||
    underline
  ) {
    obj.font = {};
    if (fontName !== "Calibri") {
      obj.font.fontName = fontName;
    }
    if (fontSize != "11") {
      obj.font.size = Number.parseInt(fontSize);
    }
    if (fontWeight !== "Regular") {
      if (fontWeight.indexOf("Bold") !== -1) {
        obj.font.bold = true;
      }
      if (fontWeight.indexOf("Italic") !== -1) {
        obj.font.italic = true;
      }
    }

    if (underline) {
      obj.font.underline = "Single";
    }
  }

  return obj;
};

const getParams: () => ExcelExportParams | undefined = () => {
  const header = getValues("header");
  const footer = getValues("footer");

  if (!header && !footer) {
    return undefined;
  }

  const obj: ExcelExportParams = {
    headerFooterConfig: {
      all: {},
    },
  };

  if (header) {
    obj.headerFooterConfig!.all!.header = [header];
  }

  if (footer) {
    obj.headerFooterConfig!.all!.footer = [footer];
  }

  return obj;
};

function onBtExport() {
  gridApi!.exportDataAsExcel(getParams());
}

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/small-olympic-winners.json")
  .then((response) => response.json())
  .then((data) =>
    gridApi!.setGridOption(
      "rowData",
      data.filter((rec: any) => rec.country != null),
    ),
  );

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).onBtExport = onBtExport;
}
```

[Live example: Excel Export - Custom Header and Footer](https://www.ag-grid.com/archive/36.2.0/examples/excel-export-extra-content/excel-export-header-footer/typescript/)

## Adding Images to the Header or Footer

In addition to exporting the Grid as an Excel file, you can also provide pictures on the Header or Footer of the Worksheet. This can be useful when you want to use images as watermark for example. Please note that the watermark image will only be visible in the header & footer view or when printing in Excel.

#### Excel Export - Header Image

```ts
import {
  ClientSideRowModelModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  ExcelExportModule,
} from "ag-grid-enterprise";
import { agGridLogo } from "./logo";
import { IOlympicData } from "./interfaces";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableDevValidations();
}

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

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  columnDefs: [
    { field: "athlete", minWidth: 200 },
    { field: "country", minWidth: 200 },
    { field: "sport", minWidth: 150 },
    { field: "gold" },
    { field: "silver" },
    { field: "bronze" },
    { field: "total" },
  ],
  defaultColDef: {
    filter: true,
    minWidth: 100,
    flex: 1,
  },

  popupParent: document.body,

  defaultExcelExportParams: {
    headerFooterConfig: {
      all: {
        header: [
          {
            value: "&[Picture]",
            image: {
              id: "logo",
              base64: agGridLogo,
              width: 720,
              height: 250,
              imageType: "png",
              recolor: "Grayscale",
            },
            position: "Center",
          },
        ],
      },
    },
  },
};

function onBtExport() {
  gridApi!.exportDataAsExcel();
}

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/small-olympic-winners.json")
  .then((response) => response.json())
  .then((data) =>
    gridApi!.setGridOption(
      "rowData",
      data.filter((rec: any) => rec.country != null),
    ),
  );

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).onBtExport = onBtExport;
}
```

[Live example: Excel Export - Header Image](https://www.ag-grid.com/archive/36.2.0/examples/excel-export-extra-content/excel-export-header-image/typescript/)

### ExcelHeaderFooterConfig

Properties available on the `ExcelHeaderFooterConfig` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `all` | `ExcelHeaderFooter` |  |  |  |
| `first` | `ExcelHeaderFooter` |  |  |  |
| `even` | `ExcelHeaderFooter` |  |  |  |

### ExcelHeaderFooter

Properties available on the `ExcelHeaderFooter` interface. At least one of header or footer is required or both.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `header` | `ExcelHeaderFooterContent[]` |  |  |  |
| `footer` | `ExcelHeaderFooterContent[]` |  |  |  |

### ExcelHeaderFooterContent

Properties available on the `ExcelHeaderFooterContent` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `value` | `string` |  |  |  |
| `image` | `ExcelHeaderFooterImage` |  |  |  |
| `position` | `'Left' \| 'Center' \| 'Right'` |  |  |  |
| `font` | `ExcelFont` |  |  |  |

### ExcelHeaderFooterImage

Properties available on the `ExcelHeaderFooterImage` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `width` | `number` |  |  |  |
| `height` | `number` |  |  |  |
| `id` | `string` |  |  |  |
| `base64` | `string` |  |  |  |
| `imageType` | `'jpg' \| 'png' \| 'gif'` |  |  |  |
| `recolor` | `'Grayscale' \| 'Black & White' \| 'Washout'` |  |  |  |
| `brightness` | `number` |  |  |  |
| `contrast` | `number` |  |  |  |
| `altText` | `string` |  |  |  |
