如何在Flutter Windows中从桌面上传Excel(xls)并保存至SQLite数据库
在Flutter Windows中实现Excel(xls)上传并保存到SQLite数据库
1. 添加必要依赖
在pubspec.yaml中引入三个核心依赖:文件选择工具、Excel解析库、Windows兼容的SQLite库:
dependencies: file_selector_windows: ^0.9.2 excel: ^4.0.1 sqflite_common_ffi: ^2.3.2
执行flutter pub get完成依赖安装。
2. 实现文件选择功能
编写方法打开Windows文件选择器,仅允许选择.xls格式文件:
import 'package:file_selector_windows/file_selector_windows.dart'; Future<String?> selectExcelFile() async { const XTypeGroup excelType = XTypeGroup( label: 'Excel文件', extensions: ['xls'], ); final XFile? selectedFile = await openFile(acceptedTypeGroups: [excelType]); return selectedFile?.path; }
3. 解析Excel文件内容
读取选中的xls文件,解析为符合数据库表结构的数据集(假设Excel第一行为表头,数据从第二行开始,列顺序为:产品名、售价、成本价、数量):
import 'dart:io'; import 'package:excel/excel.dart'; Future<List<Map<String, dynamic>>> parseExcel(String filePath) async { final List<Map<String, dynamic>> productList = []; final fileBytes = File(filePath).readAsBytesSync(); final excel = Excel.decodeBytes(fileBytes); // 遍历第一个工作表的数据行 for (final table in excel.tables.values) { for (int rowIndex = 1; rowIndex < table.maxRows; rowIndex++) { final row = table.rows[rowIndex]; if (row == null || row.any((cell) => cell == null)) continue; // 跳过空行或数据不全的行 productList.add({ 'product_name': row[0]?.value?.toString() ?? '', 'product_price': double.tryParse(row[1]?.value?.toString() ?? '0') ?? 0.0, 'price_cost': double.tryParse(row[2]?.value?.toString() ?? '0') ?? 0.0, 'product_quantity': int.tryParse(row[3]?.value?.toString() ?? '0') ?? 0, }); } } return productList; }
4. SQLite数据库操作
初始化数据库,并实现批量插入数据的方法:
import 'package:sqflite_common_ffi/sqflite_ffi.dart'; // 初始化Windows兼容的SQLite数据库 Future<Database> initDatabase() async { sqfliteFfiInit(); databaseFactory = databaseFactoryFfi; return await openDatabase( 'products.db', version: 1, onCreate: (db, version) async { await db.execute(''' CREATE TABLE "products" ( "product_id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "product_name" TEXT NOT NULL, "product_price" REAL NOT NULL, "price_cost" REAL NOT NULL, "product_quantity" INTEGER ) '''); }, ); } // 批量插入解析后的产品数据 Future<void> batchInsertProducts(List<Map<String, dynamic>> products) async { final db = await initDatabase(); await db.transaction((txn) async { for (final product in products) { await txn.insert( 'products', product, conflictAlgorithm: ConflictAlgorithm.replace, // 重复数据时替换,可按需调整 ); } }); }
5. 整合完整流程
将上述功能整合到UI按钮的点击事件中,完成从选文件到导入数据库的全流程:
import 'package:flutter/material.dart'; // 在页面中添加导入按钮 ElevatedButton( onPressed: () async { // 1. 选择Excel文件 final String? filePath = await selectExcelFile(); if (filePath == null) return; // 2. 解析文件内容 final productData = await parseExcel(filePath); if (productData.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Excel中无有效数据')), ); return; } // 3. 插入数据库 try { await batchInsertProducts(productData); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('数据导入成功')), ); } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('导入失败: ${e.toString()}')), ); } }, child: const Text('选择并导入Excel'), )
注意事项
- 需确保Excel文件的列顺序与解析代码中的索引对应,若列顺序不同,需调整
row[0]、row[1]等的索引值。 - 解析时加入了格式容错处理,避免因Excel中数据格式错误导致崩溃,可根据实际需求优化校验逻辑。
- 打包Windows应用时,需确保程序拥有读取本地文件的权限,桌面应用默认具备该权限。
内容的提问来源于stack exchange,提问作者abderaouf mansouri
相关产品推荐
相关产品推荐

