NestboltNestbolt

@nestbolt/excel

Introduction

Supercharged Excel (XLSX) and CSV export/import for NestJS with decorators, concern-based composition, templates, and pluggable storage backends.

@nestbolt/excel brings first-class spreadsheet support to NestJS applications. It lets you generate XLSX and CSV files from your existing entities, import spreadsheet data with validation, fill pre-designed Excel templates, and store the results on local disk or cloud storage -- all with a clean, composable API.

Two Ways to Export

The package offers two complementary approaches for building exports. Pick whichever matches the complexity of your use case, or mix them freely across your application.

Decorator API

Decorate your existing entities or DTOs with @Exportable(), @ExportColumn(), and @ExportIgnore(). The library reads the metadata at runtime and builds the spreadsheet automatically. This is the fastest path when you already have typed data classes:

@Exportable({ title: "Users", autoSize: true, frozenRows: 1 })
class UserEntity {
  @ExportColumn({ order: 1, header: "ID" })
  id!: number;

  @ExportColumn({ order: 2 })
  firstName!: string;

  @ExportColumn({ order: 3 })
  email!: string;

  @ExportIgnore()
  password!: string;
}

// In your controller:
return this.excelService.downloadFromEntityAsStream(UserEntity, users, "users.xlsx");

Concern-based API

For advanced scenarios -- multiple sheets, templates, lifecycle events, custom cell styles, CSV overrides -- implement one or more concern interfaces on a plain class. Each interface opts in to a single feature, keeping exports composable and testable:

class UsersExport implements FromCollection, WithHeadings, WithMapping, ShouldAutoSize {
  readonly shouldAutoSize = true as const;

  constructor(private readonly users: User[]) {}

  collection() {
    return this.users;
  }

  headings() {
    return ["ID", "Name", "Email"];
  }

  map(user: User) {
    return [user.id, user.name, user.email];
  }
}

// In your controller:
return this.excelService.downloadAsStream(new UsersExport(users), "users.xlsx");

Full Import Pipeline

Reading spreadsheets is just as composable. Build an import class that describes how to parse, map, validate, and receive the data:

class UsersImport implements ToCollection, WithHeadingRow, WithValidation, SkipsOnError {
  readonly hasHeadingRow = true as const;
  readonly skipsOnError = true as const;

  handleCollection(rows: Record<string, any>[]) {
    // Process valid rows
  }

  rules() {
    return {
      name: [{ validate: (v) => v?.length > 0, message: "Name is required" }],
      email: [{ validate: (v) => /^.+@.+\..+$/.test(v), message: "Invalid email" }],
    };
  }
}

const result = await this.excelService.import(new UsersImport(), "users.xlsx");
// result.rows -- valid rows
// result.errors -- per-row validation errors
// result.skipped -- count of skipped rows

Key Features

  • XLSX and CSV output with automatic type detection from the filename extension.
  • Decorator-based exports that work directly with your entities -- no boilerplate export classes needed for simple cases.
  • Concern-based composition for advanced exports: multiple sheets, styling, auto-filter, frozen panes, column formatting, lifecycle events, custom start cells, and CSV settings.
  • Template exports that fill {{placeholder}} patterns in existing .xlsx files, with support for repeating row data.
  • Full import pipeline with heading rows, column mapping, row transformation, custom validation rules, class-validator DTO support, batch inserts, row limits, empty-row skipping, and error tolerance.
  • Pluggable storage drivers -- local filesystem, AWS S3 (and S3-compatible services), Google Cloud Storage, and Azure Blob Storage -- all configurable through a unified disks option.
  • Global module -- register once in your root module and inject ExcelService or DiskManager anywhere.
  • Streaming downloads -- return a NestJS StreamableFile directly from controller methods for memory-efficient file delivery.

What is Next

Continue with the rest of the documentation: