Carbone
This article is a tutorial about Carbone, an open-source report generator available on github. 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.
Table of content
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
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:
- Prepare your report template using your favorite text editor (LibreOffice, PowerPoint, etc...). Insert JSON-like mustache markers
{d.name}
directly in your document. - Fetch your JSON data from your API or any storage.
- Carbone analyses and injects your data into your template and you are done.
- * ๐ถ 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:
$ 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).
Create an index.js
file and prepare a JSON data:
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.
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.
$ node index.js
Voila, our first PDF report has been generated ! ๐
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:
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:
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:
(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:
var options = {
complement: {
johnWickQuote: "I'd like to make a dinner reservation for 12."
}
}
Then, your template can be accessed { c. }
instead of { d. }
:
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:
let options: {
variableStr: '{#version = d.versionDoc}'
}
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:
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.
Leave a like, comment, or follow me to support my first article.
Thanks for reading!
* funky groovy music fades out... ๐ถ *