Importing & Exporting CSV / Excel

Bài viết này giới thiệu tới các bạn cách Import và Export file CSV/Excel đơn giản bằng Ruby on the Rails.

#CSV

  • Đầu tiên, trong file config/application.rb thêm require:

require 'csv'

Ví dụ ta sẽ import/export database bảng User.

I. Importing CSV

  • Tạo đường dẫn import_users_path trong routes.rb

resources :users do
  collection { post :import }
end
  • Thêm method import trong models/user.rb

class << self
  def import(file)
    CSV.foreach(file.path, headers: true) do |row|
      User.create!(row.to_hash)
    end
  end
end

Thêm headers: true để bỏ qua dòng đầu tiên trong file csv(column_names). Với mỗi dòng tiếp theo tạo user tương ứng vào trong database.

  • Trong users_controller.rb gọi method import trong model ra.

def index
  @users = User.all
end

def import
  User.import(params[:file])
  redirect_to root_path, notice: "Imported."
end
  • Trong view:

<h2>Import</h2>

<%= form_tag import_users_path, multipart: true do %>
  <%= file_field_tag :file %>
  <%= submit_tag 'Import' %>
<% end %>

<h2>Users</h2>

<table style='width:400px'>
  <tr>
    <th>Name</th>
    <th>Code</th>
  </tr>
  <% @users.each do |user| %>
    <tr>
      <td><%= user.name %></td>
      <td><%= user.code %></td>
    </tr>
  <% end %>
</table>

  • File csv minh họa users.csv
code,name
B120010,Lê Hoài Phương
B120011,Nguyễn Thị Minh Ngọc
B120012,Lê Duy Khánh
B120013,Nghiêm Tuấn Minh
B120016,Trần Ngọc Thắng
B120017,Nguyễn Văn Ngọc
B120018,Đinh Thanh Tâm
B120022,Phạm Ngọc Tâm
B120024,Vũ Ngọc Anh
  • Kết quả dữ liệu bảng User sau khi import:

Screenshot from 2015-05-25 14:41:04.png

II. Exporting CSV

  • Để export dữ liệu ra file csv phải thêm format: csv trong users_controller.rb

def index
  @users = User.all
  respond_to do |format|
    format.html
    format.csv { render text: @users.to_csv }
  end
end

-Trong models/user.rb method to_csv được mô tả:


class << self
  def to_csv
    CSV.generate do |csv|
      csv << column_names
      all.each do |user|
        csv << user.attributes.values_at(*column_names)
      end
    end
  end
end

Đầu tiên là thêm các column_name vào dòng đầu. Các dòng tiếp theo là giá trị các trường tương ứng với dòng đầu của mỗi user trong database.

  • Trong view:

<%= link_to 'Export', users_path(format: 'csv') %>
  • Kết quả sau khi click vào link sẽ xuất ra file users.csv
id,name,code
52,Lê Hoài Phương,B120010
53,Nguyễn Thị Minh Ngọc,B120011
54,Lê Duy Khánh,B120012
55,Nghiêm Tuấn Minh,B120013
56,Trần Ngọc Thắng,B120016
57,Nguyễn Văn Ngọc,B120017
58,Đinh Thanh Tâm,B120018
59,Phạm Ngọc Tâm,B120022
60,Vũ Ngọc Anh,B120024

#Excel

I. Importing Excel

  • Để import file Excel có nhiều gem hỗ trợ, ở đây sử dụng gem 'roo'. Thêm gem vào Gemfile rồi bundle install.
gem 'roo'
  • File routes.rb, controller và view tương tự như import file csv.

  • Đối với file models/user.rb, method import có thể mở cả file csv, excel do sử dụng thư viện roo.


class << self
  def import(file)
    spreadsheet = open_spreadsheet(file)
    header = spreadsheet.row(1)
    (2..spreadsheet.last_row).each do |i|
      row = Hash[[header, spreadsheet.row(i)].transpose]
      user = find_or_initialize_by(code: row['code'])
      user.update_attributes!(row.to_hash)
    end
  end

  def open_spreadsheet(file)
    case File.extname(file.original_filename)
    when '.csv' then Roo::Csv.new(file.path, file_warning: :ignore)
    when '.xls' then Roo::Excel.new(file.path, file_warning: :ignore)
    when '.xlsx' then Roo::Excelx.new(file.path, file_warning: :ignore)
    else raise 'Unknown file'
    end
  end
end

Trong method import ngoài việc duyệt từng dòng để lưu vào db còn xử lí thêm việc tìm xem code đã được sử dụng trong database chưa, nếu có rồi thì update các trường khác, chưa thì tạo mới.

II. Exporting Excel

  • Trong file mime_type.rb

Mime::Type.register "application/xls", :xls
  • Để export dữ liệu ra file xls phải thêm format: xls trong users_controller.rb

def index
  @users = User.all
  respond_to do |format|
    format.html
    format.xls { render text: @users.to_csv }
  end
end

-Trong models/user.rb method to_csv được mô tả tương tự như đối với file csv:


class << self
  def to_csv
    CSV.generate do |csv|
      csv << column_names
      all.each do |user|
        csv << user.attributes.values_at(*column_names)
      end
    end
  end
end

Đầu tiên là thêm các trường của User vào dòng đầu, mỗi trường tương ứng 1 cột trong file excel. Các dòng tiếp theo là giá trị các trường tương ứng với dòng đầu của mỗi user trong database.

  • Trong view:

<%= link_to 'Export', users_path(format: 'xls') %>
  • Kết quả xuất ra file excel:

Screenshot from 2015-05-26 08:58:46.png

Các bước trên là các bước thuần đơn giản và dễ dàng để import/export file csv/excel bằng Ruby on the Rails

Tài liệu tham khảo :

http://ruby-doc.org/stdlib-1.9.3/libdoc/csv/rdoc/CSV.html

http://railscasts.com/

HAVE A NICE DAY! ^_^