LoginSignup
35

More than 5 years have passed since last update.

CSVではなくてxlsxファイルから直接データを読み込む

Posted at

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処理と同じように実装できるはずです。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35