.. _gs3_jasper_template: JasperReport-шаблоны (``.jrxml``) ================================== JasperReport-шаблон — zip-архив с разметкой отчёта и, при необходимости, со скомпилированными скриптлетами и собственными библиотеками. В отличие от остальных форматов, логика шаблона пишется на Java: подстановки и агрегаты вычисляются выражениями Jasper, а более сложные вычисления выносятся в скриптлет. Шаблоны редактируются в :term:`Jaspersoft® Studio 6.20` и хранятся в базе данных вместе с остальными печатными формами. Состав архива ------------- .. list-table:: :header-rows: 1 :widths: 25 75 * - Содержимое - Назначение * - ``main.jrxml`` - Главный файл шаблона. Имя фиксировано и задаётся константой ``JRUtils.TEMPLATE_MAIN_FILE_NAME``; с него начинается компиляция. * - прочие ``*.jrxml`` - Подотчёты, подключаемые из главного файла. * - ``*.class`` - Скомпилированные скриптлеты. Ищутся и в корне архива, и в каталоге ``bin`` — туда их складывает :term:`Jaspersoft® Studio 6.20`. * - ``*.jar`` - Собственные библиотеки шаблона. Перед заполнением распаковываются рядом с архивом и добавляются в загрузчик классов скриптлетов. Скомпилированный шаблон кэшируется: при повторном построении отчёта компиляция ``.jrxml`` не выполняется. Скриптлеты ---------- Скриптлет объявляется в шаблоне и вызывается через параметр ``$P{<имя скриптлета>_SCRIPTLET}``: .. code-block:: xml ... Класс скриптлета загружается отдельным загрузчиком, родителем которого выступает загрузчик :term:`сервера приложений <Сервер приложений>`. Поэтому скриптлету доступны библиотеки самого сервера, а не только те, что лежат в архиве шаблона. Пропись чисел и сумм -------------------- Для прописи в загрузчике сервера лежат две библиотеки: ``ru.bitec:numbertostr`` (пропись числа) и ``com.github.javadev:moneytostr`` (пропись денежной суммы, вызывается через обёртку ``ru.bitec.numbertostr.MoneyToStr``). .. list-table:: :header-rows: 1 :widths: 55 45 * - Метод - Результат * - ``NumberToStr.spellout(Locale, BigDecimal)`` - Число прописью набором правил локали по умолчанию: ``8421.54`` → «восемь тысяч четыреста двадцать одна целая пятьдесят четыре сотых». * - ``NumberToStr.spelloutCardinalFeminine(Locale, BigDecimal)`` - Число прописью женским родом: ``21`` → «двадцать одна» вместо «двадцать один». * - ``MoneyToStr.spellout(BigDecimal, Currency, Language, PennyShowType)`` - Денежная сумма: ``8421.54`` → «восемь тысяч четыреста двадцать один рубль 54 копейки». Параметры ``MoneyToStr.spellout``: .. list-table:: :header-rows: 1 :widths: 25 75 * - Параметр - Значения * - ``Currency`` - ``RUR``, ``UAH``, ``USD``, ``EUR`` * - ``Language`` - ``RUS``, ``UKR``, ``ENG`` * - ``PennyShowType`` - ``NUMBER`` — копейки цифрами, ``TEXT`` — копейки прописью, ``NONE`` — без копеек Точность ~~~~~~~~ Библиотека печатает то значение, которое ей передали: величина не округляется и не подгоняется под точность ``double``. Ограничение ровно одно — словарь разрядов, которым она располагает: - дробная часть длиннее одиннадцати знаков округляется (``HALF_UP``): для более мелких разрядов слов нет, последний — «стомиллиардная»; - число, у которого целая часть достигла 10\ :sup:`18`, печатается цифрами целиком: словарь разрядов кончился, а смешивать цифры и слова в одной строке нельзя. Что передавать на вход ~~~~~~~~~~~~~~~~~~~~~~ .. warning:: Передача числа, прошедшего через ``double``, искажает пропись: дробное значение в ``double`` хранится приближённо, и это приближение читается словами. .. code-block:: text new BigDecimal("12345678.9") двенадцать миллионов … восемь целых девять десятых new BigDecimal(12345678.9) двенадцать миллионов … восемь целых девяносто миллиардов тридцать семь стомиллиардных Библиотека такой вход не вычищает и печатает ровно то значение, которое получила. По цифрам в форме расхождение не видно — там число выглядит правильно, расходится только пропись. Точность сохраняется при следующих условиях: - колонка в базе — точный десятичный тип (``numeric``), не ``double precision`` и не ``real``, и в запросе шаблона она не приводится к плавающему типу; - поле и итоговая переменная объявлены как ``java.math.BigDecimal``, не ``java.lang.Double``; - значение передаётся в скриптлет напрямую, без ``new BigDecimal(...)`` вокруг него. .. code-block:: xml .. note:: Функция макроязыка ``NumberToStrRUS(attr)`` из :ref:`TXT- ` и :ref:`Excel-шаблонов ` — независимая реализация внутри сервера. Она работает только с целыми числами: дробное значение приводит к ошибке построения отчёта. Пример ------ Скриптлет: .. code-block:: java import net.sf.jasperreports.engine.JRDefaultScriptlet; import net.sf.jasperreports.engine.JRScriptletException; import ru.bitec.numbertostr.NumberToStr; import java.math.BigDecimal; import java.util.Locale; public class SpelloutScriptlet extends JRDefaultScriptlet { public String numberToStrRu(BigDecimal npSum) throws JRScriptletException { return NumberToStr.spellout(new Locale("ru"), npSum); } } Шаблон — итог по количеству прописью: .. code-block:: xml Результат для итога ``8816.22``:: Итого: восемь тысяч восемьсот шестнадцать целых двадцать две сотых .. seealso:: - :ref:`Отчеты ` — хранение шаблонов, запуск построения, события строителя отчётов. - :ref:`REST-сервис отчётов `. - :java:type:`ru.bitec.gtk.core.report.CoreReportBuilder` — построение отчёта из прикладного кода.