20. 數據匯出
20-1 匯出 CSV 檔案
需求:後台可以匯出報名資料
有時候後台功能做再多,也不如 Microsoft Excel 或 Apple Numbers 試算表軟體提供的分析功能,這時候如果有匯出功能,就可以很方便地把資料匯出來,用軟體來打開瀏覽。
CSV 逗號分隔值是一種簡單的資料格式,基本上就是單純的文字檔,一行一筆資料,不同欄位用逗號隔開。這一節先來做這種。
編輯 app/views/admin/event_registrations/index.html.erb
,在最下方加上匯出按鈕,指定 format 格式是 csv
<%= paginate @registrations %>
+ <p>
+ <%= link_to "匯出 CSV", admin_event_registrations_path(:format => :csv), :class => "btn btn-default" %>
+ </p>
編輯 app/controllers/admin/event_registrations_controller.rb
,利用 respond_to
針對不同格式的請求,回應不同的輸出:
+ require 'csv'
class Admin::EventRegistrationsController < AdminController
before_action :find_event
def index
# (略)
+ respond_to do |format|
+ format.html
+ format.csv {
+ @registrations = @registrations.reorder("id ASC")
+ csv_string = CSV.generate do |csv|
+ csv << ["報名ID", "票種", "姓名", "狀態", "Email", "報名時間"]
+ @registrations.each do |r|
+ csv << [r.id, r.ticket.name, r.name, t(r.status, :scope => "registration.status"), r.email, r.created_at]
+ end
+ end
+ send_data csv_string, :filename => "#{@event.friendly_id}-registrations-#{Time.now.to_s(:number)}.csv"
+ }
+ end
end
CSV 是 Ruby 內建的庫,這裡第一行需要先 require
它。使用 CSV.generate
可以產生出 csv_string
字串,也就是要輸出的 CSV 資料,接著透過 send_data
傳給瀏覽器進行檔案下載。
用 Apple Number 試算表軟體打開:
但是 CSV 有個缺點,就是用 Microsoft Excel 打開時預設會變成亂碼。這是因為匯出的 CSV 的字串編碼是 UTF-8,但是 Excel 預設會用本地編碼,例如中國大陸常用 GB2312,台灣常用 Big5。解決辦法有二:
方法一: 以記事本開啟後儲存,再以 Excel 開啟即可正常顯示。
方法二: 開啟 Excel 軟體,新增空白活頁簿(Workbook),然後在上方功能選項中點選「資料(Data)」->「取得外部資料 Get External Data」->「從文字檔 From Text File…」→「選擇匯出的 CSV 檔案」→ 選擇符號分隔(Delimited)、選擇 File origin 編碼是 Unicode (UTF-8) → 選擇分隔符號是 Comma 逗點,即可正常顯示。
20-2 匯出 Excel 檔案
如果上述 Excel 打開 CSV 檔案的解法沒辦法接受的話,那隻好想辦法匯出 Excel 專用的 xlsx 格式了。這需要額外裝 gem,這裡示範使用 axlsx_rails gem。
編輯 Gemfile
+ gem 'rubyzip'
+ gem 'axlsx'
+ gem 'axlsx_rails'
執行 bundle
,重啟伺服器
編輯 app/views/admin/event_registrations/index.html.erb
,加上匯出的按鈕,指定 format 格式是 xlsx
<%= paginate @registrations %>
<p>
<%= link_to "匯出 CSV", admin_event_registrations_path(:format => :csv), :class => "btn btn-default" %>
+ <%= link_to "匯出 Excel", admin_event_registrations_path(:format => :xlsx), :class => "btn btn-default" %>
</p>
編輯 app/controllers/admin/event_registrations_controller.rb
,新增 xlsx 格式
respond_to do |format|
format.html
format.csv {
# 略
}
+ format.xlsx
end
end
新增 app/views/admin/event_registrations/index.xlsx.axlsx
樣板:
wb = xlsx_package.workbook
wb.add_worksheet(name: "Buttons") do |sheet|
sheet.add_row ["報名ID", "票種", "姓名", "狀態", "Email", "報名時間"]
@registrations.each do |r|
sheet.add_row [r.id, r.ticket.name, r.name, t(r.status, :scope => "registration.status"), r.email, r.created_at]
end
end
這樣就可以匯出 Excel 格式的檔案了。