How to export the cartesian chart as a pdf document (SfCartesianChart) ?
In this article, we explain how to export the cartesian chart as a PDF using the Flutter cartesian chart.
The SfCartesianChart widget provides an option to export the chart in PDF format. The following steps explain how to accomplish this exporting functionality.
Step 1: To access the path from mobile and other platforms, add the path_provider package as a dependency in the application. And add syncfusion_flutter_pdf package as a dependency to create and access PDF files.
path_provider: ^2.0.9 syncfusion_flutter_charts: ^20.1.48 syncfusion_flutter_pdf: ^20.1.48-beta
Step 2: It is necessary to include the platform-specific file generating codes to save the file as a PDF document. So, we have created two dart files (save_file_mobile and save_file_web) to save and launch the file on different platforms. On that two dart files, we have provided the common method called saveAndLaunchFile to save the exported content as a file.
To download the PDF file in the web platform, we should add AnchorElement from dart:html in this save_file_web file.
save_file_web.dart
import 'dart:async'; import 'dart:convert'; import 'dart:html'; class FileSaveHelper { static Future<void> saveAndLaunchFile( List<int> bytes, String fileName) async { AnchorElement( href: 'data:application/octet-stream;charset=utf-16le;base64,${base64.encode(bytes)}') ..setAttribute('download', fileName) ..click(); } }
To download the PDF file on the mobile and other platforms, we use this save_file_mobile file.
save_file_mobile.dart
import 'dart:io'; import 'package:flutter/services.dart'; import 'package:path_provider/path_provider.dart'; import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; class FileSaveHelper { static const MethodChannel _platformCall = MethodChannel('launchFile'); static Future<void> saveAndLaunchFile( List<int> bytes, String fileName) async { String? path; if (Platform.isAndroid || Platform.isIOS || Platform.isLinux || Platform.isWindows) { final Directory directory = await getApplicationSupportDirectory(); path = directory.path; } else { path = await PathProviderPlatform.instance.getApplicationSupportPath(); } final File file = File(Platform.isWindows ? '$path\\$fileName' : '$path/$fileName'); await file.writeAsBytes(bytes, flush: true); if (Platform.isAndroid || Platform.isIOS) { final Map<String, String> argument = <String, String> { 'file_path': '$path/$fileName' }; try { final Future<Map<String, String>?> result = _platformCall.invokeMethod('viewPdf', argument); } catch (e) { throw Exception(e); } } else if (Platform.isWindows) { await Process.run('start', <String>['$path\\$fileName'], runInShell: true); } else if (Platform.isMacOS) { await Process.run('open', <String>['$path/$fileName'], runInShell: true); } else if (Platform.isLinux) { await Process.run('xdg-open', <String>['$path/$fileName'], runInShell: true); } } }
Step 3: Initialize the variable _chartData which stores the data source and initialize the variable _cartesianChartKey which stores the global key of rendering the cartesian chart. This key is used to convert the chart into an image and we will use that image to create a PDF file.
And create the SfCartesianChart widget with the necessary properties.
//Add the necessary imports import 'dart:typed_data'; import 'dart:ui' as ui; import 'package:flutter/material.dart'; import '../save_file_mobile.dart' if (dart.library.html) '../save_file_web.dart'; import 'dart:async'; import 'package:syncfusion_flutter_charts/charts.dart'; import 'package:syncfusion_flutter_pdf/pdf.dart'; late GlobalKey<SfCartesianChartState> _cartesianChartKey; late List<ChartSampleData> _chartData; @override void initState() { _cartesianChartKey = GlobalKey(); _chartData = < ChartSampleData >[ ChartSampleData ('Jan', 12), ChartSampleData ('Feb', 28), ChartSampleData ('Mar', 35), ChartSampleData ('Apr', 27), ChartSampleData ('Jun', 42), ChartSampleData ('Jul', 33) ]; super.initState(); } @override Widget build(BuildContext context) { return SfCartesianChart( key: _cartesianChartKey, primaryXAxis: CategoryAxis(), series: <ColumnSeries< ChartSampleData, String>>[ ColumnSeries< ChartSampleData, String>( dataSource: _chartData, xValueMapper: (ChartSampleData data, _) => data.x, yValueMapper: (ChartSampleData data, _) => data.y ) ] ) } class ChartSampleData { ChartSampleData ({this.x, this.y}); final String? x; final num? y; }
Step 4: Create a separate method called _renderPdf where we export the chart as a PDF. Added a snack bar to notify the chart is exported as a PDF document.
Future<void> _ renderPdf () async { final ui.Image data = await _ cartesianChartKey.currentState!.toImage(pixelRatio : 3.0); final ByteData? bytes = await data.toByteData(format : ui.ImageByteFormat.png); final Uint8List imageBytes = bytes!.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes); final PdfBitmap bitmap = PdfBitmap(imageBytes); final PdfDocument document = PdfDocument(); document.pageSettings.size = Size(bitmap.width.toDouble(), bitmap.height.toDouble()); final PdfPage page = document.pages.add(); final Size pageSize = page.getClientSize(); page.graphics.drawImage(bitmap, Rect.fromLTWH(0, 0, pageSize.width, pageSize.height)); await FileSaveHelper.saveAndLaunchFile(document.save(), 'cartesian_chart.pdf'); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(5)) ), duration: Duration(milliseconds: 200), content: Text('Chart has been exported as PDF document.'), ) );
Step 5: Add the TextButton widget and call the _renderPdf method to convert the rendered chart as PDF.
@override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ SfCartesianChart( key: _ cartesianChartKey, primaryXAxis: CategoryAxis(), series: <ColumnSeries<ChartSampleData, String>>[ ColumnSeries<ChartSampleData, String>( dataSource: _chartData, xValueMapper: (ChartSampleData data, _) => data.x, yValueMapper: (ChartSampleData data, _) => data.y, ) ] ), TextButton( child: const Text('Export as PDF), onPressed: () { _renderPdf(); }, ) ] ); }
Now if we tap the TextButton ,the exported PDF of the cartesian chart will be downloaded.