Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading some excels with multiple sheets yields null check on null issue. #384

Open
kuoaid opened this issue Nov 6, 2024 · 1 comment
Open

Comments

@kuoaid
Copy link

kuoaid commented Nov 6, 2024

Platform: iOS

Issue: On select files with multiple sheets, the package's code throws a null check on null error.

Steps to reproduce:

  1. Load the file (file_picker) like this, and initialize excel:
  Future<void> pickFile() async {
    bool _fileSuccess = await _fileUploadService.pickFile();
    if (_fileSuccess && _fileUploadService.pickedFile != null) {
      sheetsService = BatchSheetsService(
          car: car, pickedFile: _fileUploadService.pickedFile!);
      sheetsService?.initialize().whenComplete(() {
        matchingServices.initialize(sheetsService!.columns);
        notifyListeners();
      });
    } else {
      devLog("Error: No file was picked or the file pick failed.");
    }
  }
  ///initialize the service
  Future<void> initialize() async {
    await _loadExcelFile(pickedFile);
    fileLoaded = true;
  }

  Future<void> _loadExcelFile(PlatformFile file) async {
    // try {
    devLog("Loading Excel file: ${file.name}");
    var fileBytes = File(file.path!).readAsBytesSync();
    devLog("File bytes: ${fileBytes.length}");
    // If bytes are available, use them
      if (file.bytes != null) {
        devLog("File bytes available.");
      } else if (file.path != null) {
        devLog("File path available: ${file.path}");
        // If bytes are not available, read the file from the path
        File localFile = File(file.path!);
        devLog("Local file: $localFile");
        fileBytes = localFile.readAsBytesSync();
        devLog("File bytes: ${fileBytes.length}");
      } else {
        // If neither bytes nor path are available, throw an error
        throw Exception("No file content available to read.");
      }

      _excel = Excel.decodeBytes(fileBytes);
      devLog("Excel file decoded.");

      if (_excel == null) {
        print("Error: Excel file could not be decoded.");
        return;
      }

      if (_excel!.tables.isEmpty) {
        print("Error: No tables (sheets) found in the Excel file.");
        return;
      }

      selectedSheet = _excel!.tables.keys.first;
      _loadColumns();
      fileLoaded = true;
    // } catch (e) {
    //   print("Error loading Excel file: $e");
    // }
  }
  1. Load the file test_excel_file (test_excel_file.xlsx). It has 2 sheets. You will get:
[log] Loading Excel file: test_excel_file.xlsx
[log] File bytes: 5731
[log] File path available: /private/var/mobile/Containers/Data/Application/BBE734D1-BAB6-43DE-BCA6-D27E8C7F36E4/tmp/test_excel_file.xlsx
[log] Local file: File: '/private/var/mobile/Containers/Data/Application/BBE734D1-BAB6-43DE-BCA6-D27E8C7F36E4/tmp/test_excel_file.xlsx'
[log] File bytes: 5731
[log] Matches initialized: []
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Null check operator used on a null value
#0      Parser._parseTable (package:excel/src/parser/parse.dart:540:9)
#1      Parser._parseContent.<anonymous closure> (package:excel/src/parser/parse.dart:156:9)
#2      Iterable.forEach (dart:core/iterable.dart:347:35)
#3      Parser._parseContent (package:excel/src/parser/parse.dart:154:39)
#4      Parser._startParsing (package:excel/src/parser/parse.dart:15:5)
#5      new Excel._ (package:excel/src/excel.dart:63:12)
#6      _newExcel (package:excel/src/excel.dart:17:20)
#7      new Excel.decodeBytes (package:excel/src/excel.dart:78:12)
#8      BatchSheetsService._loadExcelFile (package:***********************batch_upload_sheets_service.dart:52:22)
#9      BatchSheetsService.initialize (package:***********************batch_upload_sheets_service.dart:28:11)
#10     BatchAddBackend.pickFile (package:***********************main_backend.dart:90:22)
<asynchronous suspension>
<asynchronous suspension>

This points to issues with these lines' null check:

    var file = _excel._archive.findFile('xl/$target');
    file!.decompress();
  1. However, loading test_excel_file_single (test_excel_file_single.xlsx), which has only one sheet, yields no issue. It still uses the paths to locate the file, as before. If file_picker is specified to include data, the uint8list is used but the overall behavior does not change.

  2. Loading this file - car_service_mods_worksheet 3.xlsx, which has 2 sheets, has no issues. It still uses paths.
    car_service_mods_worksheet 3.xlsx

Please respond with any insights! Thanks in advance.

@kuoaid
Copy link
Author

kuoaid commented Nov 6, 2024

Update - a workaround is to use another package such as spreadsheet_decoder in case of excel package errors. I can decode the excel sheet normally with the other package, extract the data, and reconstruct the Excel object so the rest of my project does not require migration.

Still curious though what causes this bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant