PythonとExcelをハイブリッドに駆使するという当サイトのコンセプト上、ExcelブックをPythonスクリプトにわたさなければならない機会が多々あります。順当にやるならパスを引数にしてわたす方法ですが、もっと超絶簡単にできるんです。その方法とは
PythonをWindowsインストーラーでインストールしたなら
すでにドラッグ&ドロップでわたせるようになっている。
ファイルパスは sys.argv[1] で受け取れる。
以上です。ご来訪ありがとうございました。
時間があるかたは続きの解説もぜひご覧ください。
Pythonにファイルをコマンドライン引数でわたす
まずはコマンドラインで引数としてわたす方法を確認しておきます。次はExcelファイルを読み込んでA列の値をprintで出力していくだけのスクリプト(excel_reader.py)です。
import sys
import openpyxl as excel
fp = sys.argv[1]
wb = excel.load_workbook(fp)
ws = wb.active
for row in ws.iter_rows():
print(row[0].value)
ここで
fp = sys.argv[1]
が引数(ファイルパス)を受け取る処理です。argvは与えたコマンドライン引数をリストで持ってきます。インデックスが1始まりなのが罠ですが、リファレンスによると[0]はスクリプトの名前が入っているそうです。
argv[0]をprintで出力して確認してみたら、ファイルのフルパスでした。しかし条件によっては必ずしもそうはならないようです。ともかく詳しくはリファレンスを読んでもらうとして、ユーザーが与えた引数は[1]からなので注意しましょう。
読み込むExcelブック(saitama_city.xlsx)は次のような内容です。
先のPythonスクリプトをこのExcelブックのパスを引数として実行するコマンドラインは次のとおりです。どちらのファイルもD:\にあるとします。
Pythonスクリプトに続けてExcelブックのパスを指定して実行します。結果はこうなります。
無事にうごきましたが、せっかくWindowsというGUIを使っているのにわざわざCUIでパスを指定するなんて面倒くさいですよね。ファイルをドラッグ&ドロップしたらやってくんないかなと思うのが普通です。
Pythonにファイルをドラッグ&ドロップでわたす
ここから本題ですが、実は何もしなくてもすでに出来る状態になっていることが大半です。
Pythonスクリプトのファイル(.py)が次のようなアイコンになっていれば準備完了です。
その他のアイコン(たとえばテキストエディタ)になっていたらダメです。
アイコン(=拡張子の関連付け)を変えるには、ファイルを右クリックしてメニューから変更ボタンです。
これはPythonランチャというアプリで実体はC:\Windows\py.exeにあります。
WindowsのインストーラーでPythonをインストールすると自動的に.pyファイルに関連付けがされていると思います。
あとは単純にExcelブックをスクリプトの.pyファイルへドラッグ&ドロップするだけです。
先のスクリプトだと処理が終わった瞬間にコンソールが閉じてしまい、よほどの動体視力の持ち主以外、何もわからないので少し改造します。
import sys
import openpyxl as excel
import time
fp = sys.argv[1]
wb = excel.load_workbook(fp)
ws = wb.active
print('OK!ここで俺たち SaitamaCity のイカしたメンバーを紹介するゼ!!')
for row in ws.iter_rows(min_row=2):
time.sleep(1)
print(row[0].value + '!')
input('Thank You! いくぜ!ラストナンバー!「希望のまち」')
D&Dしたファイルのパスがsys.argv[1]です。実行してみましょう。結果は次のようになります。アニメーションでループしているので途中の場合は最初に戻るまでお待ちください。
このようにD&Dするだけで簡単にExcelブックを処理できます。これで神エクセルをビシバシDustBoxへ送れますね!
普段IDEでスクリプトを書いている人はこれで何も問題ないと思いますが、テキストエディタで.pyファイルを直接編集している人は、この状態だとファイルダブルクリックでスクリプトが走ってしまうので注意してください。
複数ファイルをドラッグ&ドロップでわたす
複数ファイルを一気にやっつけたい場合は、次のようにします。
for fp in sys.argv[1:]:
print(fp) # それぞれのファイル(パス)に対する処理
sys.argvは前述の通り引数のリストなのでイテレータで1個ずつ取り出せます。ただし、0番目の要素は使わないのでスライスで1から取り出すようにします。
フォルダにも対応したい場合はos.path.isdir()で、まずファイルかフォルダかを判定してフォルダならos.walk()でさらに深掘りして中身を各個処理していくようにすると良いでしょう。
おわり。