excel_plus v2.14.3
pub.dev GitHub

Reading legacy .xls files

Open binary Excel 97-2003 workbooks and convert them to the modern format.

Install#

dart pub add excel_plus
import 'package:excel_plus/excel_plus.dart';

The same call as .xlsx#

Excel.decodeBytes looks at the bytes and picks the right parser, so a legacy workbook opens through exactly the same call, with no extra dependency and no separate API.

final excel = Excel.decodeBytes(File('legacy.xls').readAsBytesSync());

print(excel.tables.keys);

What is carried over#

  • Cell values of every type
  • Dates, in both the 1900 and 1904 epochs
  • Merged cells, sheet order and sheet visibility
  • Number formats, fonts, fills, borders and alignment
  • Column widths and row heights
  • Formulas, decoded from the binary token stream back into formula text, including shared and array formulas, keeping the last calculated result as the cached value

Where the decoder meets a token stream it does not model, it falls back to the cached result rather than failing the file.

Converting to .xlsx#

Reading .xls is deliberately read only. Saving always produces a modern .xlsx, which makes this the migration path for a pile of old spreadsheets.

final excel = Excel.decodeBytes(File('legacy.xls').readAsBytesSync());
File('modern.xlsx').writeAsBytesSync(excel.save()!);

Converting a folder of them#

import 'dart:io';
import 'package:excel_plus/excel_plus.dart';

void main() {
  for (final file in Directory('old').listSync().whereType<File>()) {
    if (!file.path.toLowerCase().endsWith('.xls')) continue;

    final excel = Excel.decodeBytes(file.readAsBytesSync());
    final target = file.path.replaceAll(RegExp(r'\.xls$', caseSensitive: false), '.xlsx');
    File(target).writeAsBytesSync(excel.save()!);
  }
}

Files that will not open#

Password protected workbooks and pre-BIFF8 files (Excel 5.0 and earlier) throw a clear error rather than returning something half parsed. If a file fails, checking whether it opens in a spreadsheet program is usually the fastest way to tell a genuinely corrupt file from an unsupported one.