第7回 CSV形式経由でExcelデータを読み込む

2008/02/23

designer_image_002

今回は、カンマ区切り(CSV)形式のデータを Ruby on Rails で利用する方法について説明します。

まず、右図のような Excel ファイル table2.xls を用意してください。

Excel の [ファイル名を付けて保存] メニューで、[ファイルの種類] として「CSV(カンマ区切り)」を選び、RAILS_ROOT/data/table2.csv として保存します。もし RAILS_ROOT/data ディレクトリが存在しなければ、作成してください。

このデータを使ってテーブルを表示する TablesController は、次のようになります。

require 'csv'
class TablesController < ActionController
  def show
    id = params[:id]
    @records = []
    reader = CSV.open(RAILS_ROOT + "/data/table#{id}.csv", 'r')
    reader.shift
    reader.each {|row| @records << row }
  end
end

前回の記事で作成した TablesController との違いに注意してください。

ポイントは次の通りです:

  • CSV モジュールを読み込むため、冒頭に require 'csv' と書かれている。
  • CSV.open の第二引数には、読み込みモードを示す文字列 'r' を指定する。
  • CSV データのヘッダ行を読み飛ばすには、shift メソッドを使う。
  • @records &;&; row という書き方で、@records の末尾に row を要素として加える。

テンプレート show.rhtml も前回のそれとは少し違います。

<table border="1" cellpadding="4">
  <tr>
    <th>名前</th>
    <th>メールアドレス</th>
    <th>年齢</th>
  </tr>
<% @records.each do |record| -%>
  <tr>
    <td><%= record[0] %></td>
    <td><%= record[1] %></td>
    <td><%= record[2] %></td>
  </tr>
<% end -%>
</table>

前回は、変数 record がハッシュでしたが、今回は配列です。record['email'] のようには書けません。

ブラウザで http://localhost:3000/tables/show/2 にアクセスし、次のように表示されることを確認してください。

名前メールアドレス年齢
tarotaro@sample.com39
jirojiro@sample.com35
saburosaburo@sample.com31

さて、読者の中には文字コードの処理は大丈夫なのだろうか、と心配になった方もいらっしゃることでしょう。

RAILS_ROOT/data/table2.csv を Excel で開いて、「taro」を「太郎」に変えてみましょう。ブラウザをリロードすると…、あ。ダメです。文字化けしてしまいます。

Excel が作る CSV ファイルの文字コードは Shift JIS で、Rails の文字コードは UTF-8 なので変換が必要です。

require 'csv'
class TablesController < ActionController
  def show
    id = params[:id]
    @records = []
    reader = CSV.open(RAILS_ROOT + "/data/table#{id}.csv", 'r')
    reader.shift
    reader.each do |row|
      row = row.collect {|value| NKF.nkf('-Sw', value) }
      @records << row
    end
  end
end

NKF モジュールの nkf メソッドは、日本語文字列の文字コードを変換します。第1引数 '-Sw' は、入力が Shift JIS で、出力が UTF-8 であることを示しています。配列 rowcollect メソッドは、配列要素を一つずつ変数 value に格納して、ブロック(中括弧で囲まれたコード)を実行し、その結果から新たな配列を作ります。

ブラウザをリロードすると…、今度は大丈夫です。

名前メールアドレス年齢
太郎taro@sample.com39
jirojiro@sample.com35
saburosaburo@sample.com31