Creating dynamic reports with CarboneJS V2
Tags: javascript, node, news
Published: 2020-08-13 08:07:23

The Carbone team has released a major update to add the possibility to create complex reports easily. In the `v2.0.0`, the core has been rewritten to fix a security breach, reduce memory consumption, and gain stability! In this article, we will go through the new and cool features:
- Dynamic variables in all formatters
- Dynamic content 🎉
- **Beta** Rendering dynamic charts

Everything mentioned in this article is available on the [Carbone Changelog](https://github.com/Ideolys/carbone/blob/master/CHANGELOG.md).

> What is Carbone? It is a report generator using a JSON dataset and an XML based template (ODT/DOCX/XLSX/ODS/...). I have already made an introduction about it, [check this out!](https://dev.to/steeve/carbone-tutorial-fast-and-easy-report-generator-as-fast-as-a-spaceship-54bc)

> If you want to learn more about Carbone, check out the project on Github: [https://github.com/Ideolys/carbone](https://github.com/Ideolys/carbone)

## Dynamic variables in all formatters

For the next examples, the following JSON dataset is going to be used:

```json
{
  "quantity": 3
  "numberSupply": {
    "nbrA": 10,
    "nbrB": 5
  },
  "references": {
    "id1": "Invoice 123",
    "id2": "Bill 402"
  }
}
```

It is possible to pass variables to formatter arguments, here is an addition on a DOCX template:
![carbone addition](https://dev-to-uploads.s3.amazonaws.com/i/vbbc5rpoym9nlj8o2ofj.png)

Carbone translates the marker `{d.numberSupply.nbrA:add(.nbrB)}` to `10 + 5` and it prints the result `15` on the report.


Adding dots can be used to backtrack to the parent object. Let's multiply by the `quantity`:

![Multiply on reports](https://dev-to-uploads.s3.amazonaws.com/i/hrwb8j2ctya0m1ef57rc.png)

The marker `{d.numberSupply.nbrA:add(.nbrB):mul(..quantity)}` is translated to `(10 + 5) * 3`and it prints: `45`

There's no limit in depth to access to a parent object with dots. If an element doesn't exist, the error `[[C_ERROR]] badAttr not defined` is returned. In the end, it is not possible to pass an array to a formatter argument.

## Dynamic content block and conditional formatters

The main feature of the V2 update is the conditional sections, in other words, selectively show content on the report. Here is a template example:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/c2viz4z8y8sj537og71u.png)

1. Markers `{d.isHidden:hideBegin()}` and `{d.isHidden:hideEnd()}` surrounding the content define the beginning and the end of the section to hide.
2. If the value of the data `isHidden` is true, the table is going to be hidden, otherwise, it appears on the report.

The result:
![conditional_content](https://dev-to-uploads.s3.amazonaws.com/i/qx1e316y5ja2rw4nzqoa.gif)

The same result can be done with the pair `:showBegin()`/`:showEnd()`.


Finally, a new set of conditional formatter came out:
- `:ifEQ(value)` Matches values that are equal to a specified value. The opposite is `:ifNEQ()`.
- `:ifGT(value)` Matches values that are greater than a specified value. You can check the equality with `:ifGTE()`.
- `:ifLT(value)` Matches values that are less than a specified value. You can check the equality with `:ifLTE()`.
- `:ifIN(value)` Matches any of the values specified in an array or string. The opposite is `:ifNIN()`.
- `:ifEM(value)` Matches empty values, string, arrays or objects. The opposite is `:ifNEM()`.
- `:and(value)` AND operator between two consecutive conditional formatters.
- `:or(value)` OR operator between two consecutive conditional formatters.

It helps a lot to add logic in the report, such as showing a specific title in a DOCX report:

![Title DOCX](https://dev-to-uploads.s3.amazonaws.com/i/8wssksg80cnha7dtmyw3.png)

This is the equivalent in javascript:
```js
if (d.quantity > 2 || d.numberSupply.nbrA == 8) {
  print(d.references.id1)
}
```
In the dataset, `d.quantity` is superior to two and it validates the condition. The report generated:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/xq6u7oouro7rh1ndjst5.png)

## Iterate on attributes of objects

Printing an object as a list has never been easier, here is the dataset used for the following example:
```json
{
  myObject : {
    paul : '10',
    jack : '20',
    bob  : '30'
  }
}
```
The template used:
![Iterate objects](https://dev-to-uploads.s3.amazonaws.com/i/q60wl4rz8krs1idzrgdo.png)

First, the object have to be transformed to a list with `d.myObject[i]`, then use `.att` to print the attribute or use `.val` to print the value.

The result:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2or2gdmeqgbju3u919on.png)

## Beta - supports dynamic charts rendering in XLSX files

The feature of printing charts is still experimental and will have improvements in the future. To make it work, the following steps have to be followed:
- First, temporary data have to be inserted at the top left corner of the spreadsheet.
- Then, the chart can be created from the temporary data range.
- Replace the temporary data by the Carbone marker pointing to the JSON data set and add the formatter `:formatN()`.

Here is a template example:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/gi8duj8qge2e93kdvb25.png)
The dataset used:
```json
{
  "list": [
    { "key": 1, "nbr": 2 }, 
    { "key": 2, "nbr": 3 }, 
    { "key": 3, "nbr": 1 }, 
    { "key": 2, "nbr": 4.4 }, 
    { "key": 5, "nbr": 10.01 }
  ]
}
```
Here is the result:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/x6y4crtux7y5ylfxxvas.png)
Voila! 🎉

## Conclusion

The community is positive and sharing good feedback about the latest release. All the changes and new features are available on the [CHANGELOG.md](https://github.com/Ideolys/carbone/blob/master/CHANGELOG.md).

Contact me if you need help with Carbone, I'll be happy to answer!

Thanks for reading!

![Stay cool](https://dev-to-uploads.s3.amazonaws.com/i/kyp30njfz5ikik4koqf4.gif)