Flutterexperts

Empowering Vision with FlutterExperts' Expertise
Exploring CSV In Flutter

CSV stands for Comma-Separated Values . It is a text editable file that contains text separated by commas in a series of lines called rows. CSV is used in share market, data analytics, and data visualization. The main difference between excel and CSV files is the excel file can be used to perform various data operations and data visualization can be done inside the excel file effectively.

In this blog, we shall explore how to work with CSV files in flutter.


We shall learn how to :

  • Create CSV file
  • Add data in CSV file
  • Fetch CSV file from phone storage
  • Save CSV file in phone storage

Package used :

CSV | Dart Package
Specify (at least a major) version when adding this project as dependency. Whenever the API has incompatible changes…pub.dev

path_provider | Flutter Package
A Flutter plugin for finding commonly used locations on the filesystem. Supports iOS, Android, Linux, and macOS. Not all…pub.dev

file_picker | Flutter Package
A package that allows you to use the native file explorer to pick single or multiple files, with extensions filtering…pub.dev

random_string | Dart Package
Simple library for generating random ascii strings. While this package provides random Between for convenience, as the…pub.dev

  • csv package is used to convert List data to CSV and CSV data to List.
  • path_provider is used to access the mobile directories on the filesystem.
  • file_picker is used to pick files from mobile storage.
  • random_string is used to generate random text and numeric string.

Convert List of String to CSV :

data is a List of List of strings. Now we will convert this list to a CSV file using ListToCsvConverter() that provide the use convert() method to convert data to CSV data. Get the path of the app of the application directory and create a new custom path to store all our CSV files.

final String directory = (await getApplicationSupportDirectory()).path;
final path = "$directory/csv-${DateTime.now()}.csv";

To store all the CSV data inside a file, we need to create a file on the specified path. and then write CSV data using writeAsString method.

generateCsv() async {
List<List<String>> data = [
["No.", "Name", "Roll No."],
["1", randomAlpha(3), randomNumeric(3)],
["2", randomAlpha(3), randomNumeric(3)],
["3", randomAlpha(3), randomNumeric(3)]
];
String csvData = ListToCsvConverter().convert(data);
final String directory = (await getApplicationSupportDirectory()).path;
final path = "$directory/csv-${DateTime.now()}.csv";
print(path);
final File file = File(path);
await file.writeAsString(csvData);
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) {
return LoadCsvDataScreen(path: path);
},
),
);
}

After storing CSV file in phone storage navigate to LoadCsvDataScreen to display CSV data.

Getting CSV from storage :

FilePicker is used to pick files from the storage. FilePickerResult gives us all the files chosen by the user. allowedExtensions method allows only ‘csv’ extension files. Then we will store the file path in the path variable. Finally, navigate it to LoadCsvDataScreen.

loadCsvFromStorage() async {
FilePickerResult result = await FilePicker.platform.pickFiles(
allowedExtensions: ['csv'],
type: FileType.custom,
);
String path = result.files.first.path;
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) {
return LoadCsvDataScreen(path: path);
},
),
);
}

Fetching CSV file from the phone storage :

To fetch all the CSV files we need to get the directory path

final String directory = (await getApplicationSupportDirectory()).path;
final path = "$directory/";

After getting into the directory we need to sync all the entity with a list of FileSystemEntity .

Future<List<FileSystemEntity>> _getAllCsvFiles() async {
final String directory = (await getApplicationSupportDirectory()).path;
final path = "$directory/";
final myDir = Directory(path);
List<FileSystemEntity> _csvFiles;
_csvFiles = myDir.listSync(recursive: true, followLinks: false);
_csvFiles.sort((a, b) {
return b.path.compareTo(a.path);
});
return _csvFiles;
}

Displaying CSV file :

To display the CSV data we need to convert CSV into a List using CsvToListConverter .

Future<List<List<dynamic>>> loadingCsvData(String path) async {
final csvFile = new File(path).openRead();
return await csvFile
.transform(utf8.decoder)
.transform(
CsvToListConverter(),
)
.toList();
}

Create a new dart file called loadCsvDataScreen.dart inside the lib folder:

This contains a widget that we use to display the CSV data. To fetch the data from the CSV file we need a future builder because the data that we will receive from CSV will not be changed after it is fetched. loadingCsvData returns a Future<List<List<dynamic>>> , this method opens the CSV file and convert the CSV data to String using CsvToListConverter . The future snapshot data is then mapped with a Row that will display the data stored in CSV file in rows else it will display the CircularProgressIndicator.

import 'dart:convert';
import 'dart:io';

import 'package:csv/csv.dart';
import 'package:flutter/material.dart';

class LoadCsvDataScreen extends StatelessWidget {
final String path;

LoadCsvDataScreen({this.path});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("CSV DATA"),
),
body: FutureBuilder(
future: loadingCsvData(path),
builder: (context, AsyncSnapshot<List<dynamic>> snapshot) {
print(snapshot.data.toString());
return snapshot.hasData
? Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: snapshot.data
.map(
(data) => Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
data[0].toString(),
),
Text(
data[1].toString(),
), Text(
data[2].toString(),
),
],
),
),
)
.toList(),
),
)
: Center(
child: CircularProgressIndicator(),
);
},
),
);
}

Future<List<List<dynamic>>> loadingCsvData(String path) async {
final csvFile = new File(path).openRead();
return await csvFile
.transform(utf8.decoder)
.transform(
CsvToListConverter(),
)
.toList();
}
}

Create a new dart file called allCsv.dart inside the lib folder:

It contains a widget to fetch all the files. Here we are fetching all the CSV files from our phone storage to our app. The list of CSV files from the mobile will be of FileSystemEntity type _getAllCsvFiles will return us a list of all FileSystemEntity as a Future. A list of all the CSV files will be displayed on the screen and on tapping them it will navigate us to LoadCsvDataScreen .

import 'package:flutter/material.dart';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'loadCsvDataScreen.dart';

class AllCsvFilesScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("All CSV Files")),
body: FutureBuilder(
future: _getAllCsvFiles(),
builder: (context, AsyncSnapshot<List<FileSystemEntity>> snapshot) {
if (!snapshot.hasData || snapshot.data.isEmpty) {
return Text("empty");
}
print('${snapshot.data.length} ${snapshot.data}');
if (snapshot.data.length == 0) {
return Center(
child: Text('No Csv File found.'),
);
}
return ListView.builder(
itemBuilder: (context, index) => Card(
child: ListTile(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) =>
LoadCsvDataScreen(path: snapshot.data[index].path),
),
);
},
title: Text(
snapshot.data[index].path.substring(44),
style: TextStyle(fontWeight: FontWeight.bold),
)),
),
itemCount: snapshot.data.length,
);
},
),
);
}

Future<List<FileSystemEntity>> _getAllCsvFiles() async {
final String directory = (await getApplicationSupportDirectory()).path;
final path = "$directory/";
final myDir = Directory(path);
List<FileSystemEntity> _csvFiles;
_csvFiles = myDir.listSync(recursive: true, followLinks: false);
_csvFiles.sort((a, b) {
return b.path.compareTo(a.path);
});
return _csvFiles;
}
}

main. dart:

In this file, we are generating and loading a CSV file from the phone storage.

import 'package:csv/csv.dart';
import 'package:flutter/material.dart';
import 'package:flutter_csv/allCsv.dart';
import 'package:flutter_csv/loadCsvDataScreen.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:random_string/random_string.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Csv Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Csv Demo'),
);
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MaterialButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => AllCsvFilesScreen()));
},
color: Colors.cyanAccent,
child: Text("Load all csv form phone storage"),
),
MaterialButton(
onPressed: () {
loadCsvFromStorage();
},
color: Colors.cyanAccent,
child: Text("Load csv form phone storage"),
),
MaterialButton(
onPressed: () {
generateCsv();
},
color: Colors.cyanAccent,
child: Text("Load Created csv"),
),
],
),
),
);
}

generateCsv() async {
List<List<String>> data = [
["No.", "Name", "Roll No."],
["1", randomAlpha(3), randomNumeric(3)],
["2", randomAlpha(3), randomNumeric(3)],
["3", randomAlpha(3), randomNumeric(3)]
];
String csvData = ListToCsvConverter().convert(data);
final String directory = (await getApplicationSupportDirectory()).path;
final path = "$directory/csv-${DateTime.now()}.csv";
print(path);
final File file = File(path);
await file.writeAsString(csvData);
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) {
return LoadCsvDataScreen(path: path);
},
),
);
}

loadCsvFromStorage() async {
FilePickerResult result = await FilePicker.platform.pickFiles(
allowedExtensions: ['csv'],
type: FileType.custom,
);
String path = result.files.first.path;
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) {
return LoadCsvDataScreen(path: path);
},
),
);
}
}

Github Link :

flutter-devs/flutter_csv
A new Flutter application. This project is a starting point for a Flutter application. A few resources to get you…github.com


Demo Module :


Thanks for reading this article ❤

If I got something wrong? Let me know in the comments. I would love to improve.

Clap 👏 If this article helps you.

If we got something wrong? Let me know in the comments. we would love to improve.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire a flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter-related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.

Leave comment

Your email address will not be published. Required fields are marked with *.