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