わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

getvbaのWebインタフェースを更新

 ブラウザから,Excelマクロ有効ブック(拡張子がxlsmのファイル)をアップロードすると,そこからマクロの部分を取り出して表示する,簡単なWebアプリケーションを更新しました.
 最初に公開したときの記事は以下より読めます.

 今回更新したWebアプリについて,提供する機能は変更ありません.初期画面は次のとおりです.

f:id:takehikom:20200101060009j:plain

 CalendarMaker.xlsmをアップロードしてみると,次のように,マクロが表示されました.最初の「olevba 0.55.1 on Python 3.8.1」により,バージョンが上がっているのが確認できました.

olevba 0.55.1 on Python 3.8.1 - http://decalage.info/python/oletools
===============================================================================
FILE: ****
Type: OpenXML
-------------------------------------------------------------------------------
VBA MACRO ThisWorkbook.cls 
in file: xl/vbaProject.bin - OLE stream: 'VBA/ThisWorkbook'
(略)
       MyInput = InputBox("Type in Month and year for Calendar")
       If MyInput = "" Then Exit Sub
       Resume
   End Sub

 サーバでは,Microsoft Officeやオフィススイートを一切使用していません.かわりにDockerと,マクロを抽出するPythonライブラリのoletoolsを用いています.dockerコマンドが利用可能であれば,「docker pull takehiko/getvba」または「docker pull takehiko/getvba:alpine」のコマンドで,Dockerイメージを取得できます.またDockerfileを含むファイル一式は,以下より参照・入手できます.

 2年前との違いは,Python 2を使用しなくなったことと,サイズ削減の試みです.https://github.com/decalage2/oletoolsを見ると,2019-04-04リリースのv0.54の中に「olevba, mraptor: full Python 3 compatibility, no separate olevba3/mraptor3 anymore」と書かれています.git cloneして中身を見ると,確かに,olevba.pyが主,olevba3.pyが従の内容になっていました.
 そこで更新にあたり,Dockerのベースイメージをpython:3.8にし,実質的な処理を行う自作のpythonスクリプトvbaではPython 3を使用するよう,pythonとolevbaのパスを変更しました.
 まずは手元のLinuxコマンドライン上で,いろいろ実行:

$ docker pull python:3.8
$ docker run -it --rm python:3.8 bash
root@****:/# which python
/usr/local/bin/python
root@****:/# python --version
Python 3.8.1
root@****:/# ls /usr/local/bin
2to3              idle     pip3    pydoc3.8       python3-config
2to3-3.8          idle3    pip3.8  python         python3.8
easy_install      idle3.8  pydoc   python-config  python3.8-config
easy_install-3.8  pip      pydoc3  python3        wheel
root@****:/# ls /usr/bin/python*
/usr/bin/python   /usr/bin/python2.7  /usr/bin/python3.7   /usr/bin/python3m
/usr/bin/python2  /usr/bin/python3    /usr/bin/python3.7m

 Python 2.7も入っていますが,3.8を使うことにしましょう.pip install -U oletoolsを実行してolevba.pyの所在を確認してから,exitで抜けました.
 Dockerfileをはじめ,gitの管理対象ファイルを一つ一つ読み直してから,必要最小限の箇所を書き換えて保存し,手元でビルドとコンテナ起動.エラーメッセージも出ましたが,中断することなくビルドできました.
 次にサイズ削減です.というのも,docker imagesを実行したところ,できあがったイメージは961MBになっているのです.こんなアプリに約1GBは,大きすぎます.よく見ると,ベースイメージのpython:3.8が,932MBを占めています.
 ベースイメージを,python:3.8-alpineに切り替えることにしました.ブランチをalpineにして,コミット済みです(https://github.com/takehiko/getvba/tree/alpine).
 python:3.8を用いた場合,パッケージ管理はUbuntu系のapt-getでしたが,python:3.8-alpineのAlpine Linuxでは,apkコマンドです.「pip install -U oletools」のコマンド実行中に,ビルドできないというエラーが発生したため,Dockerfileには「apk add --no-cache alpine-sdk libffi-dev openssl-dev」を入れ,あとでapk delしました.
 日本語対応も不可欠です.getvbaを使用し始めた当初の目的は,授業で提出されたxlsmファイルからマクロを取り出すことであり,プロシージャ名や文字列に日本語が出現します.これまではapt-get nkfでインストールしていましたが,nkfのAlpine用パッケージはなさそうです.Pythonで処理を書くのも,バグが不安となり,結局,nkf-2.1.5.tar.gzをダウンロードしてmakeし,/usr/bin/nkfに置くようにしました.
 以下を参照しながら,少しの試行錯誤で,完成させました.

 出来上がったDockerイメージは,138MBとなりました(ちなみにpython:3.8-alpineは112MBでした).マクロに日本語が入ったファイル,入っていないファイルをアップロードしてみて,問題なく表示されました.Docker Hubで,masterとalpineのブランチの自動ビルドを設定し,https://hub.docker.com/r/takehiko/getvba/buildsにアクセスすると,10分もかからずに「Success」となっていました.