PDF Export uses the PDF Base 14 fonts by default. These fonts cover WinAnsi characters, including common Western European text such as praça, Casé, and robô. Register a static TrueType font when the document needs characters that the built-in fonts do not contain.
Non Latin Languages Copy Link
Start by registering one font family and using it as the default for the whole export. The two font settings have different purposes:
fontsregisters the font families that are available to the exporter. It is an array because an export can make several families available.defaultCellStyle.fontFamilyselects one registered family as the default for exported text. Headers inherit it because properties not set bydefaultHeaderStylecascade fromdefaultCellStyle.
The following example exports Japanese text. The fonts array contains only IBM Plex Sans JP, and defaultCellStyle.fontFamily selects that family. No style callback is required because every exported element uses the same family.
The optional language property is a BCP 47 language tag. It enables language-specific OpenType features and is also written to the PDF document metadata.
const japaneseFontData = await fetch('/fonts/pdf-export/IBMPlexSansJP-Regular.ttf')
.then((response) => response.arrayBuffer()
);
const japaneseFont = {
family: 'IBM Plex Sans JP',
faces: [{ data: japaneseFontData, weight: 400 }],
};
const gridOptions = {
defaultPdfExportParams: {
fonts: [japaneseFont],
defaultCellStyle: { fontFamily: japaneseFont.family },
language: 'ja',
},
};import {
ClientSideRowModelModule,
GridApi,
GridOptions,
ModuleRegistry,
createGrid,
enableDevValidations,
} from "ag-grid-community";
import { ContextMenuModule, PdfExportModule } from "ag-grid-enterprise";
// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
ModuleRegistry.registerModules([
ClientSideRowModelModule,
ContextMenuModule,
PdfExportModule,
]);
interface LanguageSample {
text: string;
}
let gridApi: GridApi<LanguageSample>;
let preparePdfExport: Promise<void>;
const fontFamily = "IBM Plex Sans JP";
const gridOptions: GridOptions<LanguageSample> = {
columnDefs: [{ field: "text", headerName: "Japanese Text", flex: 1 }],
rowData: [
{ text: "広場は太郎と花子とロボットを迎えました。" },
{ text: "PDFには日本語の文字が埋め込まれています。" },
{ text: "このグリッドでは一つのフォントを使用します。" },
],
loading: true,
onGridReady: (params) => {
preparePdfExport = loadFont("IBMPlexSansJP-Regular.ttf").then((data) => {
params.api.setGridOption("defaultPdfExportParams", {
fonts: [{ family: fontFamily, faces: [{ data, weight: 400 }] }],
defaultCellStyle: { fontFamily },
language: "ja",
});
params.api.setGridOption("loading", false);
});
},
};
function onBtExport() {
preparePdfExport.then(() => {
gridApi.exportDataAsPdf();
});
}
const fontBaseUrl = "https://www.ag-grid.com/archive/36.2.0/fonts/pdf-export/";
async function loadFont(fileName: string): Promise<ArrayBuffer> {
const response = await fetch(fontBaseUrl + fileName);
if (!response.ok) {
throw new Error(`Unable to load ${fileName}`);
}
return response.arrayBuffer();
}
gridApi = createGrid(
document.querySelector<HTMLElement>("#myGrid")!,
gridOptions,
);
if (typeof window !== "undefined") {
// Attach external event handlers to window so they can be called from index.html
(<any>window).onBtExport = onBtExport;
}
.example-wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
.controls {
margin-bottom: 8px;
}
#myGrid {
flex: 1 1 0;
width: 100%;
}
<div class="example-wrapper">
<div class="controls">
<button onclick="onBtExport()">Export to PDF</button>
</div>
<div id="myGrid"></div>
</div>
Loading Font Files Copy Link
Font files are not fetched by AG Grid. The application is responsible for loading the bytes before starting the export and for complying with the font's licence. When the font's embedding permissions allow it, PDF Export embeds only the characters used by the document instead of the complete font file. This process, known as font subsetting, reduces the size of the exported PDF. Fonts that prohibit subsetting are embedded in full.
The fontFamily value must exactly match a registered or built-in family. If it does not, PDF Export reports the unknown family and the available alternatives, then cancels the export without creating a file.
Each family can contain Regular, Medium, Bold, Italic, or other faces. PDF Export selects the closest face for the requested fontWeight and fontStyle.
Multiple Languages Copy Link
One registered family is sufficient when it contains every character used by the document. When different text requires different families, register all the families through fonts, then select the appropriate fontFamily for each element using processStyleCallback or a PDF style. This differs from the previous example, where one default family could be used for every cell.
The following example uses the built-in Helvetica family for Portuguese and registers IBM Plex Sans families for Greek, Bulgarian Cyrillic, Japanese, Simplified Chinese, and Traditional Chinese. Each row stores its required family and language tag. processStyleCallback reads those values and selects the family for each exported cell. The Text and Text Bold columns also demonstrate face selection within each family. The configuration builds on the same font-loading pattern as the previous example.
const gridOptions = {
defaultPdfExportParams: {
fonts: [japaneseFont, simplifiedChineseFont, traditionalChineseFont],
processStyleCallback: (params) => {
if (params.type !== 'cell' || !params.node?.data) {
return undefined;
}
return {
fontFamily: params.node.data.fontFamily,
fontWeight: params.column?.getColId() === 'boldText' ? 700 : 400,
language: params.node.data.languageTag,
};
},
},
};import {
CellStyleModule,
ClientSideRowModelModule,
GridApi,
GridOptions,
ModuleRegistry,
PdfExportParams,
PdfFontFamilyDefinition,
PdfStyleCallbackParams,
createGrid,
enableDevValidations,
} from "ag-grid-community";
import { ContextMenuModule, PdfExportModule } from "ag-grid-enterprise";
// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
ModuleRegistry.registerModules([
CellStyleModule,
ClientSideRowModelModule,
ContextMenuModule,
PdfExportModule,
]);
interface LanguageSample {
language: string;
text: string;
fontFamily: string;
languageTag?: "bg" | "el" | "ja" | "zh-CN" | "zh-TW";
}
let gridApi: GridApi<LanguageSample>;
let preparePdfExport: Promise<void>;
const gridOptions: GridOptions<LanguageSample> = {
columnDefs: [
{ field: "language", width: 150 },
{ field: "text", headerName: "Exported Text", flex: 1, minWidth: 280 },
{
field: "text",
colId: "boldText",
headerName: "Exported Text (Bold)",
flex: 1,
minWidth: 280,
cellStyle: { fontWeight: "bold" },
},
],
rowData: [
{
language: "Portuguese",
text: "A praça recebeu João, Maria e um robô.",
fontFamily: "Helvetica",
},
{
language: "Greek",
text: "Η πλατεία υποδέχτηκε τον Γιώργο, τη Μαρία και ένα ρομπότ.",
fontFamily: "IBM Plex Sans JP",
languageTag: "el",
},
{
language: "Bulgarian",
text: "Площадът посрещна Иван, Мария и един робот.",
fontFamily: "IBM Plex Sans JP",
languageTag: "bg",
},
{
language: "Japanese",
text: "広場は太郎と花子とロボットを迎えました。",
fontFamily: "IBM Plex Sans JP",
languageTag: "ja",
},
{
language: "Simplified Chinese",
text: "广场迎来了小明、小红和一个机器人。",
fontFamily: "IBM Plex Sans SC",
languageTag: "zh-CN",
},
{
language: "Traditional Chinese",
text: "廣場迎來了志明、雅婷和一個機器人。",
fontFamily: "IBM Plex Sans TC",
languageTag: "zh-TW",
},
],
defaultColDef: {
sortable: true,
resizable: true,
},
loading: true,
onGridReady: (params) => {
preparePdfExport = loadFonts().then((fonts) => {
params.api.setGridOption(
"defaultPdfExportParams",
getDefaultPdfExportParams(fonts),
);
params.api.setGridOption("loading", false);
});
},
};
function getDefaultPdfExportParams(
fonts: PdfFontFamilyDefinition[],
): PdfExportParams {
return {
fonts,
processStyleCallback: (params: PdfStyleCallbackParams<LanguageSample>) => {
const columnId =
params.type === "cell" ? params.column?.getColId() : undefined;
if (
params.type !== "cell" ||
(columnId !== "text" && columnId !== "boldText") ||
!params.node?.data
) {
return undefined;
}
return {
fontFamily: params.node.data.fontFamily,
fontWeight: columnId === "boldText" ? 700 : 400,
language: params.node.data.languageTag,
};
},
};
}
function onBtExport() {
preparePdfExport.then(() => {
gridApi.exportDataAsPdf();
});
}
async function loadFonts(): Promise<PdfFontFamilyDefinition[]> {
const [
japaneseRegular,
japaneseBold,
simplifiedChineseRegular,
simplifiedChineseBold,
traditionalChineseRegular,
traditionalChineseBold,
] = await Promise.all([
loadFont("IBMPlexSansJP-Regular.ttf"),
loadFont("IBMPlexSansJP-Bold.ttf"),
loadFont("IBMPlexSansSC-Regular.ttf"),
loadFont("IBMPlexSansSC-Bold.ttf"),
loadFont("IBMPlexSansTC-Regular.ttf"),
loadFont("IBMPlexSansTC-Bold.ttf"),
]);
return [
{
family: "IBM Plex Sans JP",
faces: [
{ data: japaneseRegular, weight: 400 },
{ data: japaneseBold, weight: 700 },
],
},
{
family: "IBM Plex Sans SC",
faces: [
{ data: simplifiedChineseRegular, weight: 400 },
{ data: simplifiedChineseBold, weight: 700 },
],
},
{
family: "IBM Plex Sans TC",
faces: [
{ data: traditionalChineseRegular, weight: 400 },
{ data: traditionalChineseBold, weight: 700 },
],
},
];
}
const fontBaseUrl = "https://www.ag-grid.com/archive/36.2.0/fonts/pdf-export/";
async function loadFont(fileName: string): Promise<ArrayBuffer> {
const response = await fetch(fontBaseUrl + fileName);
if (!response.ok) {
throw new Error(`Unable to load ${fileName}`);
}
return response.arrayBuffer();
}
gridApi = createGrid(
document.querySelector<HTMLElement>("#myGrid")!,
gridOptions,
);
if (typeof window !== "undefined") {
// Attach external event handlers to window so they can be called from index.html
(<any>window).onBtExport = onBtExport;
}
.example-wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
.controls {
margin-bottom: 8px;
}
#myGrid {
flex: 1 1 0;
width: 100%;
}
<div class="example-wrapper">
<div class="controls">
<button onclick="onBtExport()">Export to PDF</button>
</div>
<div id="myGrid"></div>
</div>
Right-To-Left Languages Copy Link
PDF Export inherits enableRtl from the grid, using rtl for a right-to-left grid and ltr otherwise. An RTL export renders the table columns from right to left and anchors its text accordingly. Set direction on PdfExportParams to override the inherited direction for the whole export, or on an individual PdfCellStyle to override the text direction for one element. Set it to auto to determine the text direction from the first strong directional character.
The export-level language can be overridden on an individual PdfCellStyle. This is useful when an export contains languages such as Arabic (ar), Persian (fa), and Hebrew (he) that require different font families or language-specific shaping.
The following example configures the grid with enableRtl: true and registers fonts for Arabic, Persian, and Hebrew text using the same pattern as the previous examples. The PDF inherits the grid direction, while the Text and Text Bold columns demonstrate Regular and Bold face selection.
The callback selects an embedded font only for body cells. The English headers continue to use the built-in PDF font, while each body row uses a font containing the characters for its language.
const gridOptions = {
enableRtl: true,
defaultPdfExportParams: {
fonts: [arabicFont, hebrewFont],
processStyleCallback: (params) => {
if (params.type !== 'cell' || !params.node?.data) {
return undefined;
}
return {
fontFamily: params.node.data.fontFamily,
fontWeight: params.column?.getColId() === 'boldText' ? 700 : 400,
language: params.node.data.languageTag,
};
},
},
};import {
CellStyleModule,
ClientSideRowModelModule,
GridApi,
GridOptions,
ModuleRegistry,
PdfExportParams,
PdfFontFamilyDefinition,
PdfStyleCallbackParams,
createGrid,
enableDevValidations,
} from "ag-grid-community";
import { ContextMenuModule, PdfExportModule } from "ag-grid-enterprise";
// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
enableDevValidations();
}
ModuleRegistry.registerModules([
CellStyleModule,
ClientSideRowModelModule,
ContextMenuModule,
PdfExportModule,
]);
interface LanguageSample {
language: string;
text: string;
fontFamily: string;
languageTag: "ar" | "fa" | "he";
}
let gridApi: GridApi<LanguageSample>;
let preparePdfExport: Promise<void>;
const gridOptions: GridOptions<LanguageSample> = {
columnDefs: [
{ field: "language", headerName: "Language", width: 150 },
{
field: "text",
headerName: "Text",
flex: 1,
minWidth: 280,
},
{
field: "text",
colId: "boldText",
headerName: "Text Bold",
flex: 1,
minWidth: 280,
cellStyle: { fontWeight: "bold" },
},
],
rowData: [
{
language: "العربية",
text: "استقبلت الساحة أحمد وليلى وروبوتا",
fontFamily: "Noto Sans Arabic",
languageTag: "ar",
},
{
language: "فارسی",
text: "میدان علی و سارا و یک ربات را پذیرفت",
fontFamily: "Noto Sans Arabic",
languageTag: "fa",
},
{
language: "עברית",
text: "הכיכר קיבלה את דוד נועה ורובוט",
fontFamily: "Noto Sans Hebrew",
languageTag: "he",
},
],
defaultColDef: {
resizable: true,
},
enableRtl: true,
loading: true,
onGridReady: (params) => {
preparePdfExport = loadFonts().then((fonts) => {
params.api.setGridOption(
"defaultPdfExportParams",
getDefaultPdfExportParams(fonts),
);
params.api.setGridOption("loading", false);
});
},
};
function getDefaultPdfExportParams(
fonts: PdfFontFamilyDefinition[],
): PdfExportParams {
return {
fonts,
processStyleCallback: (params: PdfStyleCallbackParams<LanguageSample>) => {
if (params.type !== "cell" || !params.node?.data) {
return undefined;
}
const columnId = params.column?.getColId();
return {
fontFamily: params.node.data.fontFamily,
fontWeight: columnId === "boldText" ? 700 : 400,
language: params.node.data.languageTag,
};
},
};
}
function onBtExport() {
preparePdfExport.then(() => {
gridApi.exportDataAsPdf();
});
}
async function loadFonts(): Promise<PdfFontFamilyDefinition[]> {
const [arabicRegular, arabicBold, hebrewRegular, hebrewBold] =
await Promise.all([
loadFont("NotoSansArabic-Regular.ttf"),
loadFont("NotoSansArabic-Bold.ttf"),
loadFont("NotoSansHebrew-Regular.ttf"),
loadFont("NotoSansHebrew-Bold.ttf"),
]);
return [
{
family: "Noto Sans Arabic",
faces: [
{ data: arabicRegular, weight: 400 },
{ data: arabicBold, weight: 700 },
],
},
{
family: "Noto Sans Hebrew",
faces: [
{ data: hebrewRegular, weight: 400 },
{ data: hebrewBold, weight: 700 },
],
},
];
}
const fontBaseUrl = "https://www.ag-grid.com/archive/36.2.0/fonts/pdf-export/";
async function loadFont(fileName: string): Promise<ArrayBuffer> {
const response = await fetch(fontBaseUrl + fileName);
if (!response.ok) {
throw new Error(`Unable to load ${fileName}`);
}
return response.arrayBuffer();
}
gridApi = createGrid(
document.querySelector<HTMLElement>("#myGrid")!,
gridOptions,
);
if (typeof window !== "undefined") {
// Attach external event handlers to window so they can be called from index.html
(<any>window).onBtExport = onBtExport;
}
.example-wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
.controls {
margin-bottom: 8px;
}
#myGrid {
flex: 1 1 0;
width: 100%;
}
<div class="example-wrapper">
<div class="controls">
<button onclick="onBtExport()">Export to PDF</button>
</div>
<div id="myGrid"></div>
</div>
PDF Export shapes registered TrueType fonts using supported OpenType layout tables. This includes contextual Arabic forms, standard and required ligatures, kerning, cursive attachment, mark-to-base positioning, mark-to-mark positioning, and mixed bidirectional text. Canonically equivalent decomposed text is normalised for rendering, while text extraction uses the original logical Unicode sequence, including when several characters are rendered as one ligature.
The fonts used by the examples are unmodified Noto and IBM Plex files distributed under the SIL Open Font License 1.1. See the included Noto licence and IBM Plex licence.
Known Limitations Copy Link
- The built-in PDF fonts support WinAnsi characters only. Register an appropriate TrueType font to export other characters.
- PDF Export does not discover or load browser and system fonts. Applications must load the font data and register each required family and face before exporting.
- PDF Export uses a built-in PDF font when a registered font omits printable ASCII characters such as
/or:. Automatic fallback between registered font families is not supported, so the selected font must contain every non-ASCII character used by the exported element, orprocessStyleCallbackmust select an appropriate registered family. - Only static TrueType fonts with
glyfoutlines are supported. OpenType fonts with CFF outlines, variable fonts, TrueType Collections, WOFF, and WOFF2 are not supported. - GPOS mark-to-ligature positioning (lookup type 5) is not supported. OpenType lookup filtering flags, including
IgnoreMarksand mark-filtering sets, are also not supported. Diacritics attached to ligatures may therefore be positioned incorrectly. - Vertical writing is not supported.
- Bidirectional text spanning multiple independently styled runs is not supported.
API Copy Link
See below the functions on the PdfExportParams interface to customise exported grid values.
Custom static TrueType font families available to this export. Font data must be loaded by the application before export. |
BCP 47 language tag used for text shaping and PDF accessibility metadata. This can be overridden by individual cell styles.
|
Default text direction for the PDF document. When omitted, this inherits the grid's enableRtl setting. Individual PdfCellStyle.direction values take precedence for text. An export-level value of rtl also renders table columns in right-to-left order. |
Default style applied to every body cell, including custom content rows. Grid styles, row and cell styles, and processStyleCallback results override these values. When no style is provided, body cells use Helvetica at 10 points. |