Pregunta

Tengo una tabla de base de datos simple llamada "Entradas":

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

¿Cómo escribo un controlador que devolverá el contenido de la tabla Entradas como un archivo CSV (idealmente de manera que se abra automáticamente en Excel)?

class EntriesController < ApplicationController

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

    # ??? NOW WHAT ????

  end

end
¿Fue útil?

Solución

Hay un complemento llamado FasterCSV que maneja esto maravillosamente.

Otros consejos

CSV más rápido es definitivamente el camino a seguir, pero si desea servirlo directamente desde su aplicación Rails, también querrá configurar algunos encabezados de respuesta.

Mantengo un método para configurar el nombre del archivo y los encabezados necesarios:

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

Usar eso hace que sea fácil tener algo como esto en mi controlador:

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

Y tenga una vista que se parece a esta:(generate_csv es 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 %>

Acepté (¡y voté a favor!) la respuesta de @Brian, por indicarme primero FasterCSV.Luego, cuando busqué en Google para encontrar la gema, también encontré un ejemplo bastante completo en esta página wiki.Juntándolos, me decidí por el siguiente código.

Por cierto, el comando para instalar la gema es:Sudo Gem Instale FASTERCSV (todos minúsculas)

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

Otra forma de hacer esto sin usar FasterCSV:

Requerir la biblioteca csv de Ruby en un archivo inicializador como config/initializers/dependencies.rb

require "csv"

Como algunos antecedentes, el siguiente código se basa en Formulario de búsqueda avanzada de Ryan Bate que crea un recurso de búsqueda.En mi caso, el método show del recurso de búsqueda devolverá los resultados de una búsqueda previamente guardada.También responde a csv y utiliza una plantilla de vista para formatear la salida deseada.

  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

El archivo show.csv.erb tiene el siguiente aspecto:

<%- 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 -%>

En la versión HTML de la página del informe tengo un enlace para exportar el informe que el usuario está viendo.El siguiente es el link_to que devuelve la versión csv del informe:

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

Échale un vistazo al CSV más rápido joya.

Si todo lo que necesita es soporte de Excel, también puede considerar generar un xls directamente.(Ver Hoja de Cálculo::Excel)

gem install fastercsv
gem install spreadsheet-excel

Estas opciones me parecen buenas para abrir el archivo csv en Windows Excel:

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

En cuanto a la parte ActiveRecord, algo como esto funcionaría:

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

Debe configurar el encabezado Content-Type en su respuesta y luego enviar los datos.Tipo de contenido:application/vnd.ms-excel debería funcionar.

También es posible que desee configurar el encabezado Content-Disposition para que parezca un documento de Excel y el navegador elija un nombre de archivo predeterminado razonable;eso es algo así como disposición de contenido:adjunto;nombre de archivo="#{nombre_sugerido}.xls"

Sugiero usar la gema Ruby más rápida csv para generar su CSV, pero también hay un csv incorporado.El código de muestra de fastcsv (de la documentación de la gema) se ve así:

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

El siguiente enfoque funcionó bien en mi caso y hace que el navegador abra la aplicación adecuada para el tipo CSV después de la descarga.

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

prueba una buena joya para generar CSV desde Railshttps://github.com/crafterm/comma

Eche un vistazo a la gema CSV Shaper.

https://github.com/paulspringett/csv_shaper

Tiene un buen DSL y funciona muy bien con los modelos Rails.También maneja los encabezados de respuesta y permite la personalización del nombre de archivo.

Si simplemente desea obtener la base de datos csv usted mismo desde la consola, puede hacerlo en unas pocas líneas.

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(""))}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top