Excelで作った表データをJavaScriptであれこれしたい時に,ExcelデータをJSONに変換したいことがあったので,さっくり書いてみました.特徴としては,セル内改行があっても正しくデータが取れるので,CSVやTSVに比べるとデータに自由が効く点があります.HTMLを入れてみたり,JavaScriptを入れて読み込み側でeval()してみたりと色々応用が利くと思います.
動作環境はRuby 1.9.3,ActiveSupport 3.2.13,roo 1.11.2です.Mac環境でのみ確認しています.案の定ご利用は自己責任でお願いします.
まず,以下のgemをインストールします.
$ gem install active_support roo
その後,以下のコードをexcel2json.rbとして保存します.Excelデータのファイル名は直して使って下さい.
# encoding: utf-8 # # excel2json.rb: Excel -> JSON変換を行う # # usage: $ ruby excel2json.rb # # description: # SOURCE_FILEに変換したいExcelファイル名を設定して実行することでJSONデータを標準出力に表示する # 変換するファイル名 SOURCE_FILE = "SOURCE_EXCEL.xlsx" # Ruby 1.8系の場合はrubygemsをrequireする必要がある # require 'rubygems' require 'active_support/all' require 'roo' # xlsxではなくxlsファイルを使う時はExcelx -> Excelに変更する doc = Roo::Excelx.new(SOURCE_FILE) # 1枚目のシートを使う doc.default_sheet = doc.sheets.first # 1行目をヘッダ行として列数をカウントする.ヘッダ名をJSONのhash keyにするので空文字はスキップされる headers = {} (doc.first_column..doc.last_column).each do |col| headers[col] = doc.cell(doc.first_row, col) end hash = {} hash[:data] = [] ((doc.first_row + 1)..doc.last_row).each do |row| row_data = {} headers.keys.each do |col| value = doc.cell(row, col) # rooは整数値もfloatとして返すので,整数値なら整数に変換する(必要なければコメントアウトして良い) value = value.to_i if doc.celltype(row, col) == :float && value.modulo(1) == 0.0 row_data[headers[col]] = value end hash[:data] << row_data end puts hash.to_json
実行するには単に
$ ruby excel2json.rb
とすれば良いです.ソースコードのSOURCE_FILEに変換したいExcelファイルのファイル名を入れて下さい.
変換データのサンプルですが,以下の様なデータを入力すると,
以下の様な構造のJSONになって出てきます.
{ "data":[ { "id":1, "title":"ほげほげほげ", "body":"ほげほげほげ?ふがふがふがふが" }, { "id":2, "title":"ふがふがふが", "body":"ふげふげふげ!\nふgうghうgうっっっっっうぇうぇ" }, { "id":3, "title":"ぴよぴよぴよ", "body":"改行があっても\nちゃんとでーたがとれますぜ" }, { "id":4, "title":"うぇえっっっうぇうぇうぇっうぇっっっうぇうぇ", "body":":\"'wee;;;;llm,記号を入れてみた" }, { "id":5, "title":"おなかすいた", "body":123123 }, { "id":6, "title":"小田急線が遅れている件について", "body":null }, { "id":7, "title":"雨が止まない件について", "body":"ueueueueeu" }, { "id":8, "title":"傘が無い件について", "body":"hogwhogwhogww" } ] }
時間のあるときに,もうちょっときちんとオプションなど整理してgemにでもしようと思いますが,とりあえず使い捨てプログラムとしてはこれで十分かと思います.