diff --git a/lib/src/workbook_json.dart b/lib/src/workbook_json.dart new file mode 100644 index 0000000..a017f04 --- /dev/null +++ b/lib/src/workbook_json.dart @@ -0,0 +1,77 @@ +import 'dart:convert'; + +import 'address.dart'; +import 'format.dart'; +import 'names.dart'; +import 'workbook.dart'; + +const int workbookJsonVersion = 1; + +String encodeWorkbookJson(Workbook workbook) { + final sheets = >[]; + for (final sheet in workbook.sheets) { + final cells = {}; + final formats = {}; + for (final entry in sheet.cells.entries) { + final cell = entry.value; + if (cell.isOccupied) cells[entry.key.label] = cell.raw; + final format = cell.format; + if (format != null) formats[entry.key.label] = format.toCode(); + } + sheets.add({ + 'name': sheet.name, + 'cells': cells, + if (formats.isNotEmpty) 'formats': formats, + }); + } + + final names = {}; + for (final entry in workbook.definedNames) { + names[entry.key] = _referenceText(entry.value); + } + + final document = { + 'version': workbookJsonVersion, + 'sheets': sheets, + if (names.isNotEmpty) 'names': names, + }; + return const JsonEncoder.withIndent(' ').convert(document); +} + +Workbook decodeWorkbookJson(String source) { + final document = jsonDecode(source) as Map; + final workbook = Workbook(); + final sheetsJson = (document['sheets'] as List).cast>(); + for (final sheetJson in sheetsJson) { + final sheet = workbook.addSheet(sheetJson['name'] as String); + final cells = (sheetJson['cells'] as Map).cast(); + for (final entry in cells.entries) { + sheet.setCell(CellAddress.parse(entry.key), entry.value as String, recalculate: false); + } + final formats = sheetJson['formats'] as Map?; + if (formats != null) { + for (final entry in formats.cast().entries) { + sheet.setFormatAt(CellAddress.parse(entry.key), NumberFormat.fromCode(entry.value as String)); + } + } + } + + final names = document['names'] as Map?; + if (names != null) { + for (final entry in names.cast().entries) { + workbook.defineName(entry.key, entry.value as String); + } + } + + workbook.recalculate(); + return workbook; +} + +String _referenceText(NameTarget target) { + switch (target) { + case CellName(:final sheet, :final address): + return "'${sheet.name}'!${address.label}"; + case RangeName(:final sheet, :final start, :final end): + return "'${sheet.name}'!${start.label}:${end.label}"; + } +}