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

A Flutter DataGrid/DataTable with minimal configuration and powerful features like filtering, formulas, pagination, editing, frozen columns, CRUD, and full customization.

example/lib/main.dart

import 'dart:math' hide log;
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:grid_sheet/grid_sheet.dart';
import 'package:grid_sheet_example/toolbar_testing.dart';

void main() {
  runApp(GridSheetApp());
}

class GridSheetApp extends StatelessWidget {
  const GridSheetApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Grid Sheet Package',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blue,
          brightness: Brightness.light,
        ),
      ),
      darkTheme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blue,
          brightness: Brightness.dark,
        ),
      ),
      themeMode: ThemeMode.system,
      home: Scaffold(
        body: GridSheetExample(),
      ),
    );
  }
}

class GridSheetExample extends StatefulWidget {
  const GridSheetExample({super.key});

  @override
  State<GridSheetExample> createState() => _GridSheetExampleState();
}

class _GridSheetExampleState extends State<GridSheetExample> {
  late final GridSheetManager gridManager;

  late List<String> columns;
  late List<List<dynamic>> rows;

  late Map<String, double> columnWidths;
  late Map<String, bool> columnVisibility;
  late Map<String, String> columnActualNames;
  late Map<String, GridSheetColumnType> columnTypes;

  final _random = Random();

  @override
  void initState() {
    super.initState();

    _initData();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // Build style configuration based on current theme
    final styleConfiguration = _buildStyleConfiguration(context);

    return GridSheet(
      columns: _getColumns(),
      rows: _getRows(),
      configuration: GridSheetLayoutConfiguration(
        enableMultiSelection: true,
        enableCellSelection: true,
        enableColumnSelection: true,
        enableRowSelectionOnFirstColumnTap: true,
        enableReorder: true,
        rowsPerPage: 25,
      ),
      styleConfiguration: styleConfiguration,
      conditionalFormatRules: getFormattingRules(),
      onLoaded: (event) {
        gridManager = event.gridManager;
        log('Table initialized!', name: 'GridSheetTableDemo');
      },
      onColumnsSelected: (event) {
        event.selectedColumnsData.forEach((columnName, values) {
          log(
            '$columnName: ${values.length} values',
            name: 'GridSheetTableDemo',
          );
        });
      },
      onRowsSelected: (event) {
        for (final rowMap in event.selectedRowsData) {
          log('Row data: $rowMap', name: 'GridSheetTableDemo');
        }
      },
      onCellsSelected: (event) {
        event.selectedCellsData.forEach((columnName, values) {
          log('$columnName: $values', name: 'GridSheetTableDemo');
        });
      },
      onCellValueChange: (event) {
        log(
          '${event.columnName}: ${event.oldValue} → ${event.newValue}',
          name: 'GridSheetTableDemo',
        );
      },
    );
  }

  _initData() {
    int colsCount = 20;
    int rowsCount = 60;

    columns = List.generate(colsCount, (i) {
      if (i % 5 == 0) {
        return 'Date ${i + 1}';
      } else if (i % 3 == 0) {
        return 'Bool ${i + 1}';
      } else if (i % 2 == 0) {
        return 'Numeric ${i + 1}';
      } else {
        return 'String ${i + 1}';
      }
    });
    columnActualNames = {
      for (var col in columns) col: col.replaceAll(' ', '').toUpperCase(),
    };
    columnVisibility = {
      for (int i = 0; i < colsCount; i++) columns[i]: i % 4 != 0,
    };
    columnTypes = {
      for (var col in columns)
        col: col.startsWith('Date')
            ? GridSheetColumnType.datetime
            : col.startsWith('Bool')
                ? GridSheetColumnType.boolean
                : col.startsWith('Numeric')
                    ? GridSheetColumnType.double
                    : GridSheetColumnType.text,
    };
    columnWidths = {
      for (var col in columns)
        col: () {
          final type = columnTypes[col];
          switch (type) {
            case GridSheetColumnType.boolean:
              return 80.0;
            case GridSheetColumnType.double:
              return 100.0;
            default:
              return 200.0;
          }
        }(),
    };
    rows = List.generate(rowsCount, (rowIndex) {
      return List.generate(colsCount, (colIndex) {
        final columnName = columns[colIndex];
        final type = columnTypes[columnName];

        switch (type) {
          case GridSheetColumnType.text:
            return 'Data_${rowIndex}_$colIndex';
          case GridSheetColumnType.double:
            // Generate a random double between 0 and 100
            return double.tryParse(
              (_random.nextDouble() * 100).toStringAsFixed(2),
            );
          case GridSheetColumnType.boolean:
            return _random.nextBool();
          case GridSheetColumnType.datetime:
            // Generate a random date in the last 10 years
            final start = DateTime.now().subtract(Duration(days: 3650));
            final end = DateTime.now();
            final randomDate = start.add(
              Duration(
                days: _random.nextInt(end.difference(start).inDays),
                hours: _random.nextInt(24),
                minutes: _random.nextInt(60),
                seconds: _random.nextInt(60),
              ),
            );
            return randomDate;
          default:
            return 'N/A';
        }
      });
    });
  }

  GridSheetStyleConfiguration _buildStyleConfiguration(BuildContext context) {
    final colorScheme = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;

    return GridSheetStyleConfiguration(
      gridBackgroundColor: colorScheme.surface,
      headerColor: colorScheme.surfaceContainerHighest,
      filterColor: colorScheme.surfaceContainerHighest,
      rowColor: colorScheme.surface,
      evenRowColor: isDark
          ? colorScheme.surfaceContainerLow
          : colorScheme.surfaceContainerLowest,
      oddRowColor: colorScheme.surface,
      selectionColor: colorScheme.primary,
      gridBorderColor: colorScheme.outlineVariant,
      rowBorderColor: colorScheme.outlineVariant,
      columnBorderColor: colorScheme.outlineVariant,
    );
  }

  List<GridSheetColumn> _getColumns({int frozenColumnCount = 0}) {
    return columns.asMap().entries.map((e) {
      final column = e.value;
      final index = e.key;
      final key = '${GridSheetConstants.columnCopyKeyStartsWith}$index';

      // Read from configurations
      bool isEditable = true;
      bool noEditMode = false;

      final actualName = columnActualNames[column] ?? column;
      final display = columnVisibility[column] ?? false;
      final maxWidth = columnWidths[column] ?? 120.0;
      final type = columnTypes[column] ?? GridSheetColumnType.text;

      String? editableExpression = '';
      if (actualName == 'BOOL7') {
        editableExpression = "NUMERIC3 < 90.5";
      }

      TextAlign alignment = TextAlign.left;
      if (type == GridSheetColumnType.double) {
        alignment = TextAlign.right;
      } else if (type == GridSheetColumnType.datetime) {
        noEditMode = true;
      }

      return GridSheetColumn(
        key: ValueKey<String>(key),
        title: column,
        name: actualName,
        type: type,
        width: maxWidth,
        visible: display,
        textAlign: alignment,
        frozen: index < frozenColumnCount,
        editable: isEditable,
        conditionalEditExpression: editableExpression,
        index: index,
        resize: true,
        sortable: true,
        noTextControllerWidget: noEditMode,
      );
    }).toList();
  }

  List<GridSheetRow> _getRows({double rowHeight = 30.0}) {
    return rows.asMap().entries.map((e) {
      final index = e.key;
      final rowData = e.value;
      final key = '${GridSheetConstants.rowKeyStartsWith}$index';

      final row = GridSheetRow(
        key: ValueKey<String>(key),
        index: index,
        data: rowData,
        height: rowHeight,
      );

      return row;
    }).toList();
  }

  List<GridSheetConditionalFormatRule> getFormattingRules() {
    return [
      GridSheetConditionalFormatRule(
        name: 'STRING2',
        expression: "NUMERIC3 > 90",
        scope: GridSheetFormatScope.row,
        backgroundColor: Colors.red,
      ),
      GridSheetConditionalFormatRule(
        name: 'BOOL4',
        expression: "BOOL7 == false",
        scope: GridSheetFormatScope.column,
        backgroundColor: Colors.green,
      ),
      GridSheetConditionalFormatRule(
        name: 'NUMERIC3',
        expression: "BOOL4 == true",
        scope: GridSheetFormatScope.cell,
        backgroundColor: Colors.orange,
      ),
    ];
  }

  Widget get loadingWidget {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          CircularProgressIndicator(),
          SizedBox(height: 16),
          Text(
            'Processing...',
            style: TextStyle(color: Colors.white, fontSize: 16),
          ),
        ],
      ),
    );
  }
}
1
likes
160
points
489
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter DataGrid/DataTable with minimal configuration and powerful features like filtering, formulas, pagination, editing, frozen columns, CRUD, and full customization.

Homepage
View/report issues

Topics

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

Documentation

API reference

License

MIT (license)

Dependencies

cupertino_icons, expressions, flutter

More

Packages that depend on grid_sheet