excel_plus 1.0.0
excel_plus: ^1.0.0 copied to clipboard
Fast, low-memory Excel (.xlsx) library for Dart and Flutter to read, create, edit, and style spreadsheets. A drop-in replacement for the excel package.
Excel (.xlsx) Library for Dart & Flutter #
excel_plus is a fast, low-memory, non-UI Dart library for creating, reading,
editing, and styling Microsoft Excel .xlsx spreadsheets. It works in plain
Dart and in Flutter apps, on the VM, Web (JS & WASM), and mobile. excel_plus is a
source-compatible drop-in replacement for the excel
package — change one import and your existing code keeps working, with better
performance on large workbooks.
Overview #
excel_plus reads and writes the Office Open XML .xlsx format used by Microsoft
Excel, Google Sheets, and LibreOffice Calc. It parses workbooks with a streaming
(SAX) reader and loads each sheet lazily, so memory stays low even on large files,
and it reuses untouched parts of a workbook byte-for-byte when saving.
What you can do with it:
- Read and parse existing
.xlsxfiles, or create new Excel workbooks from scratch. - Edit cells, rows, columns, and multiple sheets, then save back to
.xlsx. - Style spreadsheets — fonts, colors, fills, borders, alignment, number formats, and merged cells.
Performance #
excel_plus is built for large workbooks: a streaming SAX parser instead of full-DOM parsing, lazy per-sheet loading, O(1) reverse indexes for styles and shared strings, and byte-for-byte reuse of untouched workbook parts on save.
It comfortably handles workbooks with millions of cells. Here is a head-to-head
against the original excel package — same machine,
same workload:
| Workload | Encode (excel → excel_plus) |
Decode | Peak memory | Create |
|---|---|---|---|---|
| 5,000,000 cells | 48.8 s → 9.2 s · 5.3× | 56.8 s → 19.5 s · 2.9× | 12.0 GB → 2.6 GB · 4.6× | ≈ equal |
| 1,000,000 cells | 9.4 s → 1.6 s · 5.8× | 10.9 s → 3.7 s · 3.0× | 2.5 GB → 0.7 GB · 3.5× | ≈ equal |
| 10,000 cells | 184 ms → 41 ms · 4.5× | 141 ms → 75 ms · 1.9× | ≈ equal* | ≈ equal |
| 500 cells | 54 ms → 16 ms · 3.3× | 32 ms → 19 ms · 1.7× | ≈ equal* | ≈ equal |
* Below ~100k cells peak memory is dominated by the Dart VM baseline (~250 MB), so
it is comparable; the gap widens with size (3.5× at 1M → 4.6× at 5M, where excel
needed ~12 GB RAM). Create time is within noise — both build cells the same way.
The two libraries pin conflicting archive/xml majors, so they can't run in one
program; each harness lives in its own package under
benchmark/compare/.
Timings vary by hardware — reproduce both on your own machine:
cd benchmark/compare/excel_baseline && dart pub get && dart run bin/benchmark.dart
cd ../excel_plus_bench && dart pub get && dart run bin/benchmark.dart
Table of contents #
- Excel (.xlsx) Library for Dart & Flutter
- Overview
- Performance
- Table of contents
- Key features
- Limitations
- Roadmap
- Example
- Other useful links
- Installation
- Getting started
- Create a simple Excel document
- Add text, number, boolean, and date values
- Add formulas
- Read an existing Excel file
- Read a single cell
- Style a cell — font, color, fill, alignment
- Add borders
- Apply number formats
- Merge and unmerge cells
- Insert and delete rows and columns
- Append a row
- Column width, row height, and auto-fit
- Work with multiple sheets
- Find and replace
- Save the workbook
- Flutter — read from assets, edit, and save
- excel_plus vs excel
- Migrating from the excel package
- FAQ
- Support and feedback
- About
Key features #
- Read & write
.xlsxfiles from bytes. - Create new Excel workbooks from scratch.
- Multiple sheets — create, copy, rename, delete, reorder, tab colour, hide.
- All cell types — text, int, double, bool, date, time, date-time, formula,
and typed error values (
#DIV/0!,#N/A, …). - Cell styling — fonts, colors, fills, borders, alignment, rotation, indent.
- Number formats — built-in and custom format codes.
- Worksheet features — hyperlinks, data validation / dropdowns, conditional formatting (colour scales, data bars, cellIs/formula), freeze panes, autofilter, sheet protection, defined names / named ranges, gridlines & zoom.
- Rich text — read and write (per-run bold/italic/colour/size/font).
- Theme & indexed colours — read (resolved to RGB) and authored
(
ExcelColor.theme(ThemeColor.accent1, tint: x)/ExcelColor.indexed(n)), staying linked to the document theme. - Merge & unmerge cells with custom values.
- Rows & columns — insert, remove, clear, resize.
- Column width / row height with auto-fit.
- Find and replace across cells and sheets.
- Cross-platform — VM, Web (JS & WASM), Android, iOS, Windows, macOS, Linux.
- Source-compatible drop-in for the
excelpackage.
Limitations #
excel_plus focuses on fast, correct cell data and styling I/O. The following are not supported yet — if you need one, please open an issue so it can be prioritised:
- Formula evaluation — formula cells round-trip with their cached result; Excel recomputes when the file is opened. excel_plus stores and preserves formulas but does not evaluate them itself.
- Objects & media — images, charts, comments / notes, pivot tables.
- Split panes — freeze panes are supported; twip-based split panes are not.
Anything not in this list — reading, creating, editing and styling cells across multiple sheets — is supported; see Key features.
Roadmap #
excel_plus is actively developed toward broader Excel / Google-Sheets parity. 1.0.0 landed the high-impact worksheet feature set (hyperlinks, data validation, conditional formatting, freeze panes, autofilter, sheet protection, named ranges, rich-text write, error values, theme/indexed colour authoring). Next up (subject to change): images and comments, then a formula-evaluation engine. Shipped changes are tracked in the changelog, and the direction is driven by what users request on the issue tracker.
Example #
▶ Try the live demo — build, style and export real
.xlsxfiles right in your browser. No install needed.
A complete, runnable sample lives in the
example/ directory.
Clone the repository and run it, or copy any snippet from
Getting started below.
Other useful links #
Installation #
dart pub add excel_plus
# or, in a Flutter app:
flutter pub add excel_plus
Then import it:
import 'package:excel_plus/excel_plus.dart';
Getting started #
Create a simple Excel document #
final excel = Excel.createExcel(); // a new workbook with one default sheet
final sheet = excel['Sheet1'];
sheet.updateCell(CellIndex.indexByString('A1'), TextCellValue('Hello, world!'));
final bytes = excel.save(); // List<int> of the .xlsx file
Add text, number, boolean, and date values #
sheet.updateCell(CellIndex.indexByString('A1'), TextCellValue('Name'));
sheet.updateCell(CellIndex.indexByString('B1'), IntCellValue(42));
sheet.updateCell(CellIndex.indexByString('C1'), DoubleCellValue(3.14));
sheet.updateCell(CellIndex.indexByString('D1'), BoolCellValue(true));
sheet.updateCell(CellIndex.indexByString('E1'), DateCellValue(year: 2026, month: 6, day: 9));
sheet.updateCell(CellIndex.indexByString('F1'), TimeCellValue(hour: 9, minute: 30, second: 0));
sheet.updateCell(
CellIndex.indexByString('G1'),
DateTimeCellValue(year: 2026, month: 6, day: 9, hour: 9, minute: 30),
);
Add formulas #
Formulas are stored and round-tripped as text; Excel (or Sheets/Calc) computes the result when the file is opened — excel_plus does not evaluate them itself.
sheet.updateCell(CellIndex.indexByString('A1'), IntCellValue(10));
sheet.updateCell(CellIndex.indexByString('A2'), IntCellValue(20));
sheet.updateCell(CellIndex.indexByString('A3'), FormulaCellValue('SUM(A1:A2)'));
// ...or set a formula on an existing cell:
sheet.cell(CellIndex.indexByString('A4')).setFormula('AVERAGE(A1:A2)');
Read an existing Excel file #
import 'dart:io';
final bytes = File('input.xlsx').readAsBytesSync();
final excel = Excel.decodeBytes(bytes);
for (final sheetName in excel.tables.keys) {
for (final row in excel[sheetName].rows) {
print(row.map((cell) => cell?.value).toList());
}
}
Read a single cell #
final cell = excel['Sheet1'].cell(CellIndex.indexByString('B2'));
print(cell.value); // a typed CellValue: TextCellValue, IntCellValue, ...
Style a cell — font, color, fill, alignment #
sheet.updateCell(
CellIndex.indexByString('A1'),
TextCellValue('Header'),
cellStyle: CellStyle(
bold: true,
italic: true,
fontSize: 14,
fontColorHex: ExcelColor.white,
backgroundColorHex: ExcelColor.fromHexString('#21A366'),
horizontalAlign: HorizontalAlign.Center,
verticalAlign: VerticalAlign.Center,
),
);
Add borders #
sheet.cell(CellIndex.indexByString('A1')).cellStyle = CellStyle(
leftBorder: Border(borderStyle: BorderStyle.Thin),
rightBorder: Border(borderStyle: BorderStyle.Thin),
topBorder: Border(borderStyle: BorderStyle.Medium),
bottomBorder: Border(borderStyle: BorderStyle.Medium, borderColorHex: ExcelColor.red),
);
Apply number formats #
// Currency with a thousands separator (custom format code).
sheet.updateCell(
CellIndex.indexByString('A1'),
DoubleCellValue(12500.5),
cellStyle: CellStyle(numberFormat: NumFormat.custom(formatCode: r'$#,##0.00')),
);
// Percentage (built-in format).
sheet.updateCell(
CellIndex.indexByString('A2'),
DoubleCellValue(0.125),
cellStyle: CellStyle(numberFormat: NumFormat.standard_10), // 0.00%
);
Merge and unmerge cells #
sheet.merge(
CellIndex.indexByString('A1'),
CellIndex.indexByString('D1'),
customValue: TextCellValue('Merged title'),
);
sheet.unMerge('A1:D1');
Insert and delete rows and columns #
sheet.insertRow(2); // insert a blank row at index 2
sheet.removeRow(5); // delete row 5
sheet.insertColumn(1); // insert a blank column at index 1
sheet.removeColumn(3); // delete column 3
Append a row #
sheet.appendRow([
TextCellValue('Alice'),
IntCellValue(30),
DoubleCellValue(12500.0),
]);
Column width, row height, and auto-fit #
sheet.setColumnWidth(0, 24.0);
sheet.setRowHeight(0, 32.0);
sheet.setColumnAutoFit(1);
Work with multiple sheets #
final excel = Excel.createExcel();
excel['Sales'].updateCell(CellIndex.indexByString('A1'), TextCellValue('Q1'));
excel['Inventory'].updateCell(CellIndex.indexByString('A1'), TextCellValue('SKU'));
excel.rename('Sales', 'Revenue');
excel.copy('Revenue', 'Revenue (Backup)');
excel.delete('Inventory');
excel.setDefaultSheet('Revenue');
Find and replace #
// Within one sheet — returns the number of replacements made.
final count = excel['Sheet1'].findAndReplace('draft', 'final');
// Across a named sheet via the workbook.
excel.findAndReplace('Sheet1', 'old', 'new');
Save the workbook #
// 1) As bytes.
final List<int>? bytes = excel.save();
// 2) To a file (Dart VM / desktop / mobile).
import 'dart:io';
File('output.xlsx').writeAsBytesSync(excel.save()!);
// 3) Trigger a browser download on Flutter Web.
excel.save(fileName: 'report.xlsx');
Flutter — read from assets, edit, and save #
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
final data = await rootBundle.load('assets/template.xlsx');
final excel = Excel.decodeBytes(data.buffer.asUint8List());
excel['Sheet1'].updateCell(CellIndex.indexByString('A1'), TextCellValue('Updated'));
final dir = await getApplicationDocumentsDirectory();
File('${dir.path}/output.xlsx').writeAsBytesSync(excel.save()!);
excel_plus vs excel #
excel_plus is a performance-focused fork of the
excel package that keeps the same public API.
| excel_plus | excel | |
|---|---|---|
| XML parsing | Streaming SAX (parseEvents) |
Full-DOM (standard) |
| Sheet loading | Lazy, per sheet on first access | Eager |
| Large-file memory | Low — untouched parts reused byte-for-byte on save | Higher |
| Public API | Source-compatible drop-in | — (the original) |
| Platforms | VM, Web (JS & WASM), Android, iOS, desktop | VM, Web, mobile |
On a 1,000,000-cell sheet this measured ~5× faster encoding, ~3× faster decoding, and ~3.5× less peak memory — see Performance for the reproducible head-to-head.
Live pub score and likes are shown in the badges at the top.
Migrating from the excel package #
// Before
import 'package:excel/excel.dart';
// After
import 'package:excel_plus/excel_plus.dart';
No other code changes needed for typical usage — excel_plus mirrors the excel
package's public API.
FAQ #
Is excel_plus a drop-in replacement for the excel package?
Yes. The classes, methods, and enums match the excel package — change the import
to package:excel_plus/excel_plus.dart and your existing code keeps working.
Which platforms are supported?
Dart VM, Web (both JavaScript and WebAssembly), and mobile (Android & iOS) via
Flutter, as well as desktop. It is a pure-Dart package with no dart:io in the
public path.
Can it read and write large .xlsx files efficiently?
Yes — sheets are parsed with a streaming SAX reader and loaded lazily, and
untouched parts of the workbook are reused byte-for-byte on save, keeping memory low.
Does it support formulas, styling, and merged cells? Yes — formula cells, full cell styling (fonts, colors, fills, borders, alignment, number formats), and merging/unmerging with custom values are all supported.
Is it Flutter-only? No. excel_plus is a pure Dart library; it works in plain Dart and in Flutter apps alike.
Support and feedback #
- Found a bug or want a feature? Open an issue on the issue tracker.
- Questions and ideas are welcome via GitHub Discussions.
- Pull requests are welcome — see the repository for contribution guidelines.
About #
excel_plus is an open-source, MIT-licensed, performance-focused fork of the
excel package, rebuilt around a streaming
parser and lazy loading for speed and low memory on large .xlsx files while
staying API-compatible.
excel_plus is created and owned by Nurullah Al Masum.
Contributors #
excel_plus grows with its community — every contributor is listed here:
Want to help? Pull requests are welcome — see Support and feedback.
If excel_plus helps you, please ⭐ the repository and 👍 it on pub.dev — it genuinely helps others find it.