Топ контрибуторов
loading
loading
Знаете ли Вы, что

Свои вопросы для тестов можно добавлять на странице с информацией о тесте. При этом для некоторых тестов добавление вопросов закрыто

Лента обновлений
ссылка 09:06:04
Комментарий от alex2005:
значение счётчика увеличивается после присвоения
ссылка Jun 17 08:57
Добавлен вопрос в тест HTML - Средний уровень
ссылка Jun 16 19:14
Комментарий от borgir:
Спасибо
ссылка Jun 16 18:49
Комментарий от vovannna:
public class LESSONS {
private int value = 1;

...
ссылка Jun 15 11:12
Комментарий от uuoweznv:
Присоединяюсь к предыдущим ораторам!
Что такое дополнит...
Статистика

Тестов: 153, вопросов: 8595. Пройдено: 435444 / 2136357.

JasperReports & iReport

head tail Статья
дата17.12.2014
авторHeorhi_Puhachou
голосов10

Предисловие

В этой статье будет показан простой способ для генерации отчётов в удобочитаемом формате при помощи приложения написанного на Java. Для этого придётся скачать библиотеку jasperreports (при написании статьи использовалась версия 5.6.1) и необходимые для неё зависимости:

  • commons-digester-2.1.jar
  • org.apache.commons.collections.jar
  • org.apache.commons.beanutils.jar
  • commons-logging-1.2.jar
  • com.lowagie.text-2.1.7.jar

Рабочий проект со всеми библиотеками можно скачать отсюда - https://github.com/Heorhi-Puhachou/JasperReports-iReport

Также понадобится программа iReport (iReport-Designer for JasperReports) для формирования jrxml-шаблона. Её можно не качать и просто воспользоваться уже готовыми шаблонами из проекта (но так не интересно).

Немного терминологии

JasperReports – Java-библиотека, которая позволяет на основе jrxml-шаблонов (JasperReports XML) и набора данных (которые могут быть получены из БД) создавать отчёты в различных форматах.
iReport – приложение для создания jrxml-шаблонов.

Базовая структура приложения

В приложении для генерации отчётов можно выделить 4 основные части:

  • базовая сущность, которая описывает основные характеристики единицы данных;
  • источник данных;
  • шаблон, для заполнения данными;
  • генератор отчёта.

Данное разбиение не является каноническим, но по нему будет написан пример. Базовой сущности, источнику данных и генератору будет соответствовать по одному java-классу. В качестве шаблона будет использован один файл с расширением .jrxml.

Базовая сущность

Допустим нам необходимо создать отчёт о студентах и их пропусках по различным предметам (пример заезженный, но простой). Тогда пусть класс, содержащий информацию о пропусках будет иметь 3 поля: имя студента, название дисциплины, количество пропущенных часов и соответствующие геттеры-сеттеры. Код класса DataBean:


package com.heorhi.jr.sample;

public class DataBean {
	private String name;
	private String discipline;
	private Integer absence;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDiscipline() {
		return discipline;
	}

	public void setDiscipline(String discipline) {
		this.discipline = discipline;
	}

	public Integer getAbsence() {
		return absence;
	}

	public void setAbsence(Integer absence) {
		this.absence = absence;
	}
}

Источник данных

Цель данной статьи вовсе не в том, чтобы показать, как подключаться к БД. Будем использовать заглушку – DAOStub:


package com.heorhi.jr.sample;

import java.util.ArrayList;

public class DAOStub {

	public ArrayList<databean> getDataBeanList() {
		ArrayList<databean> dataBeanList = new ArrayList<databean>();
		DataBean tempBean = new DataBean();
		tempBean.setName("Петя");
		tempBean.setDiscipline("Физика");
		tempBean.setAbsence(2);
		dataBeanList.add(tempBean);

		tempBean = new DataBean();
		tempBean.setName("Вася");
		tempBean.setDiscipline("История");
		tempBean.setAbsence(3);
		dataBeanList.add(tempBean);

		tempBean = new DataBean();
		tempBean.setName("Ира");
		tempBean.setDiscipline("English");
		tempBean.setAbsence(5);
		dataBeanList.add(tempBean);

		return dataBeanList;
	}
}

Генератор

Генератор отчёта будет посложнее предыдущих 2-ух классов:


package com.heorhi.jr.sample;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

public class Generator {

	String pathForSaving = "D:\\Free time\\TestResult.pdf";
	String pathForPattern = "D:\\Free time\\workspace\\JasperReports-iReport\\ReportGenerator\\jrxml\\first_template.jrxml";

	public void create() throws JRException {
		DAOStub dataBeanMaker = new DAOStub();
		ArrayList<databean> dataBeanList = dataBeanMaker.getDataBeanList();
		JRBeanCollectionDataSource beanColDataSource = new JRBeanCollectionDataSource(dataBeanList);
		Map<String, Object> parameters = new HashMap<String, Object>();
		parameters.put("DATE", new Date());
		File reportPattern = new File(pathForPattern);
		JasperDesign jasperDesign = JRXmlLoader.load(reportPattern);
		JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
		JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport,
				parameters, beanColDataSource);
		JasperExportManager.exportReportToPdfFile(jasperPrint, pathForSaving);
	}

	public static void main(String[] args) {
		System.out.println("Начало генерации отчёта");
		try {
			new Generator().create();
			System.out.println("Генерация отчёта завершена");
		} catch (Exception e) {
			System.out.println("Во время генерации возникла ошибка: " + e);
		}
	}
}

Переменная pathForSaving содержит путь к конечному файлу, который будет являеться результатом генерации отчёта, pathForPattern содержит путь к шаблону. Далее идёт получение данных из DAOStub, которые помещаются в список dataBeanList с. Этот список «оборачивается» в JRBeanCollectionDataSource (у него есть конструктор, способный принимать всё, что унаследовано от Collection). После идёт создание Map, для хранения параметров (в контексте шаблона – это константы). Параметр будет один – дата генерации отчёта. Далее идёт загрузка шаблона, его компиляция, соединение скомпилированного отчёта, параметров и данных в переменной jasperPrint и экспорт полученного коктейля по указанному пути; exportReportToPdfFile - для создания pdf-файла, но JasperReports не ограничен одним лишь этим форматом, при использовании других форматов важно не забыть поставить правильное расширение файла (.pdf) в pathForSaving, чтобы не было проблем с открытием файлам. Всё очень здорово, но нам нужен шаблон first_template.jrxml. Его создание описано ниже.

JRXML-Шаблон

По сути наш шаблон – это XML, оформленный в виде, читаемом JasperReports. Т.е. его можно написать и руками в текстовом редакторе, но проще будет использовать iReport (при написании статьи использовался Jasper iReport Designer версии 5.6.0).

Если iReport уже установлен, то заходим во вкладку File и выбираем New… Должно появится такое окно

iReport

Жмём Launch Report Wizard

Launch Wizard

Зададим имя (first_template) и положение шаблона. У меня он размещён в папке jrxml, которая находится в корне проекта. Остальные шаги пропускаем (много раз жмём Next и потом Finish). Появится заготовка:

заготовка

Первое, что стоит сделать – нажать на корневой элемент в Report Inspector и в панели Properties найти параметр Language и выбрать Java (у меня по умолчанию стоял Groovy). Далее удаляем элементы Page Header, Column Header и т.д. Нам понадобятся только Title и Detail1. Должно получится как-то так:

Report Inspector

Теперь добавим поля для данных о пропусках :

поля

У нас это: String name, String discipline и Integer absence:



Не забываем выбрать нужный тип:



По аналогии с полями добавим параметр (Parameters).



Для того, чтобы отобразить эти данные в отчёте можно использовать различные элементы. Просмотреть на них можно во вкладке Palette:


Мы воспользуемся только одним – TextField. Просто перетаскиваем и размещаем один в Title (для даты) и три в Detail1 (для полей объектов с данными).



Ниже показано примерное размещение ячеек и то, как надо эти ячейки заполнить:



$P означает, что далее в фигурных скобках будет указан параметр, $F – поле (field). В секции Title для ячейки удалим значение по умолчанию и запишем $P{DATE}. На рисунке выше видно, как должно выглядеть некоторые параметры в Properties (здесь можно видеть задание формата для вывода даты). Для трёх ячеек полей просто правильно указываем значения: $F{name}, $F{discipline}, $F{absence}.

То, что уже сделано можно сохранить и запустить приложение для генерации отчёта. Однако то, что получится будет выглядеть… Плохо.

2 проблемы:

  • не видны границы ячеек;
  • не отображаются русские символы;

Возвращаемся в редактор, выделяем 3 ячейки ($F{name}, $F{discipline}, $F{absence}) и переходим в меню редактирования полей и отступов:



Выбираем 4 границы и задаём им ненулевую толщину:

15

Относительно русских символов – необходимо навязать использование подходящего шрифта (у меня в папке проекта, рядом с папкой jrxml лежит папка font, содержащая ARIAL.TTF) и подходящей кодировки. Для этого создадим стиль:



Стилю можно задать ему имя, можно оставить то, что по умолчанию. Далее выбираем чек-бокс Default Style (чтобы стиль использовался по умолчанию) и задаём параметр Pdf Encoding – Cp1251 (Cyrillic). Параметр Pdf Font name можно выбрать только из ограниченного списка шрифтов, поэтому перейдём в режим редактирования XML:



Здесь руками пропишем этот параметр и путь к шрифту. Т.к. у меня шрифт лежит в папке, которая является соседней к папке с шаблоном, то сначала используется символ точки для перехода на верхний уровень, а потом имя папки со шрифтом и имя шрифта:


Конечный 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="first_template" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="b72c2c80-9324-4359-a0b4-1feff9ba2ede">
	<property name="ireport.zoom" value="1.0"/>
	<property name="ireport.x" value="0"/>
	<property name="ireport.y" value="0"/>
	<style name="Default" isDefault="true" pdfEncoding="Cp1251" pdfFontName="./font/ARIAL.TTF"/>
	<parameter name="DATE" class="java.util.Date"/>
	<field name="name" class="java.lang.String"/>
	<field name="discipline" class="java.lang.String"/>
	<field name="absence" class="java.lang.Integer"/>
	<title>
		<band height="20" splitType="Stretch">
			<textField>
				<reportElement x="0" y="0" width="555" height="20" uuid="eb16ce83-eea5-4eca-b6a2-c14149019045"/>
				<textFieldExpression><![CDATA[$P{DATE}]]></textFieldExpression>
				<patternExpression><![CDATA["dd.MM.yyyy HH.mm"]]></patternExpression>
			</textField>
		</band>
	</title>
	<detail>
		<band height="20" splitType="Stretch">
			<textField>
				<reportElement x="213" y="0" width="183" height="20" uuid="1adc41ce-7c09-46fe-960a-dff145ad7e50"/>
				<box>
					<topPen lineWidth="1.0"/>
					<leftPen lineWidth="1.0"/>
					<bottomPen lineWidth="1.0"/>
					<rightPen lineWidth="1.0"/>
				</box>
				<textFieldExpression><![CDATA[$F{discipline}]]></textFieldExpression>
			</textField>
			<textField>
				<reportElement x="0" y="0" width="213" height="20" uuid="2f5d59ad-6924-492a-b5c4-f9705cc23650"/>
				<box>
					<topPen lineWidth="1.0"/>
					<leftPen lineWidth="1.0"/>
					<bottomPen lineWidth="1.0"/>
					<rightPen lineWidth="1.0"/>
				</box>
				<textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
			</textField>
			<textField>
				<reportElement x="396" y="0" width="159" height="20" uuid="7f824851-c67d-41c9-ba98-6ab57aa00d47"/>
				<box>
					<topPen lineWidth="1.0"/>
					<leftPen lineWidth="1.0"/>
					<bottomPen lineWidth="1.0"/>
					<rightPen lineWidth="1.0"/>
				</box>
				<textFieldExpression><![CDATA[$F{absence}]]></textFieldExpression>
			</textField>
		</band>
	</detail>
</jasperReport>

Итог

После сохранения шаблона и запуска генератора получим вот такой отчёт:



Может показаться, что затраченные усилия не стоили результата, но это только верхушка айсберга. Можно делать гораздо более красивые и интересные вещи, а в данной статье показаны только минимальные возможности связки JasperReports и iReport.

При желании можно группировать данные, задавать в шаблоне логику для различных вычислений (что лично я не очень люблю делать), строить графики и т.д. и т.п. Если это Вам интересно, можете прочитать продолжение этой статьи - http://www.quizful.net/post/jasperreports-and-ireports-part2

На этом все. Надеюсь, данная статья была полезной.

Если Вам понравилась статья, проголосуйте за нее

Голосов: 10  loading...
Grishman   vpravo   jobvms   capslock270790   Alibek7000   javadev75   GalinaU   stasyan72   slokoz   kraspu