12

24

[Ruby] xlsをcsvにすると情報が欠落するので、xlsファイルを直接読むプログラム

2011.12.24(13:26)

Excelで作成した xls ファイルは、一般的には、csv で保存して、それをrubyで処理するのが簡単です。

しかし、うまくいかない場合が存在します。

parking.png

このように作成された parking.xls があったとします。これを csv で保存すると、以下のような中身になります。


店名,駐車場
本町店,あり
末広町店,
駅前店,


セルが結合されている部分は、その範囲の左上だけに値がはいっていて、それ以外にははいっていません。なので上の例の場合、C4も、C5も値がはいっていない csv が出力されます。C4は「あり」ではありませんし、C4とC5が区別できません。末広町店に駐車場があって、駅前店にないことが読み取れません。

xls で含まれていた情報が csv では欠落する例です。セルを結合することに範囲を限定する情報が含まれています。

このような場合は、xls を直接 ruby で読むようにすれば、問題を解決できます。上記のような xls から、以下のような csv に相当する情報を得られるように、WIN32OLEを用いて、セルの結合を意識したプログラムを作成します。


店名,駐車場
本町店,あり
末広町店,あり
駅前店,


以下に XlsReader クラスを示します。


# coding: windows-31j
# Ruby1.9.3版 2011/12/24

require 'win32ole'

# xlsファイルを読み込むためのクラス
# @author Shima.Toshihiro
# @version 1.1 - 2011/12/24
# @see http://jp.rubyist.net/magazine/?0004-Win32OLE
# @see http://jp.rubyist.net/magazine/?0027-ExcellentRuby
# @see http://www.happy2-island.com/excelsmile/smile03/capter00501.shtml
class XlsReader

# 読み込みモードでxlsファイルを開き、各行を配列でブロックに渡す
# @param [String] path 読み込む xlsファイルのパス名。相対パスまたは絶対パス。
# @param [Fixnum | String] sheet_selection シート番号(一番左のタブが1)、
# またはシート名(タブの名前)、省略した場合は、アクティブなシートを選択する
# @return [void]
def self.foreach(path,sheet_selection = nil)
excel = WIN32OLE.new('EXCEL.Application')
excel.visible = false
abs_path = File.expand_path(path)
book = excel.workbooks.add(abs_path)
sheet = book.ActiveSheet
sheet = book.Worksheets(sheet_selection) if sheet_selection != nil
for row in sheet.UsedRange.Rows do
row_array = Array.new
for cell in row.Columns do
val = nil
if cell.MergeCells
val = cell.MergeArea.Item(1,1).Value
else
val = cell.Value
end
row_array << val.to_s
end
yield row_array
end
book.close(false)
excel.quit
end
end


もしセルが結合されていたら、結合されている範囲の左上のセルの値を得るようになっています。1行分ずつ配列にしてブロックに渡します。

XlsReaderクラス を使ったサンプルプログラムです。


# coding: windows-31j
# Ruby1.9.3版 2011/12/24

require_relative 'xls_reader'

input_file = "./parking.xls"
XlsReader.foreach(input_file) { |array|
printf "%s\n",array.join(',')
}


実行結果です。


店名,駐車場
本町店,あり
末広町店,あり
駅前店,


うまくいきました。rubyのブロックとyieldの例になっています。

コメントの投稿

非公開コメント

プロフィール

島敏博

Shima Toshihiro 島敏博
信州アルプスハイランド在住。HaskellとElixirが好き。組み込みソフトウェアアーキテクト、C++プログラマ、山歩き、美術館巡り、和食食べ歩き、日本赤十字社救急法指導員、インデックス投資、クラシック音楽、SESSAME会員、状態マシン設計、モデル駆動開発、ソフトウェアプロダクトライン、Rubyist、実践ビジネス英語

■ ツイッター
http://twitter.com/saltheads
■ Facebook
http://www.facebook.com/saltheads
■ Qiita
http://qiita.com/saltheads

印刷する場合は、ブラウザの印刷メニューではなく、このページの上から3cmくらいの青いところにある、「印刷」を押してみてください。少しうまく印刷できます。まだ完全ではないのですが、これで勘弁してください。


カテゴリ
最新記事
月別アーカイブ
最新コメント
検索フォーム
リンク
sessame
RSSリンクの表示