CSV? どうせExcelから出してるんでしょ?
CSVデータ読み込み。業務系サーバーサイドアプリケーションの開発をしていると、誰しもが一度は作る機能ではないでしょうか。しかし、ほとんどのCSVファイルはExcelからCSV形式で出力されていることが多いのでは無いでしょうか。だとすれば、直接Excelから読んでしまうというのも1つの手です。特に、RDBMSで複数のテーブルにまたがるデータをzipで固められてアップロードされた複数のCSVファイルから読み込むというような涙ぐましい状況であれば、むしろExcelファイルで上げてもらったほうが楽かもしれません。
そこで、本記事ではCSVファイルではなく、ExcelのワークシートからCSVのようにデータを読み込む方法について書きます。
RubyXL
RubyでExcelファイルを扱うgemはいくつかありますが、ここではRubyXLを使います。RubyXLはread/write共に対応しているgemなので、今回は取り上げませんがxlsxファイルを書き出す場合にも利用できます。
ワークシートの読み込み
ご存じの通り、ExcelのファイルはCSVとは異なり、複数のワークシートを保持しています。まずはExcelのファイルを読み込みます。
workbook = RubyXL::Parser.parse '/path/to/foo.xlsx'
ワークシートへのアクセスは以下のようにして行います。ここでは、Excelファイルにmembersという名前のワークシートが定義されているとします。配列として先頭からインデックス指定することもできますが、シート名で指定するほうが安全でしょう。
worksheet = workbook[0] # 一番最初のワークシート
worksheet = workbook['members'] # シート名での指定
行ベースでシートの情報を取り出す
rubyXLではワークシートに対して、いろいろなアクセス方法があります。たとえば、以下のようにして行と列番号を指定する方法があります。
worksheet[0][0]
しかし、CSVの代わりにワークシートからデータを読み込む場合、1行ずつデータを取るほうがわかりやすいといえます。以下のようにextract_data
メソッドを使うことで、指定したオフセットに該当する行からデータを取り出して配列で取得できます。
worksheet.extract_data[0]
ヘッダー行を使って各行をハッシュで受け取る
しかし、上記の方法で配列を受け取ったとしても、一行あたりの情報は配列のままです。できればヘッダー行か、指定したヘッダー情報を使ってハッシュとして受け取れると読み込んだデータの処理が楽でしょう。これは以下のようにして行います。
headers = worksheet.extract_data[0]
members = worksheet.get_table(headers)[:table]
get_table
メソッドはヘッダー情報を配列として受け取り、行毎の情報と列毎の情報をハッシュで返してくれます。詳細はrubyXLのREADMEを見ていただくとしてここでは行毎の情報が含まれている:tableキーを指定し、全行の情報を取ってきています。
仮にmembersのヘッダー行が、['ID', 'Name', 'Mail']
のようになっていた場合、membersに対しては以下のようにアクセスが可能です。
member = members[2]
member['ID']
これで、各行の値がヘッダー情報をキーとしたハッシュになり、全行の情報が配列に収まっているデータとしてワークシートの情報を取得することができました。ここからは通常のCSV処理と同じように実装できるはずです。