Mariusz Prowaźnik

o programowaniu w Javie, Scali i Clojure.


Polskie znaki w pdf z JasperReports

JasperReports to całkiem ciekawe narzędzie do tworzenia raportów w Javie. Jednak można napotkać na problemy z wyświetlaniem polskich znaków w pdf, a w internecie trudno znaleźć działające rozwiązanie. Dlatego zamieszczam przykład.

Korzystałem z:

  • Eclipse Juno
  • Jaspersoft iReport Designer 4.6.0

Krok 1: szablon w iReport

Przy użyciu iReporta stworzyłem bardzo prosty szablon raportu. Dodałem zwykły statyczny tekst, oraz pole w którym będzie się wyświetlać wartość parametru:

Należy pamiętać o dodaniu parametru:

Krok 2: projekt w Eclipse

Stworzyłem prosty projekt, który będzie tworzył raport na podstawie szablonu. Potrzebna będzie zależność w pom.xml:

<dependency>
 <groupId>net.sf.jasperreports</groupId>
 <artifactId>jasperreports</artifactId>
 <version>4.7.1</version>
</dependency>
Szablon powinien być w src/test/resources/badReport.xml. Poniżej fragment testu:
@Test
public void test() throws IOException, JRException {
 final byte[] bytes = getResourceAsByteArray("badReport.xml");
 final DefaultJasperReportsContext context = DefaultJasperReportsContext.getInstance();
 final JasperReport jasperReport = JasperCompileManager.compileReport(new ByteArrayInputStream(bytes));

 Map<String, Object> params = new HashMap<String, Object>();
 params.put("MOJTEKST", "Zażółć gęślą jaźń z parametru");

 final byte[] pdf = JasperRunManager.runReportToPdf(jasperReport, params);
 FileOutputStream fos = new FileOutputStream("C:/report.pdf");
 fos.write(pdf);
 fos.close();
 Runtime.getRuntime().exec(
   "\"C:\\Program Files (x86)\\Foxit Software\\Foxit Reader\\Foxit Reader.exe\"" + " " + "C:/report.pdf");
}

private static byte[] getResourceAsByteArray(String filePath) throws IOException {
 InputStream is = JasperTest.class.getClassLoader().getResourceAsStream(filePath);
 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 byte[] buffer = new byte[1024];
 int read = 0;
 while ((read = is.read(buffer, 0, buffer.length)) != -1) {
  baos.write(buffer, 0, read);
 }
 baos.flush();
 return baos.toByteArray();

Krok 3: usuwamy pierwszy problem

Gdy teraz uruchomimy test, to poleci wyjątek:

java.lang.NoClassDefFoundError: org/codehaus/groovy/control/CompilationFailedException

Rozwiązanie: usunąć atrybut language elementu jasperReport w badReport.xml

language="groovy"

Krok 4: usuwamy kolejny problem

Gdy teraz uruchomimy, raport będzie pustą stroną. By to zmienić dodajemy atrybut elementu jasperReport:

whenNoDataType="AllSectionsNoDetail"

Krok 5: usuwamy problem z czcionkami

Teraz raport będzie się generował prawie normalnie:

Rozwiązanie: dodajemy element reportFont wewnątrz jasperReport:

<reportFont name="Arial_Normal" isDefault="true" fontName="Arial" size="8" pdfFontName="Helvetica" pdfEncoding="Cp1250" isPdfEmbedded="false" />

W rezultacie, raport powinien się generować tak jak należy:

Poczatkowy fragment badReport.xml:

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
 name="polishFonts" pageWidth="595" pageHeight="842" columnWidth="555"
 leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20"
 whenNoDataType="AllSectionsNoDetail">
 <reportFont name="Arial_Normal" isDefault="true" fontName="Arial"
  size="8" pdfFontName="Helvetica" pdfEncoding="Cp1250" isPdfEmbedded="false" />
 <parameter name="MOJTEKST" class="java.lang.String" />

Kod przykładu jest do ściągnięcia tu:

http://evo-java.googlecode.com/svn/jasper-example