Статьи

Создавайте великолепные отчеты с JasperReports

JasperReports_Logo

Ruby on Rails — это потрясающая среда для создания веб-приложений. Экосистемы Ruby и Rails очень активны и зрелы, со многими библиотеками для решения различных проблем, с которыми сталкиваются разработчики. Но одной конкретной областью, где я чувствую, что у Руби нет вариантов, является отчетность. В Rails существует множество решений для генерации отчетов, большинство из которых полагаются на генерацию HTML и преобразование в PDF. Этот подход имеет свои преимущества, но не подходит для сложных и точных отчетов.

Войдите в JasperReports . JasperReports — это очень популярная библиотека отчетов с открытым исходным кодом, широко используемая в мире Java. Многим из вас может быть интересно узнать, как использовать библиотеку Java в Rails. Есть много подходов, но я предпочитаю использовать JRuby. Это требует от вас преобразования вашего приложения в JRuby, что довольно просто сделать в наши дни. Итак, начнем.

Пример приложения Rails

Мы создадим пример приложения на Rails с моделью контакта и действиями CRUD. Приложение будет использовать JRuby, Rails 4.2 и SQLite в качестве базы данных для простоты. Прежде всего, установите JRuby с помощью RVM или rbenv .

Переключитесь на JRuby и в bundle install последнюю версию Rails gem. Теперь создайте новое приложение Rails, вот так:

 rails new contactbook 

После того, как приложение сгенерировано, создайте скаффолд Contact, который выполняет операции с ресурсами amodel и CRUD:

 cd contactbook rails g scaffold Contact name:string address:string city:string phone:string email:string 

Теперь перенесите базу данных:

 rake db:migrate 

Давайте проверим, как это работает:

 rails s 

Направьте ваш любимый браузер на http: // localhost: 3000 / contacts и убедитесь, что все работает правильно. Создайте несколько записей, чтобы мы могли использовать их позже.

Пример JasperReport

Давайте создадим простой отчет, который показывает список контактов. Загрузите JasperSoft Studio, подходящую для вашей платформы, с сайта Jaspersoft Studio . Установите и запустите Jaspersoft Studio. Это полноценная IDE, основанная на Eclipse, специально для разработки JasperReports. Конечно, у него есть кривая обучения, но мы пока не будем вдаваться в эти детали. Вы можете обратиться к Jaspersoft Studio — Ресурсы для получения дополнительной информации.

С помощью Jaspersoft Studio создайте отчет с именами contacts который должен выглядеть следующим образом:

Jaspersoft-студия

Скомпилируйте отчет и вставьте файл contacts.jasper в app / reports / нашего приложения Rails.

Интеграция JasperReports

Теперь важная часть — интеграция JasperReports в приложение Rails. Мы будем использовать версию JasperReports 6.1 для этого урока. jasperreports-6.1.0-project.tar.gz страницу библиотеки JasperReports и загрузите jasperreports-6.1.0-project.tar.gz . Этот архив содержит JAR-файлы JasperReports в своей папке dist , а также зависимости в папке lib . Скопируйте все файлы из обеих этих папок и поместите их в папку с именем jasperreports в каталоге lib в нашем приложении Rails.

 contactbook - app ... - lib - jasperreports - jasperreports-6.1.0.jar ... 

У нас есть все необходимые файлы для JasperReports, поэтому давайте создадим класс для интеграции JasperReports. Создайте файл с именем jasper_report.rb в каталоге lib со следующим кодом:

 Dir.entries("#{Rails.root}/lib/jasperreports").each do |lib| require "jasperreports/#{lib}" if lib =~ /\.jar$/ end require 'java' java_import Java::net::sf::jasperreports::engine::JasperFillManager java_import Java::net::sf::jasperreports::engine::JasperExportManager java_import Java::net.sf.jasperreports.engine.JRResultSetDataSource class JasperReport DIR = "#{Rails.root}/app/reports" def initialize(report, query, params = nil) @model = report @report_params = params @conn = ActiveRecord::Base.connection.jdbc_connection @query = query end def to_pdf stmt = @conn.create_statement @result = JRResultSetDataSource.new(stmt.execute_query(@query)) report_source = "#{DIR}/#{@model}.jasper" raise ArgumentError, "#@model does not exist." unless File.exist?(report_source) params = {} params.merge!(@report_params) if @report_params.present? fill = JasperFillManager.fill_report(report_source, params, @result) pdf = JasperExportManager.export_report_to_pdf(fill) return String.from_java_bytes(pdf) end end 

Давайте посмотрим, что на самом деле делает код. Сначала нам нужны все файлы JasperReports в наш класс, например так:

 Dir.entries("#{Rails.root}/lib/jasperreports").each do |lib| require "jasperreports/#{lib}" if lib =~ /\.jar$/ end 

Добавьте объявления импорта Java для JasperReports:

 require 'java' java_import Java::net::sf::jasperreports::engine::JasperFillManager java_import Java::net::sf::jasperreports::engine::JasperExportManager java_import Java::net.sf.jasperreports.engine.JRResultSetDataSource 

Определите место, где будут храниться все отчеты:

 DIR = "#{Rails.root}/app/reports" 

Добавьте код инициализации в конструктор класса:

 def initialize(report, query, params = nil) @model = report @report_params = params @conn = ActiveRecord::Base.connection.jdbc_connection @query = query end 

В качестве первого шага мы инициализировали все необходимые переменные:

  • Имя файла reportreport
  • SQL-запрос отчета — query
  • Любые необязательные параметры для передачи в отчет — params

@conn — это соединение JDBC из пула соединений ActiveRecord, поскольку JasperReports требует соединения JDBC для выполнения запроса.

Наконец, мы добавили метод для заполнения и экспорта отчета в формат PDF:

 def to_pdf stmt = @conn.create_statement @result = JRResultSetDataSource.new(stmt.execute_query(@query)) report_source = "#{DIR}/#{@model}.jasper" raise ArgumentError, "#@model does not exist." unless File.exist?(report_source) params = {} params.merge!(@report_params) if @report_params.present? fill = JasperFillManager.fill_report(report_source, params, @result) pdf = JasperExportManager.export_report_to_pdf(fill) return String.from_java_bytes(pdf) end 

Первым элементом является оператор JDBC stmt = @conn.create_statement , который возвращает JDBC ResultSet путем выполнения @result = JRResultSetDataSource.new(stmt.execute_query(@query)) . Файл отчета ( .jasper ), созданный ранее с использованием JasperStudio, имеет значение report_source . После этого вызовите JasperFillManager.fill_report чтобы заполнить отчет предоставленными ResultSet и параметрами. Наконец, вызовите JasperExportManager.export_report_to_pdf чтобы экспортировать отчет в поток PDF, который возвращается с использованием String.from_java_bytes .

Теперь у нас есть отчет в формате PDF, но у нас пока нет возможности отправить его пользователю. Итак, добавьте небольшой вспомогательный метод в application_controller.rb следующим образом:

 def respond_to_report(name, query, filename, download = false, report_params = nil) @report = JasperReport.new(name, query, report_params) disposition = (download.nil? || download == false) ? 'inline' : 'attachment' send_data @report.to_pdf, :filename => filename, :type => :pdf, :disposition => disposition end 

Этот вспомогательный метод упрощает вызов отчета и отправляет ответ обратно пользователю. Также добавлены параметры для предоставления имени файла, наряду с возможностью disposition чтобы открыть файл в браузере или загрузить его как вложение.

Теперь мы добавим действие в ContactsController который вызывает отчет. Добавьте следующий код в app / controllers / contacts_controller.rb :

 def report respond_to_report('contacts', 'select * from contacts', 'contacts.pdf') end 

Поскольку у нас нет параметров для передачи и мы хотим открыть отчет в браузере, мы пропустили download и report_params из вызова метода.

Обновите route.rb, чтобы добавить новое действие:

 resources :contacts do get :report, on: :collection end 

Добавьте ссылку на отчет в представлении contacts / index.html.erb :

 ... <h1>Listing Contacts</h1> <%= link_to 'Download as PDF', report_contacts_path %> ... 

Запустите сервер и перейдите по адресу http: // localhost: 3000 / contacts . Нажмите «Скачать в формате PDF». Теперь вы должны увидеть файл PDF со всеми контактами в списке.

заключительный отчет

Завершение

Это был краткий пример того, как интегрировать JasperReports с Rails для создания отчетов без особых усилий. С помощью JasperReports и Rails можно сделать гораздо больше, например, критерии поиска, сложные отчеты, подотчеты и т. Д. Но это для другого учебника.

Я надеюсь, вам понравился этот пост. Ваши комментарии и идеи всегда приветствуются.