Link Search Menu Expand Document

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>

image

編輯 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 試算表軟體打開:

image

但是 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 逗點,即可正常顯示。

image

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 格式的檔案了。

image


Copyright © 2010-2021 Wen-Tien Chang All Rights Reserved.