Skip to content

Tutorial

Julien Férard edited this page Jun 17, 2019 · 19 revisions

This tutorial is extracted from https://github.com/jferard/fastods/tree/master/fastods-examples/src/main/java/com/github/jferard/fastods/examples. See the classes in this directory for the full code.

Writing a full documentation would be a considerable work, because every time you change the library, you have to rewrite the doc.

My idea is to provide a set of examples of the features of FastODS.

Before you start, add the following dependency to your POM (Maven users):

 <dependency>
     <groupId>com.github.jferard</groupId>
     <artifactId>fastods</artifactId>
     <version>0.6.1</version>
 </dependency>

For other build tools, look at: https://search.maven.org/artifact/com.github.jferard/fastods/0.6.1/jar

Hello, world!

Let's start with the famous "Hello, World!" example.

As stated in the javadoc, "An OdsFactory is the entry point for creating ODS documents." Every time you want to create an ODS document, you'll start with something like that:

    final OdsFactory odsFactory = OdsFactory.create(Logger.getLogger("hello-world"), Locale.US);

Now, you can create an ODS writer. You have the choice: either you give the filename now, or you keep it for the end. Let's create an anonymous writer: the content will live in memory until we save it to a file:

    final AnonymousOdsFileWriter writer = odsFactory.createWriter();

The writer owns a document that we need to create a spreadsheet:

    final OdsDocument document = writer.document();

Okay, let's go. We create a new table (a new sheet indeed) named "hello-world":

    final Table table = document.addTable("hello-world");

We get the first row:

    final TableRow row = table.getRow(0);

And the first cell of the first row:

    final TableCell cell = row.getOrCreateCell(0);

Note that we could have chained the calls: TableCell cell = document.addTable("hello-world").getRow(0).getOrCreateCell(0) Finally, we put the famous sentence in this cell A1

    cell.setStringValue("Hello, world!");

And save the file.

    writer.saveAs(new File("generated_files", "a_hello_world_example.ods"));

With a mvn clean verify at the root of the project, you can check the result in the fastods-examples/generated-files directory.

Accessing tables, rows and cells

Now, we want to write values in other cells that the A1 cell.

We start with the (now) usual boilerplate code to get a document:

    final OdsFactory odsFactory = OdsFactory.create(Logger.getLogger("accessing"), Locale.US);
    final AnonymousOdsFileWriter writer = odsFactory.createWriter();
    final OdsDocument document = writer.document();

Direct access to cells

You know how to create a table:

    final Table table1 = document.addTable("direct-access");

Get the first row (rows and columns start at 0):

    TableRow row = table1.getRow(0);

The first cell of the first row:

    TableCell cell = row.getOrCreateCell(0);

And set a value.

    cell.setStringValue("A1");

Note that the access is a write only access. You can't read the content of a cell. You can have direct access to any cell, but it has a cost. If the row doesn't exist yet in the list of rows, it will create all rows between the last row and the actual row.

    row = table1.getRow(6);

You can have direct access to cells

    cell = row.getOrCreateCell(1);
    cell.setStringValue("B7");

With a TableHelper, direct access might be easier to write...

    final TableHelper tableHelper = TableHelper.create();

...but note that the cell is referred by row then column (as matrices in maths). To access the cell "F2", you'll use:

    cell = tableHelper.getCell(table1, 1, 5);
    cell.setStringValue("F2");

You can use an address, but there is the cost of parsing that address and a risk of malformed address:

    try {
        cell = tableHelper.getCell(table1, "E3");
        cell.setStringValue("E3");
    } catch (final ParseException e) {
        /* this won't happen here! */
    }

To be (almost) complete, there is another way to write a value to a cell:

    try {
        tableHelper.setCellValue(table1, "D4", CellValue.fromObject("D4"));
    } catch (final ParseException e) {
        /* this won't happen here! */
    }

Relative access

Direct access may be useful, but FastODS was designed for a relative access Create a new table:

    final Table table2 = document.addTable("relative-access");

We want ten rows of data

    for (int r = 0; r < 10; r++) {

The Table object has an internal row index (that is updated by the getRow method). Just call nextRow to make the index advance by one (you have to call nextRow before you write data, to get the first row):

        final TableRow tableRow = table2.nextRow();

And then create a "walker" for this row:

        final TableCellWalker cellWalker = tableRow.getWalker();

Now, we want nine columns for each row:

        for (int c = 0; c < 9; c++) {

Add the value to each cell

            cellWalker.setStringValue(String.valueOf((char) (c + 'A')) + String.valueOf(r + 1));

And then push one cell right.

            cellWalker.next();
        }
    }

And save the file.

    writer.saveAs(new File("generated_files", "b_accessing_example.ods"));

Note: There is a slight inconsistency between table.newtRow (before using the row) and cellWalker.next (after using the cell). Maybe I'll fix it before version 1.0...

Value, type, style and data style

Four elements define the content of a cell:

  • the value
  • the type (string, float, boolean, ...)
  • the style (font, background color, border, ...)
  • the format, or data style (number of digits for a float, date format for a date, ...)

So far, we just created cells of type string, with neither style nor data style. Now, we will create cells with a more varied content.

Types

Now, we will create cells of different types. First, a table:

    final Table table = document.addTable("types");

We add a header:

    TableRow tableRow = table.nextRow();
    TableCellWalker cellWalker = tableRow.getWalker();
    cellWalker.setStringValue("Type");
    cellWalker.next();
    cellWalker.setStringValue("Example");

The first row contains a boolean:

    tableRow = table.nextRow();
    cellWalker = tableRow.getWalker();
    cellWalker.setStringValue("Boolean");
    cellWalker.next();
    cellWalker.setBooleanValue(true);

The second row contains a currency:

    tableRow = table.nextRow();
    cellWalker = tableRow.getWalker();
    cellWalker.setStringValue("Currency");
    cellWalker.next();
    cellWalker.setCurrencyValue(10.5, "USD");

The third row contains a date:

    tableRow = table.nextRow();
    cellWalker = tableRow.getWalker();
    cellWalker.setStringValue("Date");
    cellWalker.next();
    cellWalker.setDateValue(new GregorianCalendar(2014, 9, 17, 9, 0, 0));

The fourth row contains a float:

    tableRow = table.nextRow();
    cellWalker = tableRow.getWalker();
    cellWalker.setStringValue("Float");
    cellWalker.next();
    cellWalker.setFloatValue(3.14159);

The fifth row contains a percentage:

    tableRow = table.nextRow();
    cellWalker = tableRow.getWalker();
    cellWalker.setStringValue("Percentage");
    cellWalker.next();
    cellWalker.setPercentageValue(0.545);

The sixth row contains...

    tableRow = table.nextRow();
    cellWalker = tableRow.getWalker();
    cellWalker.setStringValue("String");
    cellWalker.next();
    cellWalker.setStringValue("A String");

The seventh row contains a time (that mean a duration):

    tableRow = table.nextRow();
    cellWalker = tableRow.getWalker();
    cellWalker.setStringValue("Time");
    cellWalker.next();
    cellWalker.setTimeValue(3600);

The eighth row contains nothing

    tableRow = table.nextRow();
    cellWalker = tableRow.getWalker();
    cellWalker.setStringValue("Void");
    cellWalker.next();
    cellWalker.setVoidValue();

Type guess

FastODS can guess types, based on Java object types. It's useful when we try to auto import typed data, e.g. from a ResultSet. We can use this ability to reduce the boilerplate code.

Let's define two lists:

    final List<String> A = Arrays
            .asList("Type", "Boolean", "Currency", "Date", "Float", "Percentage", "String",
                    "Void");
    final List<Object> B = Arrays
            .<Object>asList("Type guess example", true, new CurrencyValue(10.5f, "USD")
                    , new GregorianCalendar(2014, 9, 17, 9, 0, 0),
                    3.14159, new PercentageValue(0.545f), "A String", null);

As you can see, some types are not guessable: is 0.545 a float or a percentage? For FastODS, it is a float. What Java type will map a currency value? We have to use specific types...

We skip a row for readability:

    table.nextRow();

Now, we can use setValue to take advantage of the type guess:

    for (int r=0; r<A.size(); r++) {
        tableRow = table.nextRow();
        cellWalker = tableRow.getWalker();
        cellWalker.setStringValue(A.get(r));
        cellWalker.next();
        cellWalker.setCellValue(CellValue.fromObject(B.get(r)));
    }

Styles

Data Styles

Clone this wiki locally