Java LaTeX Report – Tutorial

This tutorial explains how to use the JLR (Java LaTeX Report) library by nixo-soft.
To understand the following code, a basic knowledge in LaTeX and Java is required.
Furthermore you need realcalc.tex, invoice.sty and invoice.def to execute the sample code.

Requirements: Java Runtime Environment (JRE) 6 Update 20 / Installed or portable LaTeX Distribution (e.g. MiKTeX or MiKTeX Portable)

The tutorial is divided into three parts:



How to create a LaTeX template file

Before we can use the JLR library in our Java project, we have to create a template file in LaTeX.
Let’s assume that we want to create multiple invoices for different customers (if you need help in creating invoices with Latex, just have a look at CTAN or invoice.pdf).

So, a very simple invoice template could look like:

invoiceTemplate.tex


\documentclass{letter} 
\usepackage{invoice} 
\address{Josh Parker \\
         5650 Webster Ave \\
         West Palm Beach, Florida 33405 \\
         JParker@mail.com} 
\date{31-May-2010} 

\begin{document} 
\begin{letter}{::Customer name::: \\ 
               ::Customer street::: \\ 
               ::Customer zip:::} 
\opening{Invoice no. ::Number:::} 
Dear customer,

... 

\begin{invoice}{Euro}{0} 
\ProjectTitle{Example Project} 
\Fee{::Development:::} {::Price:::} {1} 
\end{invoice} 

\closing{Best regards} 
\end{letter} 
\end{document} 

As you can see, there are special tags or patterns (:: and :::) with variables, which are user-defined and don’t belong to LaTeX. These are used to indicate variable information (like name, address, date etc.) and will be replaced afterwards by JLR. The beginning pattern :: (where the replacement starts) and the ending pattern ::: (where the replacement ends) have to be different. Before you compile the sample code in your LaTeX editor, it’s necessary to include realcalc.tex, invoice.sty and invoice.def in your working directory (where your invoiceTemplate.tex lies) - or you can integrate these files into your LaTeX distribution.

Note: Maybe you get some error messages from your LaTeX editor. This is normal – these errors occur because the instruction

\Fee{::Development:::} {::Price:::} {1}

expects a number as second argument (and not the variable Price). Later we are going to replace this variable with a number – hence it can be ignored so far.



The PDF file of the invoice template should look like:



(invoiceTemplatePDF.)



How to use JLR to create a report file

The next step is to start a new Java project and import the JLR library into it.
Now let’s look at some sample code to see how JLR works.

First you have to make a declaration of the template file (e.g. C:\Invoices\invoiceTemplate.tex)
and the output tex files (e.g. C:\Invoices\temp\invoice1.tex and C:\Invoices\temp\invoice2.tex) which you want to create:


File workingDirectory = new File("C:" + File.separator + "Invoices");

File template = new File(workingDirectory.getAbsolutePath() + File.separator + "invoiceTemplate.tex");

File tempDir = new File(workingDirectory.getAbsolutePath() + File.separator + "temp");
if (!tempDir.isDirectory()) {
    tempDir.mkdir();
}
File invoice1 = new File(tempDir.getAbsolutePath() + File.separator + "invoice1.tex");
File invoice2 = new File(tempDir.getAbsolutePath() + File.separator + "invoice2.tex");

Our goal is to fill the template with information. To achieve this, we have to put the data into a map,
where a map key has to correspond to the variables in the template.


HashMap<String, String> data = new HashMap<String, String>();

data.put("Number", "1");
data.put("Customer name", "Ivan Pfeiffer");
data.put("Customer street", "Schwarzer Weg 4");
data.put("Customer zip", "13505 Berlin");
data.put("Development", "Software");
data.put("Price", "500");

Now we are ready to use JLR and merge our template file with the map:


JLRConverter converter = new JLRConverter("::", ":::");
converter.parse(template, invoice1, data);

The second invoice (invoice2) is going to be created in an analogous manner.

Note: The patterns are interpreted as regular expressions. So, if you used special characters like ** and *** (instead of :: and :::) in your invoice template, you have to be careful in Java and should use an escape sequence (like \\*\\* and \\*\\*\\*).



Let’s sum it up a little:

Main.java


import de.nixosoft.jlr.*;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

public class Main {

    public static void main(String[] args) {

        File workingDirectory = new File("C:" + File.separator + "Invoices");

        File template = new File(workingDirectory.getAbsolutePath() + File.separator + "invoiceTemplate.tex");

        File tempDir = new File(workingDirectory.getAbsolutePath() + File.separator + "temp");
        if (!tempDir.isDirectory()) {
            tempDir.mkdir();
        }

        File invoice1 = new File(tempDir.getAbsolutePath() + File.separator + "invoice1.tex");
        File invoice2 = new File(tempDir.getAbsolutePath() + File.separator + "invoice2.tex");


        try {

            HashMap<String, String> data = new HashMap<String, String>();

            data.put("Number", "1");
            data.put("Customer name", "Ivan Pfeiffer");
            data.put("Customer street", "Schwarzer Weg 4");
            data.put("Customer zip", "13505 Berlin");
            data.put("Development", "Software");
            data.put("Price", "500");

            JLRConverter converter = new JLRConverter("::", ":::");
            converter.parse(template, invoice1, data);

            data.put("Number", "2");
            data.put("Customer name", "Mike Mueller");
            data.put("Customer street", "Prenzlauer Berg 12");
            data.put("Customer zip", "10405 Berlin");
            data.put("Development", "Hardware");
            data.put("Price", "2350");

            converter.parse(template, invoice2, data);

        } catch (IOException ex) {
            System.err.println(ex.getMessage());
        }
    }
}

Finally invoice1.tex and invoice2.tex were created.
A look at invoice1.tex proves that all the tags were replaced with your data.

invoice1.tex


\documentclass{letter} 
\usepackage{invoice} 
\address{Josh Parker \\
         5650 Webster Ave \\
         West Palm Beach, Florida 33405 \\
         JParker@mail.com} 
\date{31-May-2010} 

\begin{document} 
\begin{letter}{Ivan Pfeiffer \\ 
               Schwarzer Weg 4 \\ 
               13505 Berlin} 
\opening{Invoice no. 1} 
Dear customer,

... 

\begin{invoice}{Euro}{0} 
\ProjectTitle{Example Project} 
\Fee{Software} {500} {1} 
\end{invoice} 

\closing{Best regards} 
\end{letter} 
\end{document}    



How to use JLR to create a PDF file

The JLRGenerator uses pdfLaTeX and helps to create a PDF file from invoice1.tex and invoice2.tex.
You need to specify an output path for the PDF file and a working directory for pdfLaTeX (where realcalc.tex, invoice.sty and invoice.def lie – it’s important that pdfLaTeX is aware of such files).
In our example the working directory for pdfLaTeX is the same which we already use for the template file (C:\Invoices).

Note: If you use a portable LaTeX distribution, you need the generate()-method of JLRGenerator where you can specify the location of pdfLaTeX.


File desktop = new File(System.getProperty("user.home")	+ File.separator + "Desktop");

JLRGenerator pdfGen = new JLRGenerator();
pdfGen.deleteTempTexFile(false);

pdfGen.generate(invoice1, desktop, workingDirectory);
File pdf1 = pdfGen.getPDF();

pdfGen.generate(invoice2, desktop, workingDirectory);
File pdf2 = pdfGen.getPDF();

By default the input tex file (invoice1.tex / invoice2.tex) will be deleted after generating the pdf file.
To prevent that you have to set deleteTempTexFile(false) at JLRGenerator. We did that already in the example above.
Finally, you can use the JLROpener to launch the associated application and open the PDF files.


JLROpener.open(pdf1);
JLROpener.open(pdf2);




The PDF file of invoice1 should look like:



(invoice1PDF.)





The complete Java sample code (with error check):

Main.java


import de.nixosoft.jlr.*;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

public class Main {

    public static void main(String[] args) {

        File workingDirectory = new File("C:" + File.separator + "Invoices");

        File template = new File(workingDirectory.getAbsolutePath() + File.separator + "invoiceTemplate.tex");

        File tempDir = new File(workingDirectory.getAbsolutePath() + File.separator + "temp");
        if (!tempDir.isDirectory()) {
            tempDir.mkdir();
        }

        File invoice1 = new File(tempDir.getAbsolutePath() + File.separator + "invoice1.tex");
        File invoice2 = new File(tempDir.getAbsolutePath() + File.separator + "invoice2.tex");



        try {

            HashMap<String, String> data = new HashMap<String, String>();

            data.put("Number", "1");
            data.put("Customer name", "Ivan Pfeiffer");
            data.put("Customer street", "Schwarzer Weg 4");
            data.put("Customer zip", "13505 Berlin");
            data.put("Development", "Software");
            data.put("Price", "500");

            JLRConverter converter = new JLRConverter("::", ":::");
            if (!converter.parse(template, invoice1, data)) {
                System.out.println(converter.getErrorMessage());
            }

            data.put("Number", "2");
            data.put("Customer name", "Mike Mueller");
            data.put("Customer street", "Prenzlauer Berg 12");
            data.put("Customer zip", "10405 Berlin");
            data.put("Development", "Hardware");
            data.put("Price", "2350");

            if (!converter.parse(template, invoice2, data)) {
                System.out.println(converter.getErrorMessage());
            }


            File desktop = new File(System.getProperty("user.home") + File.separator + "Desktop");

            JLRGenerator pdfGen = new JLRGenerator();

            pdfGen.deleteTempTexFile(false);

            if (!pdfGen.generate(invoice1, desktop, workingDirectory)) { 
                System.out.println(pdfGen.getErrorMessage());
            }

            JLROpener.open(pdfGen.getPDF());

            if (!pdfGen.generate(invoice2, desktop, workingDirectory)) {
                System.out.println(pdfGen.getErrorMessage());
            }

            JLROpener.open(pdfGen.getPDF());

        } catch (IOException ex) {
            System.err.println(ex.getMessage());
        }
    }
}

© by nixo-soft