PythonとRubyでxlsをcsvへ変換する

必要になったので調べてみた。 どちらのサンプルも、xls形式で公開されている東証銘柄一覧をダウンロードしてcsvに加工して出力する。

Python版

xlrdを使う。

読み込み専用ライブラリなので、書き込みが必要な時はxlwrを使う。

セルを加工しなくていい時はsheet.row([index])でリスト型で一行まとめて取得できる。

import urllib.request
import xlrd

def sheet2csv(sheet):
  nrows = sheet.nrows
  ncols = sheet.ncols
  rows = []
  for r in range(nrows):
    row = []
    for c in range(ncols):
      cell = sheet.cell(r, c)
      if cell.ctype == 2:
        cell = int(cell.value)
      else:
        cell = cell.value
      row.append(str(cell))
    rows.append(row)
  return rows

request = urllib.request.Request("https://www.jpx.co.jp/markets/statistics-equities/misc/tvdivq0000001vg2-att/data_j.xls")
contents = urllib.request.urlopen(request).read()
book = xlrd.open_workbook(file_contents=contents)
csv = sheet2csv(book.sheet_by_index(0))
with open("codes.csv", mode="w") as f:
  for r in csv:
    f.write(",".join(r)+'\n')

Ruby版

ここではメジャーそうなRooを使う。 現バージョンではxls形式の読み込みには別途roo-xlsモジュールが必要。

こちらは読み書きできて、読み込み時にはURL指定で直接WEBのファイルを参照できて便利。

また、セルを加工しなくていい時はbook.to_csv([filename=nil, separator=',', sheet=default_sheet])でシートごとに直接csvへ出力できる。

require 'roo'
require 'roo-xls'

def sheet2csv(sheet)
  sheet.map {|line|
    line.map {|cell|
      cell = cell.to_i if cell.class == Float
      cell.to_s
    }
  }
end

book = Roo::Excel.new "https://www.jpx.co.jp/markets/statistics-equities/misc/tvdivq0000001vg2-att/data_j.xls"
csv = sheet2csv book.sheet(0)
File.open "codes.csv", "w" do |f|
  csv.each {|r| f << r.join(',') + "\n"}
end