AXLSX

Vos fichiers xlsx, tout simplement en Ruby

Présentation de Pierre Merlin, le 7 janvier 2012, au Paris.rb

Bonjour

Pierre Merlin, développeur freelance.
e-mail: pierre at apido.org

: Pimpin

I'm a Rugby player ;-)

Le besoin du client :

Je voudrais récupérer mes chiffres de production dans mon tableur.

En CSV

Grâce à la librairie CSV de Ruby 1.9, vous pouvez exporter des données.

Modifiez votre contrôleur,


##/app/controllers/products_controller.rb

class ProductsController < ApplicationController
  def index
    @products = Product.order(:name)
    respond_to do |format|
      format.html
      format.csv { render text: @products.to_csv }
    end
  end
end
            

Equipez votre modèle,


##/app/models/product.rb

class Product < ActiveRecord::Base
  attr_accessible :name, :price, :released_on
  
  def self.to_csv
    CSV.generate do |csv|
      csv << column_names
      all.each do |product|
        csv << product.attributes.values_at(*column_names)
      end
    end
  end
end
            

Et voila !

Oui, mais...

Quand on ouvre la base de donnée ça marche pas. On peut pas faire un fichier Excel "normal"?

OK : on fait du "EXCEL"

On déclare le nouveau type,


##/config/initializers/mime_types.rb

Mime::Type.register "application/xls", :xls
            

on adapte son contrôleur,


##/app/controllers/products_controller.rb

class ProductsController < ApplicationController
  def index
    @products = Product.order(:name)
    respond_to do |format|
      format.html
      format.csv { send_data @products.to_csv }
      format.xls { send_data @products.to_csv(col_sep: "\t") }
    end
  end
end
            

Oui, mais...

C'est pas très joli. Mes colonnes ne s'alignent pas comme il faut etc...

Soit. Développons une mise ne forme plus poussée à l'aide d'un template.

On allège le contrôleur (bonne pratique)


##app/controllers/products.rb

class ProductsController < ApplicationController
  def index
    @products = Product.order(:name)
    respond_to do |format|
      format.html
      format.csv { send_data @products.to_csv }
      format.xls
    end
  end
end
            

en "Excel"

Construire des fichiers EXCEL "à la mano",
Ce n'est pas compliqué : RTFM.

Oui, mais...

Et je peux avoir des couleurs ?
Chaque fois, je fais le même graphique; j'aimerais récupérer un fichier avec ce graphique déjà inclus...
Et ma secrétaire n'a pas de licence Microsoft Excel, ce serait bien qu'elle puisse ouvrir le fichier avec Open Office.

Attention la doc.

AXLSXà la rescousse

fonctionalités :

prise en charge des données formatées en UTF-8

formatage les pourcentage en tant que chiffres, des dates en tant que date etc.

intégration des formules de calcul dans le fichier Excel

création de fichiers avec plusieurs feuilles

Vous en voulez plus ?

édition de graph en battons, camemberts, histogrammes....

insertion d'images

gestion des styles

protection par mot de passe

gestion de la mise en forme pour impression

...

AXLSX en pratique

La base :


p = Axlsx::Package.new
wb = p.workbook
wb.add_worksheet(:name => "Ventes") do |sheet|
  sheet.add_row Product.attribute_name
  @products.each do |product|
    sheet.add_row product.attributes.values
  end
end
p.serialize('ventes.xlsx')

ajoutons du style


p = Axlsx::Package.new
wb = p.workbook

wb.styles do |s|
  black_cell = s.add_style :bg_color => "00", :fg_color => "FF", :sz => 14, :alignment => { :horizontal=> :center }
  blue_cell = s.add_style :bg_color => "0000FF", :fg_color => "FF", :sz => 20, :alignment => { :horizontal=> :center }
end

wb.add_worksheet(:name => "Ventes") do |sheet|
  sheet.add_row Product.attribute_name
  @products.each do |product|
    sheet.add_row product.attributes.values, :style => [black_cell, blue_cell, black_cell]
  end
end
p.serialize('ventes.xlsx')
          

Vous prendrez bien du camembert ?


wb.add_worksheet(:name => "statistiques") do |sheet|
  sheet.add_row ["catégorie"] + sells_by_categorie.map(&:category)
  sheet.add_row ["Volume de vente"] + sells_by_categorie.map(&:amount)

  sheet.add_chart(Axlsx::Pie3DChart,
    :start_at => [0,5],
    :end_at => [10, 20],
    :title => "Répartition des ventes par catégorie") do |chart|
      chart.add_series :data => sheet["B2:B6"],
        :labels => sheet["A2:A6"],
        :colors => ['FF0000', '00FF00', '0000FF']
  end
end
          

Et enfin...

cerise sur le gateau

distribué sous licence MIT

trés bonne couverture

documenté

support actif

intégration continue sur Travis CI


utilisez, contribuez, participez.

Merci

Des questions ?


Crédits et liens utiles: