ruby-on-railscsvfastercsv

Exporting to CSV from complex rails query


I was following this railscast video but I'm having serious difficulties to export my data to excel (or CSV for this matter).

I'm using will_paginate in some data that I show on frontend like this:

sql = "select complex..."
@data = paginate_by_sql([sql],
                :per_page => params[:rows],
                :page => params[:page])

so, as is, I thought this should work:

respond_to do |format|
    format.html
    format.xls { send_data @data.to_csv(:col_sep => "\t") }
end

and it actually downloaded a xls file correctly by the content is all messed up, it shows one row per column and something like this as content:

#<Product:0x00000004c83328>

PS -> using rails latest version

:: EDIT :: By one row per column I mean one row only on my excel sheet and on this row

COLUMN A = #<Product:0x00000004c83328>

COLUMN B = #<Product:0x00000004c83329>

COLUMN C = #<Product:0x00000004c8333> (30 columns)

UPDATE

Did a simple exercise for testing and end up with all columns again in one column only:

csv_string = CSV.generate(:col_sep => ",") do |csv|
  csv << ["row", "of", "CSV", "data"]
  csv << ["another", "row"]
end

respond_to do |format|
    format.html
    format.csv { send_data csv_string,
        :type => 'text/csv; charset=iso-8859-1; header=present',
        :disposition => "attachment; filename=records.csv" }
end

(:col_sep => ",") is optional I suppose.

result:

excel output


Solution

  • ok, so this is what I did.

    modified the responder to this...

    respond_to do |format|
        format.xls
    end
    

    and created a template called nameofmethod.xls.erb with this...

    <?xml version="1.0"?>
    <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
      xmlns:o="urn:schemas-microsoft-com:office:office"
      xmlns:x="urn:schemas-microsoft-com:office:excel"
      xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
      xmlns:html="http://www.w3.org/TR/REC-html40">
      <Worksheet ss:Name="Sheet1">
        <Table>
          <Row>
          <% @data.first.attributes.keys.each do |column| %>
            <Cell><Data ss:Type="String"><%=column%></Data></Cell>
          <% end %>
          </Row>
        <% @data.each do |row| %>
          <Row>
          <% row.attributes.values.each do |column| %>
            <Cell><Data ss:Type="String"><%= column %></Data></Cell>
          <% end %>
          </Row>
        <% end %>
        </Table>
      </Worksheet>
    </Workbook>
    

    This is pretty dynamic for any kind of ActiveRecord Object. For now this will have to do...