# For dealing with exel
gem 'caxlsx'
gem 'caxlsx_rails'
参考: https://github.com/caxlsx/caxlsx_rails
Axlsx-Rails 提供了一个 renderer 和一个 template handler. 它添加了一个新的 format :xlsx,并且可以解析 .xlsx.axlsx 模版。
在控制器层,可以处理 :xlsx format 的请求:
class ButtonController < ApplicationController
  def action_name
    @buttons = Button.all
    respond_to do |format|
      format.xlsx
    end
  end
end
然后我们需要提供一个模版,根据 convention,它的名字需要是这样: action_name.xlsx.axlsx
wb = xlsx_package.workbook
wb.add_worksheet(name: "Buttons") do |sheet|
  @buttons.each do |button|
    sheet.add_row [button.name, button.category, button.price]
  end
end
然后我们就可以通过请求,直接下载 excel 文件
$(".export-consumers").on('click', (e) =>{
  e.preventDefault();
  $.ajax({
    method: 'GET',
    dataType: 'json',
    url: `/admin/consumers.js?campaign_id=${e.currentTarget.dataset.campaignId}`
  }).done((response) => {
    window.location = `/admin/consumers/download-consumers?file_name=${response.exported_file_name}`;
  }).fail((msg) => {
    alert('Export Failed');
  })
});
respond_to do |format|
  format.js do
    @consumers = consumers
    exported_file_name = Admin::XlsxGeneration.new(@consumers, @current_campaign_id).build_tw_consumers_xlsx
    render json: {exported_file_name: exported_file_name}
  end
end
def download_consumers
  send_file Rails.root.join("tmp", "#{params[:file_name]}.xlsx"), type: :xlsx, filename: "#{params[:file_name]}.xlsx"
end
对于异步形式的下载,上面示例的方案是先生成临时文件,返回文件名,然后再异步的下载这个文件。这个方案经过验证,有效可行。
对于异步的情况我还有一个想法,就是在后端不生成文件,直接通过send_data异步返回文件,但是我没有成功,因为在前端的 callback( done ) 中,没法拿到send_data返回的文件数据。不知道有人尝试过没?