Search code examples
ruby-on-railsexcelexport-to-excel

Excel Export not working


I'm adding a CSV and Excel export feature in my app, but after downloading the file it only shows this #<Axlsx::Worksheet:0x007f5d23708dc0> instead of required data in the spreadsheet.

I'm also sharing the method and gems which I have used.

for this export, I have created a separate controller and a separate class under Module Export

require 'csv'
require 'axlsx'
# extend ActiveSupport::Concern
# include Rails.application.routes.url_helpers
module Export
  class ParseError < ::StandardError; end
  class ExportError < ::StandardError; end
  class TimesheetExport
    attr_accessor :error

    def initialize(trackers, export_to='csv')
      @trackers = trackers
      @export_to = export_to
    rescue ActiveRecord::RecordNotFound
    end

    def process
      if !@trackers
        @error = "Not Found"
        return false
      else
        case @export_to
          when "csv"
            export_csv
          when "xls"
            export_xls
          else
            raise ExportError
        end
      end
    end

    def export_csv
      columns = %w(Date Task Task_URL TimeSpent Log)
      CSV.generate do |csv|
        csv << columns
        @trackers.each do |t|
          csv << [t.created_at.to_s(:short_human_with_12hours),
                    t.task.name,
                    #project_task_url(t.task.project, t.task, host: AppConfig.app_url),
                    t.time_spent,
                    t.description ]
        end
      end
    end

    def export_xls
      package = Axlsx::Package.new
      workbook = package.workbook
      workbook.add_worksheet(name: "Timesheet") do |sheet|
        sheet.add_row ["Date", "Task Name","Time Spent","Log"]
          @trackers.each do |t|
            sheet.add_row [t.created_at.to_s(:short_human_with_12hours), 
                            t.task.name,
                            t.time_spent,
                            t.description]
        end
      end
    end

Gems which have been installed -

gem 'axlsx', '= 2.0.1'
gem 'axlsx_rails'

And this is way I'm passing the value from export controller -

@exporter = Export::TimesheetExport.new(user_trackers, params[:export_to])
    export_string = @exporter.process
    if export_string
      case params[:export_to]
        when "csv"
          send_data export_string,
                    type: 'text/csv; charset=iso-8859-1; header=present',
                    disposition: "attachment; filename=#{@exporter.file_name}"
        when "xls"
          send_data export_string,
                    type: 'application/xls; charset=iso-8859-1; header=present',
                    disposition: "attachment; filename=#{@exporter.file_name}"
      end
    else
      flash[:alert] = @exporter.error
      redirect_to timesheet_path

Solution

  • export_xls is returning a ruby object, you need to return the file stream itself.

    def export_xls
          package = Axlsx::Package.new
          workbook = package.workbook
          workbook.add_worksheet(name: "Timesheet") do |sheet|
            sheet.add_row ["Date", "Task Name","Time Spent","Log"]
              @trackers.each do |t|
                sheet.add_row [t.created_at.to_s(:short_human_with_12hours), 
                                t.task.name,
                                t.time_spent,
                                t.description]
            end
          end
          package.to_stream.read # Return the file stream to send_data
        end