Flutter读取Excel时如何避免数据被覆盖?
Flutter Excel读取时数据被覆盖的解决方案
你猜的完全正确!问题根源就是对象引用复用——你的standValues是定义在函数外部的全局Map,所有店铺条目都共享同一个Map实例。每次处理新行时,你只是在修改这个全局Map的内容,之前添加到startingStock里的所有店铺对象其实都指向同一个standValues,最后自然全部被最后一行的数据覆盖了。
接下来给你分步解决这个问题:
核心修改点
- 将
standValues移到循环内部,每次处理新店铺时创建新Map
这样每个店铺都会拥有独立的Map实例,互相之间不会干扰。 - 修正店铺存在性的判断逻辑
原来的startingStock[tourNumber].contains(standName)是错误的,因为startingStock[tourNumber]里存储的是{standName: ...}这样的Map对象,直接用字符串匹配永远找不到,需要遍历检查每个Map的键是否包含目标店铺名。 - 调整代码执行顺序
先填充当前店铺的产品数据,再判断是否要添加到startingStock,避免先添加空Map再修改导致的引用问题。
修改后的完整代码
List<dynamic> products = []; List<dynamic> prices = []; Map<String, dynamic> startingStock = {}; Future<void> _readExcel() async { try { var bytes = _tempFile.readAsBytesSync(); var excel = Excel.decodeBytes(bytes); for (var table in excel.tables.keys) { int maxCols = excel.tables[table].maxCols; // 第一步:先读取产品名称和价格 for (var row in excel.tables[table].rows) { if (row[2] == 'Produkt') { row.removeWhere( (product) => product == null || product == 'Produkt'); products = row; } if (row[2] == 'Preis') { row.removeWhere((price) => price == null || price == 'Stand' || price == 'Preis'); prices = row; } } // 第二步:处理每个店铺的库存数据 for (var row in excel.tables[table].rows) { if (row[0] != 'TP-Master' && row[0] != null && row[1] != null) { var tourNumber = row[0].toString(); var standName = row[1].toString(); // 1. 每次处理新店铺时,创建新的standValues Map Map<String, dynamic> standValues = {}; // 2. 填充当前店铺的产品数据 for (var productsPricesStock in zip([ products, prices, row.sublist(3, maxCols), ])) { standValues[productsPricesStock[0].toString()] = { 'name': productsPricesStock[0].toString(), 'price': productsPricesStock[1].toString(), 'stock': productsPricesStock[2].toString(), }; } // 3. 初始化tour对应的列表(如果不存在) if (!startingStock.containsKey(tourNumber)) { startingStock[tourNumber] = []; } // 4. 检查当前tour下是否已存在该店铺 bool standExists = startingStock[tourNumber].any((item) => item.containsKey(standName)); // 5. 如果不存在,添加新的店铺条目 if (!standExists) { Map<String, dynamic> standObject = {standName: standValues}; startingStock[tourNumber].add(standObject); } } } } successSnackBar('Die Datei wurde erfolgreich gelesen!'); } catch (err) { print(err); errorSnackBar('Beim lesen der Datei ist ein Fehler aufgetreten!'); } }
关键逻辑说明
- 每次处理一行店铺数据时,都创建全新的
standValues,确保每个店铺的数据都存储在独立的Map中。 - 使用
any()方法遍历startingStock[tourNumber]中的元素,检查是否已有包含目标店铺名的Map,修正了原来错误的判断逻辑。 - 先填充
standValues再添加到startingStock,避免了空Map被后续修改的问题。
这样修改后,每个店铺的产品数据都会独立存储,不会再被后续行的数据覆盖了,应该就能得到你期望的数据结构啦!
内容的提问来源于stack exchange,提问作者Darjusch
相关产品推荐
相关产品推荐

