You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter读取Excel时如何避免数据被覆盖?

Flutter Excel读取时数据被覆盖的解决方案

你猜的完全正确!问题根源就是对象引用复用——你的standValues是定义在函数外部的全局Map,所有店铺条目都共享同一个Map实例。每次处理新行时,你只是在修改这个全局Map的内容,之前添加到startingStock里的所有店铺对象其实都指向同一个standValues,最后自然全部被最后一行的数据覆盖了。

接下来给你分步解决这个问题:

核心修改点

  1. 将standValues移到循环内部,每次处理新店铺时创建新Map
    这样每个店铺都会拥有独立的Map实例,互相之间不会干扰。
  2. 修正店铺存在性的判断逻辑
    原来的startingStock[tourNumber].contains(standName)是错误的,因为startingStock[tourNumber]里存储的是{standName: ...}这样的Map对象,直接用字符串匹配永远找不到,需要遍历检查每个Map的键是否包含目标店铺名。
  3. 调整代码执行顺序
    先填充当前店铺的产品数据,再判断是否要添加到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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 22:17:49