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 when you tap the TextButton ,the cartesian chart will be exported and downloaded as a PDF file.
