Export and Import excel file in Ruby on Rails framework - Phần 2
Như phần một đã giới thiệu export, import dữ liệu từ hệ thống lưu trữ dữ liệu ra các định dạng file khác nhau như xls, csv là chức năng cơ bản và cần thiết nhất của mỗi ứng dụng. Trong phần trước chúng ta đã tìm hiểu hai phương pháp export excel file. Export excel file bằng thiết kế XML Export ...
Như phần một đã giới thiệu export, import dữ liệu từ hệ thống lưu trữ dữ liệu ra các định dạng file khác nhau như xls, csv là chức năng cơ bản và cần thiết nhất của mỗi ứng dụng. Trong phần trước chúng ta đã tìm hiểu hai phương pháp export excel file.
- Export excel file bằng thiết kế XML
- Export excel file bằng gem "to_xls-Rails"
Mỗi một phương pháp đều có ưu điểm và nhược điểm riêng phù hợp với từng yêu cầu chức năng mà lập trình viên mong muốn. Trong phần này xin tiếp tục giới thiệu một phương pháp export excel file sử dụng gem axlsx có đầy đủ các chức năng từ cơ bản tới phức tạp.
Hướng dẫn cài đặt
Việc cài đặt gem axlsx trên framework Ruby on Rails cũng đơn giản và tương tự như các gem khác.
- Build một project RoR với lệnh rails new project_name
- Add gem axlsx vào Gemfile
gem "axlsx"
- Run bundle install Vậy là chúng ta đã thành công cài đặt gem axlsx và sẵn sàng sử dụng.
Xây dựng chương trình demo
1. Create model
class CreateStudents < ActiveRecord::Migration def change create_table :students do |t| t.string :name t.integer :age t.string :phone_number t.string :email t.integer :class_room_id t.timestamps null: false end end end
class CreateClassRooms < ActiveRecord::Migration def change create_table :class_rooms do |t| t.string :name t.timestamps null: false end end end
2. Create controller home để hiển thị dữ liệu
- Xây dựng app/views/home/index.html
<div class="row"> <div class="container"> <table class="table table-striped"> <thead> <tr> <th>ID</th> <th>Student Name</th> <th>Student Age</th> <th>Student Phone Number</th> <th>Student Email</th> <th></th> </tr> </thead> <tbody> <% @students.each do |student| %> <tr> <td><%= student.id %></td> <td><%= student.name %></td> <td><%= student.age %></td> <td><%= student.phone_number %></td> <td><%= student.email %></td> <td><%= link_to "Download", axlsx_index_path(id: student.try(:id)) %></td> </tr> <% end %> </tbody> </table> </div> <div class="container"> <p> Download: <%= link_to "Excel_By_Xml", xml_index_path(format: "xls") %> <br> Download: <%= link_to "Excel_By_Gem_To_Xls", to_xls_path(format: "xls") %> <br> Download: <%= link_to "Excel_By_Gem_Axlsx", axlsx_index_path %> </p> </div> </div>
-
Cho giao diện như sau.
-
Xây dựng controller AxlsxController xử lý xuất dữ liệu của một student khi click vào button download
class AxlsxController < ApplicationController require "axlsx" def index student = Student.find_by id: params[:id] send_xls student end private def send_xls student book = Axlsx::Package.new workbook = book.workbook sheet = workbook.add_worksheet name: "StudentInformation" sheet.add_row ["Attributes", "Values"] create_data(student).each_with_index do |item| sheet.add_row [item.first, item.last] sheet.add_data_validation("B2", {type: :list, formula1: "MasterData!$A$3:$A$7"}) end send_excel_file book end def send_excel_file book tmp_file_path = "#{Rails.root}/tmp/#{rand(36**50).to_s(36)}.xlsx" book.serialize tmp_file_path filename = "Aloha-#{Time.zone.now}.xlsx" file_content = File.read(tmp_file_path) send_data file_content, filename: filename File.delete tmp_file_path end def create_data student [["class_room", student.class_room_name], ["name", student.name], ["age", student.age], ["phone_number", student.phone_number], ["email", student.email]] end end
- Kết qủa
- Giao diện file excel.
- Giải thích một số key word trong file app/controllers/axlsx_controller.rb
- require "axlsx": Thêm thư viện của gem axlsx vào controller để sử dụng.
- workbook: Object đại diện cho file excel được tạo ra từ class Axlsx::Package của gem axlsx
- workbook.add_worksheet name: "StudentInformation" tạo ra sheet trong file excel với name là StudentInformation.
- add_row method thêm một hàng vào trong file excel.
- book.serialize: Khởi tạo file excel với đường path định sẵn.
- send_data method để send file excel đã khởi tạo.
- File.delete xóa file đã được gửi.
Tìm hiểu một số chức năng nâng cao
Về thiết kế chúng ta sẽ thêm một sheet thứ hai chứa data master là dữ liệu được hiển thị trong dropdown class room.
1. Thêm dropdown để chọn dữ liệu
- Thêm method make_pulldown trong method send_xls
private def send_xls student book = Axlsx::Package.new workbook = book.workbook sheet = workbook.add_worksheet name: "StudentInformation" info_sheet = book.workbook.add_worksheet name: "MasterData" make_pulldown sheet, info_sheet, student send_excel_file book end
- Nội dung private method make_pulldown
def make_pulldown sheet, info_sheet, student info = {class_room: ClassRoom.pluck(:name)} base = [*1..info.values.to_a.map(&:size).max] info_sheet_data = base.each_with_index.inject([]) do |info_sheet_data, (item, index)| info_sheet_data << info.values.map{|item| item[index]}.unshift(item) end info_sheet.add_row info.keys.map{|item| "List All Class Room"} info_sheet.add_row [""] info_sheet_data.each do |data| info_sheet.add_row data[1..-1], types: Array.new(data.length, nil) end sheet.add_row ["Attributes", "Values"] create_data(student).each_with_index do |item| sheet.add_row [item.first, item.last] sheet.add_data_validation("B2", {type: :list, formula1: "MasterData!$A$3:$A$7"}) end end
Trong đó:
- info_sheet: Thêm một sheet khác trong file excel để chứa dữ liệu master.
- info_sheet_data: Dữ liệu master data có dạng một mảng.
- Thêm dữ liệu master dưới dạng mảng.
info_sheet_data.each do |data| info_sheet.add_row data[1..-1], types: Array.new(data.length, nil) end
- Thêm thông tin của student và định nghĩa data trong pull down được lấy từ sheet thứ hai.
sheet.add_row ["Attributes", "Values"] create_data(student).each_with_index do |item| sheet.add_row [item.first, item.last] sheet.add_data_validation("B2", {type: :list, formula1: "MasterData!$A$3:$A$7"}) end
Kết qủa:
Dữ liệu master trong sheet thứ hai:
2. Custom Styles của file excel
Những style như font chữ, màu sắc, độ rộng cột ... đều được cung cấp và dễ dàng sử dụng.
- Customer method make_pulldown
def make_pulldown workbook, student sheet = workbook.add_worksheet name: "StudentInformation" info_sheet = workbook.add_worksheet name: "MasterData" info = {class_room: ClassRoom.pluck(:name)} base = [*1..info.values.to_a.map(&:size).max] info_sheet_data = base.each_with_index.inject([]) do |info_sheet_data, (item, index)| info_sheet_data << info.values.map{|item| item[index]}.unshift(item) end info_sheet.add_row info.keys.map{|item| "List All Class Room"} info_sheet.add_row [""] info_sheet_data.each do |data| info_sheet.add_row data[1..-1], types: Array.new(data.length, nil) end style = workbook.styles black_cell = style.add_style bg_color: "00", fg_color: "FF", sz: 14, alignment: {horizontal: :center} blue_cell = style.add_style bg_color: "0000FF", fg_color: "FF", sz: 20, alignment: {horizontal: :center} sheet.column_awidths 30, 50 sheet.add_row ["Attributes", "Values"], :style => [black_cell, blue_cell] create_data(student).each_with_index do |item| sheet.add_row [item.first, item.last] sheet.add_data_validation("B2", {type: :list, formula1: "MasterData!$A$3:$A$7"}) end end
- Trong đó:
- style = workbook.styles: Khởi tạo object để chứa các cài đặt style.
- add_style: Method dùng để thêm style đã được khởi tạo vào trong file excel theo từng dòng.
- sheet.column_awidths 30, 50: Cài đặt độ rộng của từng cột tính theo px.
- Các method như bg_color, fg_color, sz, ... đều được cung cấp đầy đủ dùng để định nghĩa các cài đặt style tới mức nhỏ nhất.
Kết qủa:
3. Một số chức năng nổi bật
- Thêm hình ảnh vào trong file.
- Thêm biểu đồ vào trong file.
- Thêm công thức vào trong từng ô của file.
- Customer kiểu dữ liệu trong từng ô của file.đều
- .....v v
Tất cả những cài đặt, cách sử dụng những chức năng trên đều được cũng cấp và hướng dẫn cụ thể trên trang chủ của gem axlsx tại đây
4. Một số chức năng nổi bật
Có rất nhiều cách để import dữ liệu từ file excel tuy nhiên xin giới thiệu một cách đơn giản sử dụng gem roo được hướng dẫn cụ thể tại đây.
Có rất nhiều phương pháp để xây dựng chức năng này, mỗi một phương pháp đều có ưu điểm và nhược điểm riêng tùy theo yêu cầu mà chọn lựa cách hợp lý nhất. Bài viết chỉ đề xuất một vài phương án trong đó còn nhiều thiếu xót mong nhận được góp ý từ bạn đọc.
Thanks you for listening!!!