23 現実逃避: Excel の .xlsx.xls に変換する

ちょっと現実逃避がしたくなって、 Excel のファイルをターミナルで読んでみようかと考えた。 ずっと昔、xlhtml というコマンドがあった。それと lv, w3m をインストールして
alias	readxls	'xlhtml \!* | lv -Iu8 -Ou8 | w3m -T text/html'
という別名定義をすると、 ターミナルで readxls なんとか.xls として、.xls ファイルが読めた。

xlhtml は古すぎて、今では使っている人も、メンテナンスしている人もいないようだ。 何とか xlhtml-0.5.1.5.tar.gz を入手して
インストール (とても雑)
tar xzf xlhtml-0.5.1.5.tar.gz
cd xlhtml
cp -p /opt/local/share/automake-1.16/compile .
cp -p /opt/local/share/automake-1.16/depcomp .
touch ChangeLog
./configure --prefix=/usr/local
make
sudo make install
(最初、configure もまともに動かなくて、ちょっと苦戦した。)

ここまで来ると、 lv と w3m はもともとインストールしてあるので、readxls コマンドが動くはず。

読めた!でも、読めるのは .xls だけで、.xlsx は読めない。 xlhtml の作られた時期を考えれば、仕方のないことだろう。 でも、今それではさすがに使いづらい (Excel 起動して保存し直して変換するくらいだったら、 ターミナルで読もうなんて考えないもの)。

.xlsx.xls に変換する手段はあるはずだと思って、 探してみた。確かにすぐ見つかるのだけれど、Windows 限定だったり、 オンラインでやりましょう、だったり。

そのうち、R でやっている人のページを見つけた。 そうか、R で出来るくらいならば、 Python でも出来るだろう。 それで “Python Excel” で検索すると、色々なライブラリィがあることが判明した。

https://note.nkmk.me/python-excel-library/

でも一長一短、という感じのものが多い。 .xlsx と .xls の一方しか使えないとか、色々な属性を読み飛ばすとか。

現時点で思いついた解決策が、 xlrd, xlutils を使う、というもの。
xlsx2xls.py
# 第1引数に .xlsx を指定して、第2引数に .xls を指定して、読んで、書き出す。
from xlrd import open_workbook
from xlutils.copy import copy
import sys

args = sys.argv
rb=open_workbook(args[1])
wb=copy(rb)
wb.save(args[2]);

早速試してみよう…あ、xlrd も xlutils もないや。 なければ pip コマンドでインストールしなさい、とのことだけど、 使っていた Mac には、pip も入っていなかった (笑)。

MacPorts の python2.7 を使う場合に pip で xlrd, xlutils をインストール
sudo port install py27-pip
sudo pip-2.7 install xlrd
sudo pip-2.7 install xlutils

では、もう一度試してみよう。
電気水道料金.xlsx電気水道料金.xls に変換
/opt/local/bin/python2.7 xlsx2xls.py 電気水道料金.xlsx 電気水道料金.xls
あっけなく出来た。

このままだと使い方が面倒なので、シェル・スクリプトでラップする。
xlsx2xls
#!/bin/sh
for i in "$@"
do
  name=`basename $i .xlsx`
  /opt/local/bin/python2.7 ~/bin/xlsx2xls.py ${name}.xlsx ${name}.xls
done
こうしておけば
xlsx2xls 電気水道料金.xlsx
電気水道料金.xls が出来るはず…出来た!

こうしておくと、
xlsx2xls *.xlsx
のような使い方も出来るかな?

3つくらいのファイルでしか確認していないので、全然自信がなくて、 何の保証もする気はないけれど、 今日最初に見てみたいと思ったファイルの処理は出来たので、これで現実逃避は終了する。


また続きを書くことがあるだろうか?

桂田 祐史
2020-04-20