XLS Export in ActiveAdmin

Today I want to talk about my recent experience with ActiveAdmin and export to XLS.

To obtain an XLS from ActiveAdmin we currently have two simple solutions that allow us to do it in a short time: activeadmin-axlsx and activeadmin-xls. The second takes much from the first.

Unfortunately for me, neither of the two was giving me the result that I wanted, therefore I decided to approach the problem from a lower level and use spreadsheet.

Thanks to spreadsheet we can have complete control over the file that is generated, though at the price of having to write a little more code.

As the first thing we add spreadsheet to the Gemfile

gem ‘spreadsheet’

Next, in order to maintain the folder structure as ordered as possible we create a folder (`app/spreadsheets’) where we wil place all the classes that will take care of the generation of XLS files. Then we add to config/application.rb:

module TestApp
  class Application < Rails::Application
    …
    config.autoload_paths += %W(#{config.root}/app/spreadsheets)
    …
  end
end

In this way we can have classes for creating XLS without using require.

MimeType

In order to allow our application to export xls file, we must define the format. To do this we modify the file config/initializers/mime_types.rb and add

Mime::Type.register “application/vnd.ms-excel”, :xls

ActiveAdmin download links

The download links for ActiveAdmin are set in config/initializers/active_admin.rb, in my case I did not need the pdf so I set:

ActiveAdmin.setup do |config|
  …
  config.download_links = [:csv, :xml, :xls]
  …
end

At this point we can set up our controller ActiveAdmin to respond properly to the XLS format. We will take the model User as example. We edit the file app/admin/user.rb adding the code needed to handle the format xls

ActiveAdmin.register User do
  …
  controller do
    def index
      …
      index! do |format|
        format.xls {
          spreadsheet = UsersSpreadsheet.new @users
          send_data spreadsheet.generate_xls, filename: “users.xls”
        }
      end
    end
  end
  …
end

XLS File generation

At this point we are finally able to generate XLS files without constraints.

Create the file app/spreadsheets/users_spreadsheet.rb

class UsersSpreadsheet
  attr_accessor :users
  
  def initialize users
    @users = users
  end

  def generate_xls
    book = Spreadsheet::Workbook.new
    sheet = book.create_worksheet name: “Users”

    create_body sheet

    data_to_send = StringIO.new
    book.write data_to_send
    data_to_send.string 
  end

  def create_body sheet
    # Header row with a specific format
    sheet.row(0).concat %w{Email Username Newsletter}
    sheet.row(0).default_format = Spreadsheet::Format.new weight: :bold

    row_index = 1
    users.each do |user|
      sheet.row(row_index).concat [user.email, user.username, user.newsletter_subscription]
      # sheet.row(row_index).default_format = Spreadsheet.Format.new # define a custom format
      row_index += 1
    end
  end
end

Note: I’ve used the row_index variable to set more easily the cell format, if needed.

We just have to click on the “XLS” link in the Users index.

At this point we have our xls, simple, but that we can manage as we want through the application’s code. We can set the format by entire row or by single cell but we can do more complex things such as printing more rows for record, maybe for handling a relationship. Such customizations were impossible with the two gems mentioned at the beginning.

I leave you with the link of an initial guide on what you can do with Spreadsheet, it is small but on Stack Overflow can find many examples about how to vary many cell formats and settings.

I hope this post has been helpful.

Bye and see you soon!

Leave a Reply

wpDiscuz