Coder Social home page Coder Social logo

devcorkvince / odf-report Goto Github PK

View Code? Open in Web Editor NEW

This project forked from sandrods/odf-report

2.0 1.0 0.0 167 KB

Generates ODF files, given a template (.odt) and data, replacing tags

Home Page: http://sandrods.github.com/odf-report

License: MIT License

odf-report's Introduction

ODF-REPORT

Gem for generating .odt files by making strings, images, tables and sections replacements in a previously created .odt file.

INSTALL

(sudo) gem install odf-report

USAGE

Step 1 — the template

First of all, you need to create a .odt file to serve as a template

Templates are normal .odt files with placeholders for Substitutions

There are now four kinds of substitutions available: fields, tables, images and sections.

Fields placeholders

It’s just an upcase sentence, surrounded by brackets. It will be replaced for wathever value you supply.

In the folowing example:

report = ODFReport::Report.new("Users/john/my_template.odt") do |r|

  r.add_field :user_name, @user.name
  r.add_field :address, "My new address"

end

All occurences of [USER_NAME] found in the file will be replaced by the value of @user.name whereas all [ADDRESS] ’es will contains My new address

It’s as simple as that.

Table placeholders

To use table placeholders, you should create a Table in your document and give it a name. In OpenOffice, it’s just a matter of right-clicking the table you just created, choose Table Properties… and type a name in the Name field.

If you inform :header=>true, the first row will be treated as a header and left untouched. The remaining rows will be used as the template for the table. If you have more than one template row, they will be cycled. This is usefull for making zebra tables.

As with Field placeholders, just insert a [FIELD_NAME] in each cell and let the magic takes place.

Taking the folowing example:

report = ODFReport::Report.new("Users/john/my_template.odt") do |r|

  r.add_field "USER_NAME", @user.nome
  r.add_field "ADDRESS", @user.address

  r.add_table("TABLE_1", @list_of_itens, :header=>true) do |t|
    t.add_column(:item_id, :id)
    t.add_column(:description) do { |item| "==> #{item.description}" }
  end

end

and considering you have a table like this in your template

---------------------------------
|  [ITEM_ID]  |  [DESCRIPTION]  |
---------------------------------

* this is my lame attempt to draw a table.
  you don't suppose to type this.
  you have to use an actual table.
  i don't know... just thought I'd mention it ;-)

and a collection @list_of_itens, it will be created one row for each item in the collection, and the replacement will take place accordingly.

Any format applied to the fields in the template will be preserved.

Images

You must put a mock image in your odt template and give it a name. That name will be used to replace the mock image for the actual image.
You can also assign any properties you want to the mock image and they will be kept once the image is replaced.

An image replace would look like this:

report = ODFReport::Report.new("Users/john/my_template.odt") do |r|

  r.add_image :graphics1, "/path/to/the/image.jpg"

end

Sections (NEW!)

Sometimes, you have to repeat a whole chunk of a document, in a structure a lot more complex than a table. Now you can make a Section in your template and use it in this situations. Creating a Session in OpenOffice is as easy as select menu Insert and then Section…, and then choose a name for it.

Section ’s are lot like Tables, in the sense that you can pass a collection and have that section repeated for each member of the collection. But, Sections can have anything inside it, even Tables, as long as you pass the appropriate data structure.

Let’s see an example:

  @invoices = Invoice.find(:all)

  report = ODFReport::Report.new("reports/invoice.odt") do |r|

    r.add_field(:title, "INVOICES REPORT")
    r.add_field(:date, Date.today)

    r.add_section("SC_INVOICE", @invoices) do |s|

      s.add_field(:number) { |invoice| invoice.number.to_s.rjust(5, '0') }
      s.add_field(:name,    :customer_name)
      s.add_field(:address, :customer_address)

      s.add_table("TB_ITEMS", :items, :header => true) do |t|
        t.add_column(:id)
        t.add_column(:product) {|item| item.product.name }
        t.add_column(:value, :product_value)
      end

      s.add_field(:total) do |invoice|
        if invoice.status == 'CLOSED'
          invoice.total
        else
          invoice.items.sum('product_value')}
        end
      end

    end

  end

Note that when you add a Table to a Section, you don’t pass the collection itself, but the attribute of the item of that section that’s gonna return the collection for that particular Table. Sounds complicated, huh? But once you get it, it’s quite straightforward.

In the above example, s.add_table("TB_ITEMS", :items, :header => true) do |t|, the :items thing refers to a invoice.items. Easy, right?



Step 2 — generating the document

It’s fairly simple to generate the document. You can use this inside a Rails application or in a standalone script.

Generating a document in a Rails application

In a controller, you can have a code like this:

def print

  @ticket = Ticket.find(params[:id])

  report = ODFReport::Report.new("#{RAILS_ROOT}/app/reports/ticket.odt") do |r|

    r.add_field(:id,         @ticket.id.to_s)
    r.add_field(:created_by, @ticket.created_by)
    r.add_field(:created_at, @ticket.created_at.strftime("%d/%m/%Y - %H:%M"))
    r.add_field(:type,       @ticket.type.name)
    r.add_field(:status,     @ticket.status_text)
    r.add_field(:date,       Time.now.strftime("%d/%m/%Y - %H:%M"))
    r.add_field(:solution,   (@ticket.solution || ''))

    r.add_table("OPERATORS", @ticket.operators) do |t|
      t.add_column(:operator_name) { |op| "#{op.name} (#{op.department.short_name})" }
    end

    r.add_table("FIELDS", @ticket.fields) do |t|
      t.add_column(:field_name, :name)
      t.add_column(:field_value) { |field| field.text_value || "Empty" }
    end

  end

  report_file_name = report.generate

  send_file(report_file_name)

end

The generate method will, er… generate the document in a temp dir and returns the full path of the generated file, so you can send it back to the user.

That’s all I have to say about that.

Generating a document in a standalone script

It’s just the same as in a Rails app, but you can inform the path where the file will be generated instead of using a temp dir.

report = ODFReport::Report.new("ticket.odt") do |r|

... populates the report ...

end

report.generate("./documents/")

REQUIREMENTS

rubyzip: for manipulating the contents of the odt file, since it’s actually a zip file.


THE FUTURE

Well, this is my first attempt. This gem was extracted from an actual project we developed internally, to fulfill our specific needs.

That said, I would really appreciate any input you can come up with. Critics, suggestions, bug reports are welcome and will be thoroughly examined.

odf-report's People

Contributors

joseicosta avatar sandrods avatar

Stargazers

 avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.