Advanced

Excel Export

Export NuGrid data to Excel files.

NuGrid supports exporting data to Excel files with formatting, using the write-excel-file library.

Setup

Install the optional dependency:

pnpm add write-excel-file

Basic Export

Export data using the grid ref:

<script setup lang="ts">
const gridRef = useTemplateRef('grid')

function exportToExcel() {
  gridRef.value?.exportToExcel({
    filename: 'users',
  })
}
</script>

<template>
  <UButton @click="exportToExcel">
    Export to Excel
  </UButton>

  <NuGrid ref="grid" :data="data" :columns="columns" />
</template>

Export Options

interface ExcelExportOptions {
  filename?: string
  sheetName?: string
  includeHeaders?: boolean
  columns?: string[]
  dateFormat?: string
}

Options Reference

OptionTypeDefaultDescription
filenamestring'export'File name (without extension)
sheetNamestring'Sheet1'Excel sheet name
includeHeadersbooleantrueInclude column headers
columnsstring[]All columnsColumns to export
dateFormatstring'YYYY-MM-DD'Date format

Selective Column Export

Export specific columns:

<script setup lang="ts">
function exportToExcel() {
  gridRef.value?.exportToExcel({
    filename: 'user-emails',
    columns: ['name', 'email'],  // Only export these columns
  })
}
</script>

Export with Formatting

Columns can define their export format:

const columns: NuGridColumn<Product>[] = [
  {
    accessorKey: 'name',
    header: 'Product Name',
  },
  {
    accessorKey: 'price',
    header: 'Price',
    // Excel will format as currency
    exportFormat: '$#,##0.00',
  },
  {
    accessorKey: 'createdAt',
    header: 'Created',
    // Excel date format
    exportFormat: 'YYYY-MM-DD',
  },
  {
    accessorKey: 'quantity',
    header: 'Quantity',
    // Integer format
    exportFormat: '#,##0',
  },
]

Export Filtered Data

Export only visible (filtered) data:

<script setup lang="ts">
function exportFiltered() {
  gridRef.value?.exportToExcel({
    filename: 'filtered-users',
    // Only exports rows that pass current filters
    filteredOnly: true,
  })
}
</script>

Export Selected Rows

Export only selected rows:

<script setup lang="ts">
function exportSelected() {
  gridRef.value?.exportToExcel({
    filename: 'selected-users',
    selectedOnly: true,
  })
}
</script>

<template>
  <div>
    <UButton
      :disabled="!hasSelection"
      @click="exportSelected"
    >
      Export Selected
    </UButton>

    <NuGrid
      ref="grid"
      v-model:row-selection="rowSelection"
      :data="data"
      :columns="columns"
      selection="multi"
    />
  </div>
</template>

Export Grouped Data

Export with group structure:

<script setup lang="ts">
const grouping = ref(['category'])

function exportWithGroups() {
  gridRef.value?.exportToExcel({
    filename: 'grouped-products',
    includeGroups: true,  // Include group headers
  })
}
</script>

<template>
  <NuGrid
    ref="grid"
    v-model:grouping="grouping"
    :data="data"
    :columns="columns"
  />
</template>

Custom Export Function

For full control, access the data directly:

<script setup lang="ts">
import writeXlsxFile from 'write-excel-file'

async function customExport() {
  const grid = gridRef.value
  const rows = grid?.tableApi?.getFilteredRowModel().rows ?? []

  const schema = [
    {
      column: 'Name',
      type: String,
      value: (row) => row.original.name,
    },
    {
      column: 'Email',
      type: String,
      value: (row) => row.original.email,
    },
    {
      column: 'Salary',
      type: Number,
      format: '$#,##0.00',
      value: (row) => row.original.salary,
    },
  ]

  await writeXlsxFile(rows, {
    schema,
    fileName: 'custom-export.xlsx',
  })
}
</script>

Export Button Component

Create a reusable export button:

<!-- components/GridExportButton.vue -->
<script setup lang="ts">
defineProps<{
  gridRef: any
  filename?: string
}>()
</script>

<template>
  <UDropdownMenu
    :items="[
      {
        label: 'Export All',
        icon: 'i-lucide-file-spreadsheet',
        onSelect: () => gridRef?.exportToExcel({ filename }),
      },
      {
        label: 'Export Filtered',
        icon: 'i-lucide-filter',
        onSelect: () => gridRef?.exportToExcel({ filename, filteredOnly: true }),
      },
      {
        label: 'Export Selected',
        icon: 'i-lucide-check-square',
        onSelect: () => gridRef?.exportToExcel({ filename, selectedOnly: true }),
      },
    ]"
  >
    <UButton variant="outline" icon="i-lucide-download">
      Export
    </UButton>
  </UDropdownMenu>
</template>

Usage:

<template>
  <div>
    <GridExportButton :grid-ref="gridRef" filename="my-data" />
    <NuGrid ref="gridRef" :data="data" :columns="columns" />
  </div>
</template>

Example: Complete Export Setup

<script setup lang="ts">
const gridRef = useTemplateRef('grid')
const toast = useToast()

const columns: NuGridColumn<Product>[] = [
  { accessorKey: 'id', header: 'ID' },
  { accessorKey: 'name', header: 'Name' },
  { accessorKey: 'category', header: 'Category' },
  {
    accessorKey: 'price',
    header: 'Price',
    exportFormat: '$#,##0.00',
  },
  {
    accessorKey: 'stock',
    header: 'Stock',
    exportFormat: '#,##0',
  },
  {
    accessorKey: 'createdAt',
    header: 'Created',
    exportFormat: 'YYYY-MM-DD',
  },
]

async function exportAll() {
  try {
    await gridRef.value?.exportToExcel({
      filename: 'products',
      sheetName: 'Products',
    })
    toast.add({ title: 'Exported', color: 'success' })
  } catch (error) {
    toast.add({ title: 'Export failed', color: 'error' })
  }
}

async function exportSelected() {
  const selected = gridRef.value?.getSelectedRows()
  if (!selected?.length) {
    toast.add({ title: 'No rows selected', color: 'warning' })
    return
  }

  await gridRef.value?.exportToExcel({
    filename: 'selected-products',
    selectedOnly: true,
  })
}
</script>

<template>
  <div class="space-y-4">
    <div class="flex gap-2">
      <UButton icon="i-lucide-download" @click="exportAll">
        Export All
      </UButton>
      <UButton
        variant="outline"
        icon="i-lucide-check-square"
        @click="exportSelected"
      >
        Export Selected
      </UButton>
    </div>

    <NuGrid
      ref="grid"
      v-model:row-selection="rowSelection"
      :data="data"
      :columns="columns"
      selection="multi"
    />
  </div>
</template>

Next Steps

State Persistence

Save and restore grid state.

Drag & Drop

Enable row and column reordering.