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

今回は、カンマ区切り(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 にアクセスし、次のように表示されることを確認してください。
| 名前 | メールアドレス | 年齢 |
|---|---|---|
| taro | [email protected] | 39 |
| jiro | [email protected] | 35 |
| saburo | [email protected] | 31 |
さて、読者の中には文字コードの処理は大丈夫なのだろうか、と心配になった方もいらっしゃることでしょう。
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 であることを示しています。配列 row の collect メソッドは、配列要素を一つずつ変数 value に格納して、ブロック(中括弧で囲まれたコード)を実行し、その結果から新たな配列を作ります。
ブラウザをリロードすると…、今度は大丈夫です。
| 名前 | メールアドレス | 年齢 |
|---|---|---|
| 太郎 | [email protected] | 39 |
| jiro | [email protected] | 35 |
| saburo | [email protected] | 31 |
