Carbone Tutorial: fast and easy report generator (as fast as a spaceship 🚀)
Tags: node, javascript, tutorial
Published: 2019-10-14 18:53:11

# Carbone

This article is a tutorial about Carbone, an open-source report generator available on [github](https://github.com/Ideolys/carbone). I have been working on it since some time now but I do feel a lack of visibility for this awesome project.

Everything mentioned in this tutorial is available on [the carbone documentation](https://carbone.io/documentation.html#building-a-template).

## Table of content
1. [Introduction](#introduction)
2. [Generating our first report](#generating-our-first-report)
3. [Rendering options](#rendering-options)

## Introduction

Some years ago, I remember one of my missions (you may have encountered): generate invoices through HTML/CSS/DB/JS (or other broken frameworks). I spent so much hours to perfectly copy the report template and find some tricks to export it to PDF (or other formats). After spending a lot of time on one report, a mate gives you the following feedback: 
__`"It's not right here, can you change this? the design isn't right here. etc.."`__
Then, you lose hours in fixing the latter: It was time-consuming and not that easy 😅 


Anyway, an open-source project makes the life easier _* Start 1960 Funky Groovy Music 🎶 *_ :


🔥 Carbone ! [https://github.com/Ideolys/carbone](https://github.com/Ideolys/carbone)

![Groovy Dance](https://thepracticaldev.s3.amazonaws.com/i/oax67y69oexthem2tcsx.gif)

Carbone is a mustache-like template engine that analyses your template and injects data in the document. You can export it into the same format or any other formats: ODF, DOCX, PDF, XLSX, PPT, ODS, Text, CSV and more. A simple example step by step: 
1. Prepare your report template using your favorite text editor (LibreOffice, PowerPoint, etc...). Insert JSON-like mustache markers `{d.name}` directly in your document. 
2. Fetch your JSON data from your API or any storage.
3. Carbone analyses and injects your data into your template and you are done.
4. _* 🎶 enjoying funky groovy music 🎉 *_


Now, time to generate our first document.

## Generating our first report

Our goal is to generate a PDF document from an ODT template.

### Set up
- (required) Node 8 minimum.
- (optional) Install LibreOffice if you want to generate your documents in PDF format (only for pdf). For this tutorial, it can be downloaded here: https://www.libreoffice.org/download/download/.

Install Carbone with NPM:
```shell
$ npm install carbone --save
```

### Create the template
We begin with creating our template with LibreOffice by inserting some variables into single curly braces by adding `d.` in front of them. This is used by the carbone parser to identify variables. Finally, save the document as `template.odt`. For this step, you can use your favorite text editor (Word, Excel, Powerpoint).
![Edit Doc](https://thepracticaldev.s3.amazonaws.com/i/mn1bg6nlb81jv4fnbyo4.gif)

Create an `index.js` file and prepare a JSON data:
```js
  var data = {
    firstname : 'John',
    lastname : 'Wick'
  };
```
Next, import carbone and call the render function by passing the template created, JSON data and the options. In callback, the path of the PDF File that will be generated and the binary are passed in `fs.writeFileSync()` method.
```js
const fs = require('fs');
const carbone = require('carbone');

// data object to inject
let data = {
  firstname : 'John',
  lastname : 'Wick'
};

// options object is used to pass more parameters to carbone render function 
let options = {
  convertTo: 'pdf' //can be docx, txt, ...
}

carbone.render('./template.odt', data, options, (err, res) => {
    if (err) {
      return console.log(err);
    }
    // fs is used to create the PDF file from the render result
    fs.writeFileSync('./result.pdf', res);
    process.exit();
});

```
The final step, execute the file.
```shell
$ node index.js
```
Voila, our first PDF report has been generated ! 🎉
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/16qs160f59v33th4u3k0.png)

It was a really basic example, you can do exactly the same with different file formats with any kind of design. Next, this tutorial continues and dives into more advanced (and cool) options!

## Rendering options

Meanwhile, Carbone offers options for rendering which can be useful. Here is an example of some available options:
```js

let options = {
  convertTo    : 'pdf',
  lang         : 'en-us',
  complement   : {}, 
  variableStr  : '{#def = d.id}',
  reportName   : '{d.date}.odt',
  enums        : {
    'ORDER_STATUS' : ['open', 'close'],
    'SPEED' : {
      10 : 'slow' 
      20 : 'fast' 
    }
  },    
  translations : {
    'fr-fr' : {'one':'un' },
    'es-es' : {'one':'uno'}
  }
}
```
The options object can be passed to the render function or to `carbone.set(options)`.


Let's go into the details!

#### convertTo

Define the file type to generate. It can be a string with different format:`"pdf"`, `"ODT"`, `"TXT"`, `"xlsx"`, `"docx"`, `"ods"`, etc...
Also, it can be an object for CSV export: 
```js
let options = {
  convertTo: {
    formatName    : 'csv',
    formatOptions : {
      // you can define your own separators and delimiters
      fieldSeparator : '|', 
      textDelimiter  : '*',
      // utf-8, you can defined the system character set
      // check out the list: https://wiki.openoffice.org/wiki/Documentation/DevGuide/Spreadsheets/Filter_Options#Filter_Options_for_Lotus.2C_dBase_and_DIF_Filters
      characterSet   : '76' 
    }
  }
}
```
Example:
![Report sheet generator](https://thepracticaldev.s3.amazonaws.com/i/n65sj0luy6lmk7w43hcg.png)
(An article is coming soon about array repetitions, nested array, and more, stay tuned! Follow me on dev.to)
#### complement

You can add complement data in the template:
```js
var options = {
    complement: {
       johnWickQuote: "I'd like to make a dinner reservation for 12."
    }
}
```
Then, your template can be accessed `{ c. }` instead of `{ d. }`:
![Complement data report generator](https://thepracticaldev.s3.amazonaws.com/i/fw1j1ektaxw4irxptk11.png)

#### variableStr (alias)

This option is used to pass variables to the carbone template. The carbone documentation mentions `alias`, it is doing exactly the same thing: `alias` == `variableStr`. For example, you can insert in the document an alias where special characters like square brackets are not allowed. To define it:
```js
let options: {
  variableStr: '{#version = d.versionDoc}'
}
```
Then you can use it:
![conditional report generator](https://thepracticaldev.s3.amazonaws.com/i/4uu3lrlfzk9rgvu7d7gl.png)

Carbone offers a lot of possibilities about conditional logic through formatters. Again, I will explain further in another article.

#### reportName
The report name is passed to the callback function as third argument. It can be useful to inject dynamic data into the title, then receive it to create the file in the carbone callback. For example:

```js
let options: {
  reportName: 'invoice_{d.id}_{d.date}.odt'
}
```

#### enums

Enums are used with the `convEnum` formatter, I will explain the formatters in details (coming soon).


#### lang & translations

I will explain translations in another article (coming soon).

## The end

We have covered a lot about Carbone, it might have been difficult to explain at some point. Do not hesitate to comment for any help.

If you like the project, don't hesitate to fork and contribute (#hacktoberfest is not finished yet 🍻 hehe): [Github](https://github.com/Ideolys/carbone).

Leave a like, comment, or follow me to support my first article.

Thanks for reading! 

_* funky groovy music fades out... 🎶 *_ 


![Groovy Dance End](https://thepracticaldev.s3.amazonaws.com/i/e319jilihcqqm4mgpcxd.gif)

## Related articles
- [Use CarboneJS into Docker Container 🐳](https://dev.to/steeve/use-carbonejs-into-docker-container-4326)
- [Generate dynamic sheets from ODS templates with CarboneJS](https://dev.to/steeve/generate-dynamic-sheets-from-ods-templates-and-node-with-carbonejs-4c5m)
- [Creating dynamic reports with Carbone V2](https://dev.to/steeve/creating-dynamic-reports-with-carbonejs-v2-kfj)