DEV Community

Cover image for How to Create PDF/A Standard Files in Flutter
Suresh Mohan for Syncfusion, Inc.

Posted on • Originally published at syncfusion.com on

How to Create PDF/A Standard Files in Flutter

The Syncfusion Flutter PDF Library allows users to create and edit PDF documents in a Flutter application. You can also create various PDF conformance documents. In this blog, we will take a brief look at the PDF conformance levels followed by the procedure to create PDF documents with different conformance levels.

PDF/A is an ISO-standardized version of the PDF, specialized for use in the archiving and long-term preservation of electronic documents to preserve text, vector graphics, raster images, and related metadata. This PDF/A conformance comes in different variants. At present our Flutter PDF Library supports creating PDF documents with the following conformance levels:

  • PDF/A-1B
  • PDF/A-2B
  • PDF/A-3B

PDF/A-1

PDF/A-1 was the first archiving standard. It was published in 2005 as ISO 19005-1. It is based on PDF 1.4 and imposes some restrictions regarding the use of color, fonts, annotations, transparencies, and other elements.

PDF/A-2

PDF/A-2 was published in 2011 as ISO 19005-2. It is based on PDF version 1.7, which has been standardized as ISO 32000-1. It makes use of the new features in this version. PDF/A-2 allows JPEG2000 compression, transparent elements, and PDF layers. PDF/A-2 also allows you to embed OpenType fonts and supports PAdES. One important innovation is the container function: PDF/A files can be embedded within a PDF/A-2 document.

PDF/A-3

PDF/A-3 has been available since October 2012. A PDF/A-3 document allows you to embed any format file in a PDF document desired—not just PDF/A documents. For example, a PDF/A-3 file can contain the original file from which it was generated. The PDF/A standard does not regulate the suitability of these embedded files for archiving.

Level B conformance ensures that the visual appearance of a document is preservable long term, that the document will look the same when it is viewed or printed at any time in the future.

In this blog, we are going to cover the creation of the following conformance-level documents programmatically:

Create PDF/A-1B file

With the Syncfusion Flutter PDF Library, you can create a PDF document with PDF/A-1B standard. Here’s the procedure to do so:

Step 1: Create a Flutter application.

Follow the instructions provided in this Getting Started documentation to create a basic Flutter application.

Step 2: Add the Syncfusion Flutter PDF dependency.

Include the Syncfusion Flutter PDF package dependency in the pubspec.yaml file in your project.

Refer to the following code.

dependencies:
  syncfusion_flutter_pdf: ^18.4.30-beta
Enter fullscreen mode Exit fullscreen mode

Step 3: Get the package.

Run the following command to get the required package.

| $ flutter pub get |

Step 4: Import the package

Import the PDF package into main.dart file using the following code example.

import 'package:syncfusion_flutter_pdf/pdf.dart';
Enter fullscreen mode Exit fullscreen mode

Step 5: Create PDF/A-1B conformance document.

  1. Add a button widget as a child to your container widget, as shown in the following code example.
@override
Widget build(BuildContext context) {
  return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Choose the conformance level:'),
            Row(
              children: [
                Row(children: [
                  Radio(
                      groupValue: _groupValue, onChanged: _changed, value: 0),
                  Text('PDF/A-1B', style: TextStyle(fontSize: 16))
                ]),
                Row(children: [
                  Radio(
                      groupValue: _groupValue, onChanged: _changed, value: 1),
                  Text('PDF/A-2B', style: TextStyle(fontSize: 16))
                ]),
                Row(children: [
                  Radio(
                      groupValue: _groupValue, onChanged: _changed, value: 2),
                  Text('PDF/A-3B', style: TextStyle(fontSize: 16))
                ]),
              ],
            ),
            FlatButton(
              child: Text(
                'Create PDF',
                style: TextStyle(color: Colors.white),
              ),
              onPressed: _conformancePDF,
              color: Colors.blue,
            )
          ],
        ),
      ));
}
Enter fullscreen mode Exit fullscreen mode
  1. Include the following code in the button click event to create a PDF/A-1B document.
//Create a new PDF document with conformance A1B.
PdfDocument document =
    PdfDocument(conformanceLevel: PdfConformanceLevel.a1b);
//Add page to the PDF.
final PdfPage page = document.pages.add();
//Get page client size.
final Size pageSize = page.getClientSize();
//Draw rectangle.
page.graphics.drawRectangle(
    bounds: Rect.fromLTWH(0, 0, pageSize.width, pageSize.height),
    pen: PdfPen(PdfColor(142, 170, 219, 255)));
//Read font file.
List<int> fontData = await _readData('Roboto-Regular.ttf');
//Create a PDF true type font.
PdfFont contentFont = PdfTrueTypeFont(fontData, 9);
PdfFont headerFont = PdfTrueTypeFont(fontData, 30);
PdfFont footerFont = PdfTrueTypeFont(fontData, 18);
//Generate PDF grid.
final PdfGrid grid = _getGrid(contentFont);
//Draw the header section by creating text element.
final PdfLayoutResult result =
    _drawHeader(page, pageSize, grid, contentFont, headerFont, footerFont);
//Draw grid.
_drawGrid(page, grid, result, contentFont);
//Add invoice footer.
_drawFooter(page, pageSize, contentFont);
//Save and dispose the document.
final List<int> bytes = document.save();
document.dispose();
Enter fullscreen mode Exit fullscreen mode
  1. The following code example is used to create the invoice header with basic information.
PdfLayoutResult _drawHeader(PdfPage page, Size pageSize, PdfGrid grid,
      PdfFont contentFont, PdfFont headerFont, PdfFont footerFont) {
    //Draw rectangle.
    page.graphics.drawRectangle(
        brush: PdfSolidBrush(PdfColor(91, 126, 215, 255)),
        bounds: Rect.fromLTWH(0, 0, pageSize.width - 115, 90));
    //Draw string.
    page.graphics.drawString('INVOICE', headerFont,
        brush: PdfBrushes.white,
        bounds: Rect.fromLTWH(25, 0, pageSize.width - 115, 90),
        format: PdfStringFormat(lineAlignment: PdfVerticalAlignment.middle));
    page.graphics.drawRectangle(
        bounds: Rect.fromLTWH(400, 0, pageSize.width - 400, 90),
        brush: PdfSolidBrush(PdfColor(65, 104, 205)));
    page.graphics.drawString(
        '\$' + _getTotalAmount(grid).toString(), footerFont,
        bounds: Rect.fromLTWH(400, 0, pageSize.width - 400, 100),
        brush: PdfBrushes.white,
        format: PdfStringFormat(
            alignment: PdfTextAlignment.center,
            lineAlignment: PdfVerticalAlignment.middle));
    //Draw string.
    page.graphics.drawString('Amount', contentFont,
        brush: PdfBrushes.white,
        bounds: Rect.fromLTWH(400, 0, pageSize.width - 400, 33),
        format: PdfStringFormat(
            alignment: PdfTextAlignment.center,
            lineAlignment: PdfVerticalAlignment.bottom));
    //Create data foramt and convert it to text.
    final DateFormat format = DateFormat.yMMMMd('en_US');
    final String invoiceNumber = 'Invoice Number: 2058557939\r\n\r\nDate: ' +
        format.format(DateTime.now());
    final Size contentSize = contentFont.measureString(invoiceNumber);
    const String address =
        'Bill To: \r\n\r\nAbraham Swearegin, \r\n\r\nUnited States, California, San Mateo, \r\n\r\n9920 BridgePointe Parkway, \r\n\r\n9365550136';
    PdfTextElement(text: invoiceNumber, font: contentFont).draw(
        page: page,
        bounds: Rect.fromLTWH(pageSize.width - (contentSize.width + 30), 120,
            contentSize.width + 30, pageSize.height - 120));
    return PdfTextElement(text: address, font: contentFont).draw(
        page: page,
        bounds: Rect.fromLTWH(30, 120,
            pageSize.width - (contentSize.width + 30), pageSize.height - 120));
  }
Enter fullscreen mode Exit fullscreen mode
  1. Add the invoice data in a tabular format with five columns using Syncfusion PDF tables.
//Create PDF grid and return.
  PdfGrid _getGrid(PdfFont contentFont) {
    //Create a PDF grid.
    final PdfGrid grid = PdfGrid();
    //Specify the column count to the grid.
    grid.columns.add(count: 5);
    //Create the header row of the grid.
    final PdfGridRow headerRow = grid.headers.add(1)[0];
    //Set style.
    headerRow.style.backgroundBrush = PdfSolidBrush(PdfColor(68, 114, 196));
    headerRow.style.textBrush = PdfBrushes.white;
    headerRow.cells[0].value = 'Product Id';
    headerRow.cells[0].stringFormat.alignment = PdfTextAlignment.center;
    headerRow.cells[1].value = 'Product Name';
    headerRow.cells[2].value = 'Price';
    headerRow.cells[3].value = 'Quantity';
    headerRow.cells[4].value = 'Total';
    _addProducts('CA-1098', 'AWC Logo Cap', 8.99, 2, 17.98, grid);
    _addProducts(
        'LJ-0192', 'Long-Sleeve Logo Jersey,M', 49.99, 3, 149.97, grid);
    _addProducts('So-B909-M', 'Mountain Bike Socks,M', 9.5, 2, 19, grid);
    _addProducts(
        'LJ-0192', 'Long-Sleeve Logo Jersey,M', 49.99, 4, 199.96, grid);
    _addProducts('FK-5136', 'ML Fork', 175.49, 6, 1052.94, grid);
    _addProducts('HL-U509', 'Sports-100 Helmet,Black', 34.99, 1, 34.99, grid);
    final PdfPen whitePen = PdfPen(PdfColor.empty, width: 0.5);
    PdfBorders borders = PdfBorders();
    borders.all = PdfPen(PdfColor(142, 179, 219), width: 0.5);
    ;
    grid.rows.applyStyle(PdfGridCellStyle(borders: borders));
    grid.columns[1].width = 200;
    for (int i = 0; i < headerRow.cells.count; i++) {
      headerRow.cells[i].style.cellPadding =
          PdfPaddings(bottom: 5, left: 5, right: 5, top: 5);
      headerRow.cells[i].style.borders.all = whitePen;
    }
    for (int i = 0; i < grid.rows.count; i++) {
      final PdfGridRow row = grid.rows[i];
      if (i % 2 == 0) {
        row.style.backgroundBrush = PdfSolidBrush(PdfColor(217, 226, 243));
      }
      for (int j = 0; j < row.cells.count; j++) {
        final PdfGridCell cell = row.cells[j];
        if (j == 0) {
          cell.stringFormat.alignment = PdfTextAlignment.center;
        }
        cell.style.cellPadding =
            PdfPaddings(bottom: 5, left: 5, right: 5, top: 5);
      }
    }
    //Set font
    grid.style.font = contentFont;
    return grid;
  }
  //Create and row for the grid.
  void _addProducts(String productId, String productName, double price,
      int quantity, double total, PdfGrid grid) {
    final PdfGridRow row = grid.rows.add();
    row.cells[0].value = productId;
    row.cells[1].value = productName;
    row.cells[2].value = price.toString();
    row.cells[3].value = quantity.toString();
    row.cells[4].value = total.toString();
  }
  //Get the total amount.
  double _getTotalAmount(PdfGrid grid) {
    double total = 0;
    for (int i = 0; i < grid.rows.count; i++) {
      final String value = grid.rows[i].cells[grid.columns.count - 1].value;
      total += double.parse(value);
    }
    return total;
  }
Enter fullscreen mode Exit fullscreen mode

Draw the table in the PDF document.

void _drawGrid(
      PdfPage page, PdfGrid grid, PdfLayoutResult result, PdfFont contentFont) {
    Rect totalPriceCellBounds;
    Rect quantityCellBounds;
    //Invoke the beginCellLayout event.
    grid.beginCellLayout = (Object sender, PdfGridBeginCellLayoutArgs args) {
      final PdfGrid grid = sender;
      if (args.cellIndex == grid.columns.count - 1) {
        totalPriceCellBounds = args.bounds;
      } else if (args.cellIndex == grid.columns.count - 2) {
        quantityCellBounds = args.bounds;
      }
    };
    //Draw the PDF grid and get the result.
    result = grid.draw(
        page: page, bounds: Rect.fromLTWH(0, result.bounds.bottom + 40, 0, 0));
    //Draw grand total.
    page.graphics.drawString('Grand Total', contentFont,
        bounds: Rect.fromLTWH(
            quantityCellBounds.left,
            result.bounds.bottom + 10,
            quantityCellBounds.width,
            quantityCellBounds.height));
    page.graphics.drawString(_getTotalAmount(grid).toString(), contentFont,
        bounds: Rect.fromLTWH(
            totalPriceCellBounds.left,
            result.bounds.bottom + 10,
            totalPriceCellBounds.width,
            totalPriceCellBounds.height));
  }
Enter fullscreen mode Exit fullscreen mode
  1. Include the following code to add the seller information.
void _drawFooter(PdfPage page, Size pageSize, PdfFont contentFont) {
    final PdfPen linePen =
        PdfPen(PdfColor(142, 170, 219, 255), dashStyle: PdfDashStyle.custom);
    linePen.dashPattern = <double>[3, 3];
    //Draw line.
    page.graphics.drawLine(linePen, Offset(0, pageSize.height - 100),
        Offset(pageSize.width, pageSize.height - 100));
    const String footerContent =
        '800 Interchange Blvd.\r\n\r\nSuite 2501, Austin, TX 78721\r\n\r\nAny Questions? support@adventure-works.com';
    //Added 30 as a margin for the layout.
    page.graphics.drawString(footerContent, contentFont,
        format: PdfStringFormat(alignment: PdfTextAlignment.right),
        bounds: Rect.fromLTWH(pageSize.width - 30, pageSize.height - 70, 0, 0));
  }
Enter fullscreen mode Exit fullscreen mode
  1. Add the assets to the pubspec.yaml file.
# To add assets to your application, add an assets section, like this.
assets:
  - assets/Roboto-Regular.ttf

Enter fullscreen mode Exit fullscreen mode
  1. Include the following code to read the font data from the folder where it is saved. Here, we have named our folder assets.
Future<List<int>> _readData(String name) async {
final ByteData data = await rootBundle.load('assets/$name');
return data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
}
Enter fullscreen mode Exit fullscreen mode

By executing the code example, the PDF/A-1B conformance document will be created like in the following screenshot.

Create PDF/A-1B conformance document

Create PDF/A-2B file

Just modify the PdfConformanceLevel to a2b during the PdfDocument object initialization to create a PDF document with the PDF/A-2B conformance level. The following code illustrates this.

//Create a new PDF document with conformance A2B.
PdfDocument document =
    PdfDocument(conformanceLevel: PdfConformanceLevel.a2b);
Enter fullscreen mode Exit fullscreen mode

By executing the previous code, a PDF document with PDF/A-2B conformance level will be created.

Create PDF/A- 2B conformance document

Create PDF/A-3B file

PDF/A-3B conformance supports attachments to the PDF document. Modify the PdfConformanceLevel to a3b during the PdfDocument object initialization to create a PDF document with a PDF/A-3B conformance level. The following code illustrates this along with including an attachment to the PDF document.

//Create a new PDF document with conformance A3B.
PdfDocument document =
    PdfDocument(conformanceLevel: PdfConformanceLevel.a3b);
//Add attachment to the PDF document.
String text =
    'Adventure Works Cycles, the fictitious company on which ...';
document.attachments.add(PdfAttachment(
    'AdventureCycle.txt', utf8.encode(text),
    description: 'Adventure Works Cycles', mimeType: 'application/txt'));
Enter fullscreen mode Exit fullscreen mode

By executing this code, you will get an output PDF document like the following screenshots.

Create PDF/A -3B conformance document

PDF/A-3B file with attachmentResource

You can check out the complete sample in this GitHub repository to create PDF conformance documents.

Conclusion

In this blog post, we have learned the procedure to create PDF documents at various conformance levels using our Syncfusion PDF Flutter Library.

Take a moment to peruse our documentation, where you’ll find other options and features, all with accompanying code examples.

If you have any questions about these features, please let us know in the comments below. You can also contact us through our support forum, Direct-Trac, or feedback portal. We are happy to assist you!

If you liked this article, we think you would also like the following articles about PDF Library:

Top comments (0)