12/08/2018, 13:34

Tìm hiểu thư viện xử lý file CSV trong Ruby

Giới thiệu chung Trong các ứng dụng quản lý việc xử lý nhập/xuất dữ liệu từ file có định dạng như xlsx hay csv là công việc cơ bản và cần thiết. Công việc xử lý của ứng dụng với những định dạng file này không chỉ tạo sự tiện lợi trong quá trình trao đổi, lưu trữ thông tin giữa người dùng với ứng ...

Giới thiệu chung

Trong các ứng dụng quản lý việc xử lý nhập/xuất dữ liệu từ file có định dạng như xlsx hay csv là công việc cơ bản và cần thiết. Công việc xử lý của ứng dụng với những định dạng file này không chỉ tạo sự tiện lợi trong quá trình trao đổi, lưu trữ thông tin giữa người dùng với ứng dụng mà còn giúp lập trình viên thao tác với dữ liệu nhanh chóng và dễ dàng hơn. Bài viết này trình bày cách nhập/xuất dữ liệu và các thao tác xử lý dữ liệu từ file CSV.

Xử lý file CSV trong Ruby

Giả xử ta có một bảng tính để quản lý thông tin tất cả khách hàng của một nhà hàng, mỗi hàng bao gồm các thông tin sau.

  1. Tên khách hàng
  2. Tổng số lần khách hàng đã đến nhà hàng và sử dụng đồ ăn
  3. Tổng số tiền chi tiêu
  4. Đánh giá của khách hàng về món ăn của nhà hàng.

Ví dụ với 4 khách khách hàng

Dan,34,2548,Lovin it!
Maria,55,5054,"Good, delicious food"
Carlos,22,4352,"I am ""pleased"", but could be better"
Stephany,34,6542,I want bigger steaks!!!!!

Ta thấy ở phần đánh giá khách hàng ở hàng 2 và 3, có chứa dấu phẩy, ta cần đưa toàn bộ chuỗi đó vào trong dấu nháy kép. Phức tạp hơn ở hàng 3, ta muốn đưa từ "pleased" vào nháy kép thì phải gấp đôi nháy kép đó lên.

Ví dụ trên cũng là cấu trúc cơ bản một file định dạng CSV, tiếp theo ta sẽ tìm hiểu Ruby xử lý một file CSV như thếo nào.

Giả sử ta có file customers.csv chứa dữ liệu khách hàng như ở ví dụ trên. Làm thế nào để nhập dự liệu từ file đó vào vào ứng dụng Ruby. Trong Ruby bạn có thể nhập tất cả nội dung một file vào trong bộ nhớ, hoặc nhập từng hàng. Mỗi phuơng pháp đều có ưu điểm và khuyết điểm của nó. Ví dụ với file có 300.000 dòng và máy tính có cấu hình khiêm tốn (ram 512Mb) thì việc nhập đồng thời toàn bộ nội dung file vào bộ nhớ là điều không nên, vì chuơng trình của bạn sẽ crash ngay lập tức. Ruby lưu trữ mỗi hàng của bảng thành một mảng, mỗi phần tử mảng là một string chứa nội dung từng ô (cell).

w704.jpg

Để minh họa, ta sẽ nhập dữ liệu từ file customers.csv. Ta thực hiện với phuơng thức "read" tham số là đường dẫn đến file. Phuơng thức này sẽ đọc toàn bộ tập tin và lưu trữ nó vào trong biến customers.

require 'csv'
customers = CSV.read('customers.csv')

Biến customers trở thành một mảng lớn, là mảng chứa mảng, mỗi mảng con là một hàng trong file csv.

Bằng cách khác, ta đọc file trên bằng cách đọc từng dòng. Chúng ta có thể làm điều đó bằng cách sử dụng phuơng thức CSV.foreach, đối số truyền vào là chuỗi đường dẫn file csv.

CSV.foreach('customers.csv') do |row|
  puts row.inspect
end

Kết quả như sau:

["Dan", "34", "2548", "Lovin it!"]
["Maria", "55", "5054", "Good, delicious food"]
["Carlos", "22", "4352", "I am "pleased", but could be better"]
["Stephany", "34", "6542", "I want bigger steaks!!!!!"]

Mọi xử lý với file CSV đều duơí dạng string.

Thư viện CSV cũng có thể xử lý chuỗi

Xử dụng phuơng thức CSV.parse để đưa một chuỗi thành dạng thể hiện cho dữ liệu file csv.

a_string = "Dan,34
Maria,55"
CSV.parse(a_string) #=> [["Dan", "34"], ["Maria", "55"]]

Ví dụ

Nhập dữ liệu từ file csv

Nhập dữ liệu từ file csv và lưu và database

Bước 1: Tạo model có tên customer gồm các thuộc tính là: name, total_visited, total_money, feedback

rails g model customer name:string total_visited:integer total_money:float feedback:string
rake db:migrate

Bước 2: Tạo task

# create  lib/tasks/import.rake
rails g task import customer

Bước 3: Đọc dữ liệu từ file csv vào lưu cào database

customers.csv file

Name,Times arrived,Total $ spent,Food feedback
Dan,34,2548,Lovin it!
Maria,55,5054,"Good, delicious food"
Carlos,22,4352,"I am ""pleased"", but could be better"
Stephany,34,6542,I want bigger steaks!!!!!
require "csv"

namespace :import do
  desc "Import customer from csv file"
  task customer: :environment do
     # get customers.csv
    customers_file = Rails.root + "public/customers.csv"

    # Read line-by-line and save it to database as a customer object
    CSV.foreach(customers_file, headers: true) do |row|
      Customer.create!(name: row[1], total_visited: row[2],
        total_money: row[3], feedback: row[4])
    end
  end
end

Run task: rake import:customer

Buớc 5: Kiểm tra database

  • Mở cửa sổ console rails c
  • Gõ lệnh Customer.all để kiểm tra

Xuất dữ liệu ra file Excel hoặc CSV

Bước 1: Config

# /config/application.rb
require "csv"
# /config/initializers/mime_types.rb
Mime::Type.register "application/xls", :xls

Bước 2: Tạo controller CustomersController

rails g controller customers index

class CustomersController < ApplicationController
  def index
    @customers = Customer.order(:name)
    respond_to do |format|
      format.html
      format.csv {send_data @customers.to_csv}
      format.xls {send_data @customers.to_csv(col_sep: "	")}
    end
  end
end

Bước 3: Xây dựng phuơng thức to_csv cho model Customer

class Customer < ActiveRecord::Base
  def self.to_csv(options = {})
    CSV.generate(options) do |csv|
      csv << column_names
      all.each do |customer|
        csv << customer.attributes.values_at(*column_names)
      end
    end
  end
end

Bước 4: Xây dựng giao diện

<h1>Customers</h1>

<p>
  Download:
  <%= link_to "CSV", customers_path(format: "csv") %> |
  <%= link_to "Excel", customers_path(format: "xls") %>
</p>
<table border="1">
  <tr>
    <th>ID</th>
    <th>Name</th>
    <th>Release Date</th>
    <th>Price</th>
  </tr>
  <% @customers.each do |customer| %>
  <tr>
    <td><%= customer.name %></td>
    <td><%= customer.total_visited %></td>
    <td><%= customer.total_money %></td>
    <td><%= customer.feedback %></td>
  </tr>
  <% end %>
</table>

Kết quả

Screenshot from 2016-06-27 03-17-09.png

Screenshot from 2016-06-27 03-19-00.png

Kết luận

Trong bài viết này đã trình bày cấu trúc một file CSV, những phuơng thức cơ bản cung cấp bởi thư viện CSV Ruby để thao tác với nhưng file bảng tính như csv, excel ...

Nguồn tham khảo

https://www.sitepoint.com/guide-ruby-csv-library-part/

http://railscasts.com/episodes/396-importing-csv-and-excel?view=asciicast

0