Question

J'ai une table de base de données simple appelée "Entrées":

class CreateEntries < ActiveRecord::Migration
  def self.up
    create_table :entries do |t|
      t.string :firstName
      t.string :lastName
      #etc.
      t.timestamps
    end
  end

  def self.down
    drop_table :entries
  end
end

Comment puis-je écrire un gestionnaire qui renvoie le contenu du tableau Entries sous forme de fichier CSV (idéalement de manière à ce qu'il s'ouvre automatiquement dans Excel)?

class EntriesController < ApplicationController

  def getcsv
    @entries = Entry.find( :all )

    # ??? NOW WHAT ????

  end

end
Était-ce utile?

La solution

Il existe un plugin appelé FasterCSV qui gère cela à merveille.

Autres conseils

FasterCSV est certainement la voie à suivre, mais si vous souhaitez le servir directement depuis votre application Rails, vous voudrez également configurer des en-têtes de réponse.

Je garde une méthode pour configurer le nom du fichier et les en-têtes nécessaires:

def render_csv(filename = nil)
  filename ||= params[:action]
  filename += '.csv'

  if request.env['HTTP_USER_AGENT'] =~ /msie/i
    headers['Pragma'] = 'public'
    headers["Content-type"] = "text/plain" 
    headers['Cache-Control'] = 'no-cache, must-revalidate, post-check=0, pre-check=0'
    headers['Content-Disposition'] = "attachment; filename=\"#{filename}\"" 
    headers['Expires'] = "0" 
  else
    headers["Content-Type"] ||= 'text/csv'
    headers["Content-Disposition"] = "attachment; filename=\"#{filename}\"" 
  end

  render :layout => false
end

En utilisant cela, il est facile d'avoir quelque chose comme ça dans mon contrôleur:

respond_to do |wants|
  wants.csv do
    render_csv("users-#{Time.now.strftime("%Y%m%d")}")
  end
end

Et obtenez une vue ressemblant à ceci: ( generate_csv provient de FasterCSV)

UserID,Email,Password,ActivationURL,Messages
<%= generate_csv do |csv|
  @users.each do |user|
    csv << [ user[:id], user[:email], user[:password], user[:url], user[:message] ]
  end
end %>

J'ai accepté (et voté!) @ La réponse de Brian, pour m'avoir d'abord dirigé vers FasterCSV. Ensuite, lorsque j'ai cherché sur Google pour trouver la gemme, j’ai également trouvé un exemple assez complet sur cette page wiki . En les assemblant, j'ai choisi le code suivant.

Au fait, la commande pour installer la gem est la suivante:     sudo bijou installer plus vite (tous en minuscules)

require 'fastercsv'

class EntriesController < ApplicationController

  def getcsv
      entries = Entry.find(:all)
      csv_string = FasterCSV.generate do |csv| 
            csv << ["first","last"]
            entries.each do |e|
              csv << [e.firstName,e.lastName]
            end
          end
          send_data csv_string, :type => "text/plain", 
           :filename=>"entries.csv",
           :disposition => 'attachment'

  end


end

Une autre façon de faire cela sans utiliser FasterCSV:

Requiert la bibliothèque csv de ruby ??dans un fichier d'initialisation tel que config / initializers / dependencies.rb

require "csv"

Comme référence, le code suivant est basé sur le formulaire de recherche avancée de Ryan Bate qui crée une ressource de recherche. . Dans mon cas, la méthode show de la ressource de recherche renverra les résultats d'une recherche précédemment enregistrée. Il répond également au format csv et utilise un modèle de vue pour formater la sortie souhaitée.

  def show
    @advertiser_search = AdvertiserSearch.find(params[:id])
    @advertisers = @advertiser_search.search(params[:page])
    respond_to do |format|
      format.html # show.html.erb
      format.csv  # show.csv.erb
    end
  end

Le fichier show.csv.erb se présente comme suit:

<%- headers = ["Id", "Name", "Account Number", "Publisher", "Product Name", "Status"] -%>
<%= CSV.generate_line headers %>
<%- @advertiser_search.advertisers.each do |advertiser| -%>
<%- advertiser.subscriptions.each do |subscription| -%>
<%- row = [ advertiser.id,
            advertiser.name,
            advertiser.external_id,
            advertiser.publisher.name,
            publisher_product_name(subscription),
            subscription.state ] -%>
<%=   CSV.generate_line row %>
<%- end -%>
<%- end -%>

Sur la version html de la page du rapport, j'ai un lien pour exporter le rapport affiché par l'utilisateur. Voici le lien_to qui renvoie la version csv du rapport:

<%= link_to "Export Report", formatted_advertiser_search_path(@advertiser_search, :csv) %>

Consultez le FasterCSV , un joyau.

Si tout ce dont vous avez besoin, c'est du support Excel, vous pouvez également envisager de générer directement un xls. (Voir Tableur :: Excel)

gem install fastercsv
gem install spreadsheet-excel

Je trouve ces options utiles pour ouvrir le fichier csv dans Windows Excel:

FasterCSV.generate(:col_sep => ";", :row_sep => "\r\n") { |csv| ... }

En ce qui concerne la partie ActiveRecord, cela ressemblerait à ceci:

CSV_FIELDS = %w[ title created_at etc ]
FasterCSV.generate do |csv|
  Entry.all.map { |r| CSV_FIELDS.map { |m| r.send m }  }.each { |row| csv << row }
end

Vous devez définir l'en-tête Content-Type dans votre réponse, puis envoyer les données. Content_Type: application / vnd.ms-excel devrait faire l'affaire.

Vous pouvez également définir l'en-tête Content-Disposition afin qu'il ressemble à un document Excel et que le navigateur sélectionne un nom de fichier par défaut raisonnable. c'est quelque chose comme Content-Disposition: attachement; nom_fichier = "# {nom suggéré} .xls"

Je suggère d’utiliser la gem ruby ??plus rapidement que vôtre pour générer votre fichier CSV, mais il existe également un fichier CSV intégré. L'exemple de code plus rapidecsv (tiré de la documentation de la gemme) se présente comme suit:

csv_string = FasterCSV.generate do |csv|
  csv << ["row", "of", "CSV", "data"]
  csv << ["another", "row"]
# ...
end

Ce qui suit a bien fonctionné dans mon cas et a amené le navigateur à ouvrir l'application appropriée pour le type CSV après le téléchargement.

def index
  respond_to do |format|
    format.csv { return index_csv }
  end
end

def index_csv
  send_data(
    method_that_returns_csv_data(...),
    :type => 'text/csv',
    :filename => 'export.csv',
    :disposition => 'attachment'
  )
end

essayez un bon bijou pour générer du CSV à partir de Rails https://github.com/crafterm/comma

Jetez un coup d'œil à la gemme CSV Shaper.

https://github.com/paulspringett/csv_shaper

Il a un joli DSL et fonctionne vraiment bien avec les modèles Rails. Il gère également les en-têtes de réponse et permet la personnalisation du nom de fichier.

Si vous souhaitez simplement récupérer vous-même la base de données csv à partir de la console, vous pouvez le faire en quelques lignes

tags = [Model.column_names]
rows = tags + Model.all.map(&:attributes).map(&:to_a).map { |m| m.inject([]) { |data, pair| data << pair.last } }
File.open("ss.csv", "w") {|f| f.write(rows.inject([]) { |csv, row|  csv << CSV.generate_line(row) }.join(""))}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top