Juno Report

Cry with Report Generation? Nevermore!

Installation

Add this line to your application's Gemfile:

gem 'juno-report'

And then execute:

$ bundle

Or install it yourself as:

$ gem install juno-report

Usage

The generating reports is based on a YAML file with all rules, with the fields and their settings, divided by sections.

Body section

Represents the records which will be iterated to report generating

# example.yml
body:
  settings: {posY: 40, height: 25}
  fields:
    test_field1: [10]
    test_field2: [220]
    test_field3: [430, {column: "Named Test Field 3"}]
  footer:
    label_total: [10, {value: "Total"}]
    totalizer: [220, {behavior: count}]
    test_field3: [430, {behavior: sum}]

The [body] section must have three rules:

  • settings: Defines some configurations for body, like their height and ypos.
  • fields: Describes each field of record to be iterated.
  • footer: Drawn at the end of all printed records and calculates fields according behavior parameter.

Each of these rules receives a array, where the first position is an integer representing the field horizontal position and the second position is a hash with some configurations.

Settings
  • height: Set the of each row at report [Integer].
  • posY: Relative vertical position of last row at report [Integer].
  • groups: Describes which groups will be printed (More bellow) [Array].
Fields
  • size: Font size of the field [Integer].
  • align: Defines the text alignment for each value [left|center|right].
  • font: Supports all font type provided by Prawn gem (See more in http://rubydoc.info/gems/prawn/Prawn/Font/AFM).
  • style: Stylistic variations of a font [bold|italic].
  • value: Fixed text to be printed [string].
  • column: The header are "humanized" automatically, but you can set other value manually [string].
  • behavior: Specify a function to be performed, sending as parameter the fieldname value [string].
  • label: Preppends a text to fieldname value specified [string].
  • value: Fixed text to be printed (fieldname value will be ignored) [string].

With theses configurations already is possible generate a basic report, without groups feature. For this we need call the generate method on JunoReport module:

# test.rb
require 'juno-report'

data = [
    {:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 50},
    {:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 7},
    {:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 10},
    {:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 5},
    {:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 2},
    {:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 4},
    {:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 24}
]

JunoReport::generate(data, :report => 'example')

The first parameter must be a set of hash or objects which represent the report data. And the second parameter is a hash with the report settings, that can be:

  • report: The source of all rules. Must be a YAML file [string].
  • type: Specify if the report will be writed on the disc or returned to the caller such a stream [:file|:stream]
  • filename: Defines the report name which will be writed on disc. If not specified, the default name is "report.pdf" [string].

Page section

You may want to print a title every time that a page is created. You simply insert a [page] section.

# example.yml
page:
  fields:
    title1: [260, {size: 24, align: center, value: "Test Report"}]
    subtitle1: [260, {size: 20, posY: 20, align: center, value: "Generated by Juno Report"}]
body:
  settings: {posY: 40, height: 25}
  fields:
    test_field1: [10]
    test_field2: [220]
    test_field3: [430, {column: "Named Test Field 3"}]
  footer:
    label_total: [10, {value: "Total"}]
    totalizer: [220, {behavior: count}]
    test_field3: [430, {behavior: sum}]

Groups section

For each item in groups parameter at body section you should create a section with same name. This section represents the header configurations to every time that the group is printed and behaves like [body] section.

# example.yml
page:
  fields:
    title1: [260, {size: 24, align: center, value: "Test Report"}]
    subtitle1: [260, {size: 20, posY: 20, align: center, value: "Generated by Juno Report"}]
body:
  settings: {posY: 40, height: 30, groups: [group_field1, group_field2]}
  fields:
    test_field1: [10]
    test_field2: [220]
    test_field3: [420, {column: "Named Test Field 3"}]
  footer:
    label_total: [10, {value: "Total"}]
    totalizer1: [220, {behavior: count}]
    test_field3: [420, {behavior: sum}]
group_field1:
  settings: {posY: 30, height: 10}
  fields:
    group_field1: [10, size: 25]
  footer:
    group_field1: [10, {label: "Total "}]
    totalizer1: [220, {behavior: count}]
    test_field3: [420, {behavior: sum}]
group_field2:
  settings: {posY: 30, height: 25}
  fields:
    group_field2: [10, size: 17]
  footer:
    group_field2: [10, {label: "Total "}]
    totalizer1: [220, {behavior: count}]
    test_field3: [420, {behavior: sum}]

Every time that a "group field" value changes, the group will be printed.

# test.rb
require 'juno-report'

data = [
    {:test_field1 => 'Test Value 1', :test_field2 => "Test Value 1", :test_field3 => 50, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 1'},
    {:test_field1 => 'Test Value 2', :test_field2 => "Test Value 2", :test_field3 => 16, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 1'},
    {:test_field1 => 'Test Value 5', :test_field2 => "Test Value 3", :test_field3 => 7, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 1'},
    {:test_field1 => 'Test Value 3', :test_field2 => "Test Value 9", :test_field3 => 10, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 2'},
    {:test_field1 => 'Test Value 3', :test_field2 => "Test Value 2", :test_field3 => 4, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 2'},
    {:test_field1 => 'Test Value 9', :test_field2 => "Test Value 4", :test_field3 => 10, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 2'},
    {:test_field1 => 'Test Value 7', :test_field2 => "Test Value 5", :test_field3 => 5, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 3'},
    {:test_field1 => 'Test Value 3', :test_field2 => "Test Value 5", :test_field3 => 2, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 3'},
    {:test_field1 => 'Test Value 3', :test_field2 => "Test Value 2", :test_field3 => 27, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
    {:test_field1 => 'Test Value 3', :test_field2 => "Test Value 5", :test_field3 => 2, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
    {:test_field1 => 'Test Value 0', :test_field2 => "Test Value 4", :test_field3 => 13, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
    {:test_field1 => 'Test Value 4', :test_field2 => "Test Value 7", :test_field3 => 7, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
    {:test_field1 => 'Test Value 1', :test_field2 => "Test Value 3", :test_field3 => 28, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
    {:test_field1 => 'Test Value 4', :test_field2 => "Test Value 5", :test_field3 => 4, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 2'},
    {:test_field1 => 'Test Value 5', :test_field2 => "Test Value 6", :test_field3 => 24, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 2'}
]

JunoReport::generate(data, :report => 'example', :filename => 'juno-report.pdf')

Contributors

  1. Edson JĂșnior (http://github.com/ebfjunior)

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request