streamRows method
Reads sheetName row by row without building the sheet's cell grid.
The eager path (excel['Sheet1'].rows) materialises every cell of a
worksheet as a Data object in a sparse map, then flattens that into a
dense list. For a large file that costs many times the size of the file
itself. This reads the worksheet part straight out of the archive and
yields one row at a time, so peak memory is the worksheet XML plus a
single row rather than the whole grid.
The iterable is lazy: nothing is parsed until it is walked, and breaking out stops the parse there. That makes it the right tool for validating a bulk upload, where you want to reject on the first bad row rather than read the whole file first.
for (final row in excel.streamRows('Sheet1')) {
process(row);
}
Rows arrive in the order the file stores them, and a row the file omits entirely is skipped rather than yielded as blanks, so this is not a substitute for indexing when you need absolute row numbers. Trailing empty cells are trimmed. Values are typed exactly as the eager reader types them, including shared strings, dates and cached formula results, but styles, merges and row metadata are not read: use the eager path when you need those.
Throws ArgumentError when sheetName is not in the workbook.
Implementation
Iterable<List<CellValue?>> streamRows(String sheetName) sync* {
if (!_sheetMap.containsKey(sheetName) &&
!_pendingSheetNodes.containsKey(sheetName)) {
throw ArgumentError.value(sheetName, 'sheetName', 'no such sheet');
}
final path = _worksheetPartPath(sheetName);
if (path == null) return;
final file = _archive.findFile(path);
if (file == null) return;
file.decompress();
final xmlStr = utf8.decode(file.content);
final start = xmlStr.indexOf('<sheetData');
if (start == -1) return;
final openEnd = xmlStr.indexOf('>', start);
if (openEnd == -1) return;
// <sheetData/> carries no rows at all.
if (xmlStr[openEnd - 1] == '/') return;
final end = xmlStr.indexOf('</sheetData>', openEnd);
if (end == -1) return;
yield* _streamSheetData(xmlStr.substring(openEnd + 1, end));
}