こんにちは(@t_kun_kamakiri)(‘◇’)ゞ
本記事では、Pythonで作成したコードをExcelから実行する方法を解説します。
本日作成するツールはこちら↓。
このようにパラメータ設定はExcelに設定しておいて、主要な計算部分はPythonにやらせています。
一見Excelだけで動いているように見えますよね。
使う側からすると計算の詳細を知らなくてもパラメータを設定するだけで計算ができるためストレス無くほしい結果を得ることができて便利ですよね。
このようなツールの目的は、「設計者が使うツールとしてはExcelのみにしておき、計算実行の部分は数値計算が得意で高速な言語にしておきたい」ということです。
目的を達せしするためなら、
- 設計者が使うGUIツール(ボタンを押すだけ):Excel、Webアプリなど
- 数値計算:C/C++、Fortran、Python
このような方法の中で自分が使いやすいものを選択することができると思います。
しかし、会社で使おうと思うと、Webアプリにするにも作成者の手間もかかるしサーバーをどうしようかなどあったり、数値計算のコードもできるだけ自分が得意な言語でやる方が良いでしょう。
今回の行うケースでは、十分Pythonでも行うことができますので個人的に簡単だと思うPythonを選択しました。
Pythonを使うのであれば、PythonのWebアプリフレームワークとしては、Django、Flask、Bottleなどがありますし、PythonのGUI構築・操作するための標準ライブラリであるTkinterもありますね。いずれにしても、作成者の学習コストはじゃっかんかかります。
使う側からするとExcelから計算実行させて、Excelで計算結果をまとめたいという気持ちもあるかと思います。
こういったExcel大好きって人の気持ちになって今回はExcelベースで動くツールを作成しました。
数値計算の題材としては以下の記事のPythonコードを使います。
数値流体のPythonコードをExcelから実行するということをやります。
本記事の内容は以下となっています。
- Pythonコードで数値流体を体験
- ExcelからPythonを実行する手順の説明
今回使用したファイルはこちら
- Python 3.7.6(Windows 64bit)
- Excel2016
※WSL(Ubuntu)でのPythonを使って今回の内容を行おうとしましたが、「xlwings」のインストールで以下のようなエラーが出ます。
githubのソースコードを読みに行くと、「WindowsかMacではないと・・・」という感じで書かれているため、Ubuntuではダメなのかなと思い、今回はWindowsのPythonを使うことにします。
※既にWindowsにPythonがインストールされていることを想定しています。
将来的には、「exe化」してPythonがインストールされていなくても実行できるようにしたいです_(._.)_
数値流体の離散化(Jupyter notebook(lab)を使ってPythonコードを完成させる)
まず、計算をさせる対象を示しておきます。
\frac{\partial u}{\partial t}+c\frac{\partial u}{\partial x}=0\tag{1}
\end{align*}
(1)式の離散化は以下のようになります。
\frac{u^{n+1}_{i}-u^{n}_{i}}{\Delta t}+c\frac{u^{n}_{i}-u^{n}_{i-1}}{\Delta x}=0
\end{align*}
u^{n+1}_{i}=u^{n}_{i}+\frac{c\Delta t}{\Delta x}\big(u^{n}_{i}-u^{n}_{i-1}\big)\tag{2}
\end{align*}
ここで、\(\alpha=\frac{c\Delta t}{\Delta x}\)として時間刻み空間の分割幅\(\Delta x\)と\(c\)で決まるものとしておきます。
この\(\alpha\)の大きさによって、数値計算の結果が大きく変わるので、ツールができたら遊んでみてください。
(2)をPythonコードで書いてみましょう。
今回は、デバッグがしやすいJupyter notebook(lab)でコードを書いていきます。
Excelファイル「param.xlsm」からパラメータを読み込むため、pandasの使い方もここで確認しておきます。
Pythonコード
以上が、できたらひとつのPythonファイルにまとめておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
import numpy as np import matplotlib.pyplot as plt from matplotlib import animation # from IPython.display import HTML import pandas as pd df_import_file = pd.read_excel('param.xlsm', index_col=0, header=1) df_import_file = df_import_file.drop(df_import_file.index[4:]) param_ = df_import_file.to_dict() param = param_['数値'] nx = int(param['nx']) #★ xmax = param['xmax'] #★ dx = xmax / (nx-1) nt = 40 c = param['c'] #★ alpha = param['alpha'] #★ dt = alpha * (dx/c) x = np.linspace(0,xmax,nx) un = [] u = np.ones(nx) u[int(.5 / dx):int(1 / dx + 1)] = 2 fig = plt.figure(figsize=(8,4)) ims=[] for n in range(nt): un = u.copy() if (nt%1==0): im = plt.plot(x,u, "r") ims.append(im) for i in range(1, nx): u[i] = un[i] - c * dt / dx * (un[i] - un[i-1]) plt.grid() plt.ylim([-0.1,3]) plt.xlabel("x") plt.ylabel("u(m/s)") anim = animation.ArtistAnimation(fig, ims) # rc('animation', html='jshtml') #ani.save('anim.mp4', writer="ffmpeg") # plt.close() # anim anim.save('anim.gif', writer='pillow') plt.show() |
ちゃんと計算が実行できるか確かめます。
コマンドプロンプトを立ち上げてコードを実行しています。
条件によっては動画のように、解が振動してしまいます。
エラー無く計算が実行できていることが確認出来たら、これをExcelから実行できるようにします。
ExcelからPythonを実行する(テスト)
ExcelからPythonを実行する方法を確認します。
必要なライブラリをインストール
まず、することが2つあります。
コマンドプロンプトで以下をインストールします。
- pip install xlrd:xlrdのインストール
- pip install xlwings:xlwingsのインストール
僕は既にインストールしているので、「・・・already・・・」と書かれています。
Excel VBEにxlwings.basをインポート
Excelを起動し、開発タブの「Visual Basic」をクリックしてVBEを起動します。
「xlwings.bas」はPythonがインストールされている環境によるので、自身の環境に合わせてファイルを探してみてください。
僕は「C:\Users\Owner\AppData\Local\Programs\Python\Python37\Lib\site-packages\xlwings」にありました。
「xlwings.bas」の中身は詳しく知る必要はないのですが、「Public Function RunPython(PythonCommand As String)」でPythonが実行するコードが書かれています。
なので、仕組み的には「RunPython」というFunctionをcallで呼び出せば良いということがわかります。
ExcelのVBEでRunPythonを呼び出す
次に、ExcelのVBEに以下を記述します。
1 2 3 4 5 |
Option Explicit Public Sub copyText() Call RunPython("import excel_test; excel_test.copy_add_tex()") End Sub |
これで、RunPythonというFunctionが呼び出されて、
- excel_test(excel_test.py)をimport
- excel_test.pyの中のcopy_add_text()関数を実行する
というのを行います。
では、テスト計算として「param.xlsm」と同じフォルダに「excel_test.py」を用意します。
ボタンを設定しておくと、「計算実行」ボタンを押すだけでマクロが動いてくれるようにしておきます。
- 「E2」セルに今どのパスになっているのかを確認しています。
「param.xlsm」の絶対パスになっていると思ったら全然違うパスになっていますよね。 - ディレクトを移るため以下のように書いて出力してみます
これで「param.xlsm」があるフォルダのパスになりました。 - 「param.xlsm」で設定したパラメータが読み込めるか「E10」セルに値を出力してみます。
ちゃんとパラメータが読めているのが確認できますね。
ExcelからPythonを実行する(数値流体のPythonコード)
以上で、ExcelからPython実行の方法がわかったので、
「param.xlsm」に設定しておいた数値を読み込んで、1次元移流方程式を解くPythonコードを実行してみましょう。
ここでやったのは、メインのコードを「def all():」に入れただけですね。
ファイル名:Excel_import_1D_Fluid_test.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
import numpy as np import matplotlib.pyplot as plt from matplotlib import animation # from IPython.display import HTML import pandas as pd import os import xlwings as xw def all(): #現在のディレクトリに移動 os.chdir('C:\Work\Python\Python_fluid_Excel') #パラメータファイルのインポート df_import_file = pd.read_excel('param.xlsm', index_col=0, header=1) df_import_file = df_import_file.drop(df_import_file.index[4:]) param_ = df_import_file.to_dict() param = param_['数値'] #初期状態の設定(初期条件) nx = int(param['nx']) #★ xmax = param['xmax'] #★ dx = xmax / (nx-1) nt = 40 c = param['c'] #★ alpha = param['alpha'] #★ dt = alpha * (dx/c) x = np.linspace(0,xmax,nx) un = [] u = np.ones(nx) u[int(.5 / dx):int(1 / dx + 1)] = 2 fig = plt.figure(figsize=(8,4)) ims=[] #計算実行 for n in range(nt): un = u.copy() if (nt%1==0): im = plt.plot(x,u, "r") ims.append(im) for i in range(1, nx): u[i] = un[i] - c * dt / dx * (un[i] - un[i-1]) plt.grid() plt.ylim([-0.1,3]) plt.xlabel("x") plt.ylabel("u(m/s)") anim = animation.ArtistAnimation(fig, ims) # rc('animation', html='jshtml') #ani.save('anim.mp4', writer="ffmpeg") # plt.close() # anim anim.save('anim.gif', writer='pillow') plt.show() |
そして、ExcelVBAコードは以下のようにしておきます。
1 2 3 4 5 |
Option Explicit Public Sub copyText() Call RunPython("import Excel_import_1D_Fluid_test; Excel_import_1D_Fluid_test.all()") End Sub |
- Excel_import_1D_Fluid_test(Excel_import_1D_Fluid_test.py)をimport
- Excel_import_1D_Fluid_test.pyの中のall()関数を実行する
これによって、以下のようにパラメータを変えると計算結果も変わってくれます。
今回は「alpha」の値を変更させた結果を示しています。
※Pythonは現在のExcelの状態を読みに行くため、パラメータの数値を変更すると毎回保存しなおさないとパラメータ変更が反映されません。
このあたりは、「計算実行」ボタンを押すと、PythonでExcelの自動保存をさせるか、VBAのコードでExcelの保存をさせるか色々方法があると思います。
今回は、手動で保存しています。
まとめ
ExcelからPythonコード(1次元移流方程式)を実行させる手順を解説しました。
目的は、Excelでパラメータを変更して計算は別の言語にやらせるということです。
こういった方法を使えば、Excelをメインにしながら、計算部分は作成者の得意な言語を使って高速に結果を取得することができます。
※もちろんExcelVBAを使っても同じことができますが、数値計算には不向きでコードも面倒ですし計算も遅いですね。
ExcelとPythonの連携は以下の書籍で勉強しています!
※おまけ(JupyterをWordpressに埋め込む方法)
Jupyter notebook(lab)をWordpressに埋め込む方法を探していたら、簡単な方法を見つけました。
Githubアカウントにログインした状態で、以下の「Gist」に行って「*.ipynb」をアップロードします。
「Create secret gist」を押して以下のページ移ったら、<script>***</script>をWordpressの「テキスト」に貼り付けたら終了です(^^)/
便利なので試してみてください!