ブラウザから,Excelマクロ有効ブック(拡張子がxlsmのファイル)をアップロードすると,そこからマクロの部分を取り出して表示する,簡単なWebアプリケーションを開発しました.初期画面は次のとおりです.
授業で提供しているファイルの一つ,CalendarMaker.xlsm*1をアップロードしてみると,次のように,マクロが表示されます.
olevba 0.51 - http://decalage.info/python/oletools Flags Filename ----------- ----------------------------------------------------------------- OpX:M-S-HB-- **** =============================================================================== FILE: **** Type: OpenXML ------------------------------------------------------------------------------- VBA MACRO ThisWorkbook.cls in file: xl/vbaProject.bin - OLE stream: u'VBA/ThisWorkbook' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (empty macro) ------------------------------------------------------------------------------- VBA MACRO Sheet1.cls in file: xl/vbaProject.bin - OLE stream: u'VBA/Sheet1' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (empty macro) ------------------------------------------------------------------------------- VBA MACRO Module1.bas in file: xl/vbaProject.bin - OLE stream: u'VBA/Module1' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Sub CalendarMaker() ' Unprotect sheet if had previous calendar to prevent error. ActiveSheet.Protect DrawingObjects:=False, Contents:=False, _ Scenarios:=False (略) Range("a2") = "Sunday" Range("b2") = "Monday" Range("c2") = "Tuesday" Range("d2") = "Wednesday" Range("e2") = "Thursday" Range("f2") = "Friday" Range("g2") = "Saturday" (略) MyErrorTrap: MsgBox "You may not have entered your Month and Year correctly." _ & Chr(13) & "Spell the Month correctly" _ & " (or use 3 letter abbreviation)" _ & Chr(13) & "and 4 digits for the Year" MyInput = InputBox("Type in Month and year for Calendar") If MyInput = "" Then Exit Sub Resume End Sub
ファイル選択をせずにアップロードのボタンを押した場合や,ファイル名の終わりがxlsmでないファイルをアップロードした場合には,メッセージを表示し,マクロ取得は行いません.
2年前のことです.1年後期のプログラミング科目でVBAについて教えるようになり,演習課題の答案を提出してもらいまして,採点に苦労しそうだと感じました.Excelマクロ有効ブック(拡張子がxlsmのファイル)を1つ1つ開いて,Excelの画面と,Visual Basic Editorの画面を見るのは,相当な手間です.
何かコマンドで,xlsmファイルを与えると,マクロの部分だけを取り出して,出力してくれるものはないか…と探していると,oletoolsというのを見つけました.Pythonで書かれたツール集です.この中のolevbaが,求めているものでした.
CygwinでもLinuxでも,マクロを取り出してくれました.ただし日本語もそのままなので,コマンドの後ろに「| nkf -w」を書き,UTF-8で保存するようにしました.先にechoコマンドで,各学生の(学生番号込みの)ファイル名を出力しておくことで,一つのテキストファイルに,全員分のマクロが格納でき,これで,正味のプログラム部の採点が楽になりました.
今年度は,VBA授業の最終回に,Webアプリケーションとして提示し,各学生にアップロードしてもらって,今まで書いたマクロを,ブラウザ上で見ることができるようにしました.クリスマス前のことです.
Dockerコンテナとして稼働します.Dockerfileを含むファイル一式は,以下より入手できます.
dockerコマンドが利用可能であれば,docker pull takehiko/getvbaのコマンドで,Dockerイメージが取得できます.gitからという方は,上記,各ページに記載のコマンドをご使用ください.
Webサーバに関して,ApacheやNginxといった大がかりなものは採用せず,PythonでHTTPサーバを走らせました.Pythonというと,バージョン2と3の非互換性に配慮しないといけません.今後のことを考えて,バージョン3を,そしてDockerのベースイメージとしては,python:3.5を,採用しました.そこに,文字コードの変換にnkfを導入し,またpip3コマンドで前述のoletoolsもインストールするよう,Dockerfileを書き,ビルドしました.
Webアプリケーションの処理を担うのも,vbaというファイル(Pythonスクリプト)一つだけにしました.
なのですが,多数のエラーや,出力なしの状況から,バージョン3用のolevba3.pyでは,思うように動かないことに気づきました.
ある程度開発を進めたところで,バージョン2に戻りたくないなと思いながら,自作Dockerコンテナにbashで入り込んでみると,python2がコマンドとして使用可能となっていました.python:3.5には,バージョン3だけでなくバージョン2のPythonも,入っていたのでした.
結局,HTTPサーバやWebアプリケーションについては,バージョン3を使用し,olevbaについてはpython2でolevba.pyを,自作スクリプトのvbaから呼び出す(コマンドとして実行する)こととしました.
他にも何やかやありました*2が,終わってしまうと過去のことです.個人的には,Pythonの書き方と,Dockerfileほかの公開の仕方を学ぶ機会となりました.そういった内部の話は,授業で伝えていませんが,ノウハウを積み重ねて,今の1年生が研究室選択をするときには,当研究室の基盤技術の一つにしていきたいところです.
*1:http://d.hatena.ne.jp/takehikom/20171208/1512745198
*2:subprocess.check_outputを用いて,出力をそのまま受け取ると,終了ステータスが0でない場合にはエラー終了になるため,かわりにsubprocess.Popenを用いていったんファイルに保存しました.そうして保存したファイルが,なぜか読み出せず,time.sleepを使って少し待てばよいと分かりました.待ち時間は,授業で使用のWebアプリケーションでは1秒でしたが,0.5秒まで減らしても,自分の実行環境では大丈夫でした.