前言
不論是產各式報表,都與 Excel 脫離不了關係,產 Excel 屬於必備技能之一,以下示範如何產 Excel 檔
實作
這邊以 axlsx Gem 做範例,也有其他 Gem 也能做到,像是 xlsxtream 等,可參考此 pr
直接用 axlsx 最新版本直接 bundle 的話,會踩到雷,詳情,自己裝看看就知道了 XD
1
2
3
4
5
6# Gemfile
gem 'rubyzip', '~> 2.3', '>= 2.3.2'
gem 'axlsx_rails', '~> 0.6.1'
gem 'axlsx', git: "https://github.com/randym/axlsx.git",
ref: "c8ac844572b25fda358cc01d2104720c4c42f450"
將產 Excel 寫在 services,方便之後共用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31# app/services/shops_excel/generator.rb
module ShopsExcel
class Generator
TITLES = %w[商家名稱 信箱 備註].freeze
ROW_TYPES = %i[string string string].freeze
def execute
shops = Shop.all
xlsx = Axlsx::Package.new
workbook = xlsx.workbook
workbook.add_worksheet(name: '商家清單') do |sheet|
sheet.add_row(TITLES)
shops.find_each do |shop|
sheet.add_row(shop_row_data(shop), types: ROW_TYPES)
end
end
xlsx
end
private
def shop_row_data(shop)
[
shop.name,
shop.email,
shop.note
]
end
end
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# config/routes.rb
get :export_shops_xlsx
---
# app/controllers/shops_controller.rb
def export_shops_xlsx
# 實務上,並不建議直接在 controller 直接產 Excel,若資料很多的話,使用者體驗會不好 (會等很久)
xlsx = ShopsExcel::Generator.new.execute
send_data(xlsx.to_stream.read, type: 'application/xlsx', filename: '商家總表.xlsx')
end
若只是單純產一次就不會再產的話,可以在 rails console
直接下 code,如下
1
2
3
4
5
6# rails console
xlsx = ShopsExcel::Generator.new.execute
xlsx.use_shared_strings = true
xlsx_file = Rails.root.join("data/test.xlsx")
xlsx.serialize(xlsx_file)
從網頁下載
產的 Excel 內容
小結
產 Excel 其實不難,難的是產的資料內容過於複雜且多時,可能會關聯超多 Model 、多個工作表 (worksheet),還要考量是否會 Memory Bloat
實務上並不建議直接在 controller 直接產 Excel ,資料太多的話,使用者體驗會不好,會等很久,通常會放 sidekiq 處理,完成後,再寄信給使用者
參考資料
鐵人賽文章連結:https://ithelp.ithome.com.tw/articles/10272151
medium 文章連結:https://link.medium.com/GmNaDhwgQjb
本文同步發布於 小菜的 Blog https://riverye.com/
備註:之後文章修改更新,以個人部落格為主