Skip to main content

grid_sheet 3.0.1 copy "grid_sheet: ^3.0.1" to clipboard
grid_sheet: ^3.0.1 copied to clipboard

A powerful Flutter DataGrid/DataTable for large datasets, offering Excel-like features and fully customizable cells — ready with minimal setup. See README for full features

GridSheet #

It is a highly flexible, high-performance Flutter DataTable / DataGrid package designed for building rich tabular UIs similar to Excel or spreadsheet applications, with minimal configuration and powerful built-in features. It gives developers full control over both data management and UI presentation while remaining easy to set up and extend.

pub package Platform License

Demo #

GridSheet Demo

Explore GridSheet's features through our live demos. Every demo page has a Code tab with its complete source.

Found a bug or have an idea to improve GridSheet? We'd love to hear from you.

  • Report bugs or request features: here

Table of Contents #

Highly Configurable #

GridSheet is designed to adapt to different application requirements rather than enforcing a fixed set of behaviors.

Most features are configurable and can be enabled, disabled, or customized through the available configuration classes and callbacks. Whether you need a lightweight data table or a fully featured spreadsheet-like experience, you can choose only the functionality your application requires.

Every application has different requirements, so GridSheet focuses on providing sensible defaults while allowing you to override behavior whenever needed. Most visual components, interactions, and data handling mechanisms can be customized through configuration objects, builder callbacks, and event listeners.

You can integrate GridSheet with local data sources, server-side APIs, or your own state management solution. Features can be enabled independently, allowing you to keep the widget lightweight while adding advanced capabilities only where they are needed.

The package also exposes customization points for headers, rows, filters, footers, cells, pagination, loading states, empty states, context menus, and styling. This makes it easy to match your application's design system without modifying the package itself.

As new features are introduced, they are designed to remain configurable and backward compatible whenever possible, ensuring existing implementations continue to work while giving you access to additional functionality.

The goal of GridSheet is to provide a flexible foundation that can scale from simple data tables to complex enterprise applications with minimal changes to your existing code.

Features #

Core Functionality #

  • ✅ Data Display & Management - Display tabular data with full CRUD operations on rows and columns
  • ✅ Multi-Column Sorting - Sort by multiple columns with ascending/descending order
  • ✅ Advanced Filtering - 14 comparison modes (contains, exact match, greater/less than, between, LIKE patterns, and more), combining values with AND/OR, plus typed operators (>100, =Apple, app%) parsed automatically with no comparison chosen
  • ✅ Cross-Column Search - Search across every cell in every row, narrowing progressively as more terms are added, with the same typed-operator parsing (>100, app%) as filtering
  • ✅ Pagination - Built-in pagination with customizable rows per page (client-side, server-side, and infinite scroll)
  • ✅ Column Pinning - Pin columns to the left or right side, excluded from horizontal scrolling
  • ✅ Row Pinning - Pin specific rows to a non-scrolling band above or below the scrollable section, excluded from sorting, filtering, and pagination
  • ✅ Column Reordering - Drag-and-drop column reordering with visual feedback,. onColumnReorder callback
  • ✅ Row Reordering - Long-press-and-drag row repositioning with visual feedback, onRowReorder callback. Works even without a serial-number column — the whole row becomes the drag handle
  • ✅ Column Resizing - Resize columns by dragging column borders
  • ✅ Row Resizing - Resize rows by dragging a handle on their bottom edge. Works even without a serial-number column — every column grows its own handle
  • ✅ Cell Editing - Inline cell editing with type-specific input formatters
  • ✅ Dropdown Cell Type - Built-in dropdown/select cells with a constrained options list and popup menu

Selection & Navigation #

  • ✅ Multi-Selection - Select multiple rows, columns, or cells simultaneously
  • ✅ Keyboard Navigation - Navigate between cells with arrow keys, Tab/Shift+Tab, and Enter/Shift+Enter
  • ✅ Select All - Tri-state header checkbox (unchecked/indeterminate/checked) to select/deselect all visible rows
  • ✅ Selection Callbacks - Events for row, column, and cell selection changes

Data Manipulation #

  • ✅ Change Tracking - Track inserted, modified, and deleted rows
  • ✅ Position-Based Insert - Insert rows/columns above/below or before/after the current selection
  • ✅ Undo Operations - Revert changes to individual rows or all changes
  • ✅ Cell Undo/Redo - Step back and forward through cell edits with gridManager.history or Ctrl+Z / Ctrl+Y
  • ✅ Bulk Operations - Clear, fill, find, and replace operations on cell ranges
  • ✅ Copy/Paste - Clipboard support for tab-delimited data
  • ✅ Auto-Fill - Fill cells with patterns and automatic incrementing

Visual Customization #

  • ✅ Conditional Formatting - Apply background colors and text styles based on expressions
  • ✅ Custom Cell Widgets - Build custom widgets for headers, filters, and data cells via cellBuilder, optionally organized in an IGridSheetCustomCellBuilder implementation
  • ✅ Row State Indicators - Visual indicators for inserted, modified, and deleted rows
  • ✅ Theme Support - Comprehensive styling with light/dark theme support
  • ✅ Custom Wrappers - Wrap header, filter, and row widgets with custom containers

Advanced Features #

  • ✅ Row & Column Virtualization - Rows and non-pinned columns are windowed (Sliver-backed), only building what's currently visible plus a small overscan buffer — scrolls smoothly with 100K+ rows and very wide schemas
  • ✅ Row Expansion - Inline master-detail panel below each row, rendered full-width across all pinned/scrollable columns, with responsive field layout, animated open/close, and full cell widget consistency
  • ✅ Row Separators - Insert a custom full-width widget below any row via rowSeparatorBuilder — section dividers, group banners, subtotal rows, and more
  • ✅ Row Swipe - Swipe a row sideways to reveal a custom strip on either side via rowSwipeConfiguration.
  • ✅ Row Grouping - Group rows by one or more columns (by value, numeric range, date part, or custom logic) under collapsible headers, with per-group aggregates (sum, average, min, max, count, custom) and a grand total via groupingConfiguration.rows
  • ✅ Column Grouping - Gather related columns under nested header bands (e.g. Contact over Name, Email and Phone) that can collapse to fewer columns, across pinned and scrollable columns, via groupingConfiguration.columns
  • ✅ Form Layout - Card-based label : value layout for narrow/mobile viewports, switching automatically at a configurable breakpoint while sharing the table's selection, editing, reorder, and pagination
  • ✅ Runtime Configuration Updates - Toggle visual and behavioral flags at runtime via gridManager.config.updateGrid without rebuilding the parent widget
  • ✅ Data Reload - Manual reload on demand via gridManager.reload, plus interval-based and daily scheduled auto-reload with onBeforeReload / onAfterReload lifecycle callbacks
  • ✅ Expression Evaluation - Evaluate conditional expressions for cell editability and formatting. Implement GridSheetEvaluator to use your own logic for conditional expressions
  • ✅ Context Menus - Right-click context menus for cells, rows, and columns
  • ✅ Column Visibility - Show/hide columns dynamically
  • ✅ Row Visibility - Show/hide rows dynamically, addressed by row key
  • ✅ Row Height Management - Auto-fit or manually adjust row heights
  • ✅ Column Width Management - Auto-fit or manually adjust column widths
  • ✅ Snapshot/Restore - Save and restore grid state for undo/redo functionality
  • ✅ Statistics - Calculate sum, average, min, max, median for numeric columns
  • ✅ Data Export - Export to CSV with customizable options
  • ✅ Loading States - Display custom loading indicators during operations
  • ✅ Formula Columns - Excel-style formulas, automatic evaluation, reactive updates, and filter support
  • ✅ Undo Delete - After deleting rows or columns, show an UNDO prompt instead of deleting permanently right away.
  • ✅ Right-to-Left (RTL) Support - Full right-to-left support: the whole grid mirrors its layout, scrolling, icons and navigation.
  • ✅ Localization - Translate the grid's own text (tooltips, pagination footer, undo banner, group and pivot labels) with GridSheetLocalizations, per grid or through your app's localizationsDelegates.
  • ✅ Animations - Optional reveal animations for columns and rows, and a flash when a cell's value changes.
  • ✅ Dynamic Table Generation - Generate a table of any size from a column and row count, for prototypes and performance testing.

Widgets #

The package provides several customizable widget options:

  • ✅ Empty Rows Widget - Show your own widget when the grid has no rows..
  • ✅ Empty Columns Widget - Show your own widget when every column is hidden..
  • ✅ Loading Widget - Show your own loading indicator while the grid is loading or processing data.
  • ✅ TopBar Widget - Optional widget displayed above the table.
  • ✅ BottomBar Widget - Optional widget displayed below the table.

Installation #

Add grid_sheet to your pubspec.yaml:

dependencies:
  grid_sheet: ^3.0.1

Then run:

flutter pub get

Import #

import 'package:grid_sheet/grid_sheet.dart';

Usage #

Basic Setup #

late final GridSheetManager gridManager;

GridSheet(
  columns: [
    GridSheetColumn(
      key: const ValueKey('col_name'),
      index: 0,
      name: 'COL_NAME',
      title: 'Name',
      type: GridSheetColumnType.text(),
      width: 200,
    ),
    GridSheetColumn(
      key: const ValueKey('col_age'),
      index: 1,
      name: 'AGE',
      title: 'Age',
      type: GridSheetColumnType.double(),
      width: 80,
      textAlign: TextAlign.right,
    ),
    GridSheetColumn(
      key: const ValueKey('col_active'),
      index: 2,
      name: 'ACTIVE',
      title: 'Active',
      type: GridSheetColumnType.boolean(),
      width: 80,
    ),
  ],
  rows: List.generate(
    50,
    (i) => GridSheetRow(
      key: ValueKey('row_$i'),
      index: i,
      data: [
        'Person $i',
        20 + i,
        i.isEven,
      ],
    ),
  ),
  onLoaded: (event) {
    gridManager = event.gridManager;
    debugPrint('Table initialized!');
  },
);

Data Ownership #

The grid changes the GridSheetRow objects you pass it, in place. As the grid is used it writes into each row object: cell values (also rearranged when columns are reordered), change state and original data, selection, height, position and pinning.

That has two consequences:

  • Don't share row objects between grids. Two GridSheets given the same GridSheetRow objects edit each other's rows. Build a separate list of rows for each grid.
  • Don't keep GridSheetRow objects in immutable state (Bloc, Riverpod, Redux, …). The grid would change the objects your earlier states still hold. Keep your own models in state, map them to rows when building, and read the edits back through the manager:
GridSheet(
  columns: columns,
  // New row objects from your own models on each build. Rebuilding with
  // equal data changes nothing, so edits made in the grid survive.
  rows: [
    for (final (i, p) in people.indexed)
      GridSheetRow(key: ValueKey(p.id), index: i, data: [p.name, p.age, p.active]),
  ],
  onCellValueChanged: (event) {
    // Read edits back as plain values, not as the row objects.
    final edited = event.gridManager.data.toMap(event.rowKey);
    // ...update your own state from `edited`.
  },
);

Passing different rows or columns (by key and content) replaces the grid's data and keeps sort, filters, grouping, the page, and the selection and expansion of rows that are still there. If the user has unsaved edits at that moment, the new data wins. Unsaved edits are listed in gridManager.changes.

Platform Support #

GridSheet works in web browsers and supports all Flutter platforms:

  • ✅ Android
  • ✅ iOS
  • ✅ Web (Chrome, Edge, Firefox, Safari)
  • ✅ Windows
  • ✅ macOS
  • ✅ Linux

Notes #

Performance Considerations #

  • Both rows and non-pinned columns are virtualized (windowed): only the rows and columns currently visible, plus a small overscan buffer, are actually built — scrolling in either direction stays smooth into the 100K-row / hundreds-of-column range without needing pagination purely for rendering performance.
  • Pinned-left and pinned-right columns are never windowed (there are typically few of them), and always fully built for every visible row.
  • Pagination (client-side, server-side, or infinite scroll) is still the right tool when the dataset itself — not just its on-screen rendering — is too large to hold in memory at once; use server-side pagination or infinite scroll for very large remote datasets so only one page of rows is fetched/held at a time.
  • Limit the number of conditional format rules for better performance
  • Avoid excessive column reordering in production
  • The controller pool automatically manages TextEditingControllers, bounding retention to the visible row window (plus overscan) rather than the whole current page — most impactful with pagination disabled, where the "current page" is the entire dataset
  • Column/row drag-resize and row-expansion animation frames update only the affected row or column's layout instead of rebuilding the whole grid's row/column extents
  • Formula expressions are parsed once and cached by their text, so repeated recalculation of the same formula doesn't re-tokenize/re-parse it

Limitations #

  • Column expressions use the expressions package for evaluation
  • Custom evaluators can be provided for advanced expression handling
  • Multi-column sorting preserves order by priority (first added = highest priority)
  • While rows are grouped, rows can't be reordered by dragging (the same as while sorted), client-side pagination counts group header and summary lines toward rowsPerPage, and the form layout shows its cards in a single list
  • Column group bands aren't shown in the form layout. Collapsing a group hides its columns on screen only (they stay visible); exports of the visible columns match the screen, and GridSheetColumnScope.all includes them. data.toGrouped() returns the data with its row and column grouping for exporting to any format

Best Practices #

  1. Use stable keys - Always provide unique ValueKey<String> for rows and columns
  2. Leverage callbacks - Use onCellValueChanged to track changes in real-time
  3. Manage state externally - Use GridSheetManager from callbacks to update external state
  4. Optimize rendering - Use hasTextController: false for read-only columns or when using custom widgets that do not require a TextEditingController, preventing unnecessary controller creation and improving performance. showOverflowTooltip defaults to false (no per-cell overflow measurement); opt it in with showOverflowTooltip: true only on columns where truncated text is likely (e.g. free-form text columns) and the hover tooltip is worth the cost.
  5. Handle loading states - Provide a loadingIndicator for better UX during async operations

Contributions #

If GridSheet has been helpful, please consider giving our Pub package a 👍. You can also support the project by spreading the word and sharing it with others.

We truly appreciate your support and contributions to the ongoing development of this project. We welcome discussions, feedback, and pull requests—feel free to share your ideas or suggestions on our GitHub repository. Issues Tracker

License #

This project is licensed under the MIT License - see the LICENSE file for details.

4
likes
160
points
438
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A powerful Flutter DataGrid/DataTable for large datasets, offering Excel-like features and fully customizable cells — ready with minimal setup. See README for full features

Homepage
View/report issues

Topics

#data-table #data-grid #table #excel #spreadsheet

License

MIT (license)

Dependencies

expressions, flutter

More

Packages that depend on grid_sheet