#author("2023-02-24T18:44:15+09:00","default:irrp","irrp") →Python関連Tips →ExcelのVBA →C#によるExcel制御 #contents *一般 [#qd2ffbd8] -PythonによるExcel制御の方法として、Openpyxl, xlwings, pywin32 の3通りがあるが、それぞれ一長一短がある。 -もっとも一般的なのはOpenpyxlだが、もっとも制約が大きい→後述 -Window+Excelインストール済みの環境であることを前提とすれば、pywin32(win32com)を使うことでVBAとほぼ同等の機能が使えるが、openpyxlに比べ情報が少ないと言うデメリットがある。 -pywin32のもう一つの難点として、Pylanceを使った型ヒントアノテーションの仕組みと相性が悪いという問題がある。pywin32で使うCOMオブジェクト類には型ヒントはつけられないと思った方が良さそう。 -[[VBAユーザーのためのPython入門 〜xlwingsでExcelからPythonを呼び出す〜 - Qiita>https://qiita.com/k_maki/items/9efdb70f69d6f3b00f80]] 2022 -[[ExcelからPythonを実行する - Qiita>https://qiita.com/katzhide/items/60d0336b322105bf8fe9]] 2016 -[[ExcelにPython搭載!マクロVBAからプログラムを実行する方法>https://fastclassinfo.com/entry/run_python_from_vba/]] 2023.2 --VBAから xlwings を使ってPythonプログラムを実行する。 *OpenPyxl [#e4f560ef] -2022.10月時点の調査では、下記の通りです。 --openpyxlの重大な欠点として、セルの計算式の評価がその場でできないというのがある。セルに値を入れてもそれが即計算式に反映されない。 --計算式の値を得るには一度保存した上で、data_only=Trueの引数でオープンする必要があるが、このオプションをつけて開いたファイルをセーブすると、中の計算式が値に変換されて消えるため、data_only=Trueで開いたファイルはセーブしてはならない。 --openpyxlではチェックボックスなどのオブジェクトもまともに使えない。また吹き出しなどの図形オブジェクトはセーブとともに消えてなくなる。 --データ入力規則にも対応しておらず、セーブすると設定が消えてなくなる。 --openpyxlはExcelがインストールされてなくても使える、また単なるファイル処理なので動作が軽い反面、Excelの機能に依存する気の利いたことはできないと思った方が良い。 --ブックの名前やフルパスの取得すらまともにできない。 --これらの制約があるため、使える範囲はVBAよりも限定されると考えるべきだろう -[[python3 openpyxl でエクセルに行挿入する - Qiita>https://qiita.com/gameover/items/13868ca9101348bdf4fc]] 2018 -[[openpyxlでExcelを操作する【Python入門】 - RAKUS Developers Blog | ラクス エンジニアブログ>https://tech-blog.rakus.co.jp/entry/20210729/openpyxl]] 2022.9 -[[openpyxlでpythonからエクセルファイルを操作する - Qiita>https://qiita.com/studio_haneya/items/7e49b616d4972fe1804d]] 2021 -openpyxlでExcelを開くとき、Excelにデータ入力制限があると対応していないためワーニングが出るのを抑制する --エラー内容:UserWarning: Data Validation extension is not supported and will be removed warn(msg) --ワーニング抑制 import warnings warnings.simplefilter(action='ignore', category=UserWarning) または↓でもよい openpyxl.reader.excel.warnings.simplefilter('ignore') --[[io - Python 3 openpyxl UserWarning: Data Validation extension not supported - Stack Overflow>https://stackoverflow.com/questions/53965596/python-3-openpyxl-userwarning-data-validation-extension-not-supported]] 2018 -[[【AI 講師が解説】Python で Excel(エクセル)を読み込む方法 | キカガクの技術ブログ>https://blog.kikagaku.co.jp/python-excel]] 2022.7 --Pandasを使う方法 -[[python 2.7 - openpyxl Set Active Sheet - Stack Overflow>https://stackoverflow.com/questions/41556378/openpyxl-set-active-sheet]] --wb.active にシートを設定する *Pywin32 [#j7f8fb5c] -[[Python pywin32(win32com) Excel 操作備忘録 - Qiita>https://qiita.com/feo52/items/150745ae0cc17cb5c866]] 2022 -[[PythonからExcelをwin32comで操作する - Qiita>https://qiita.com/kumarstack55/items/9ae3432446afca06497f]] 2019 -[[Python(openpyxl)でExcelを出力した際に数式の計算結果が取得できない問題 – 対策編 | ニッチな技術録>https://buzz-server.com/tech/python-openpyxl-no-value-measures/]] 2022.2 --xlwingsでExcelを実行と書いてあるが、それは関係ない。Pywin32を使いCOMで開いてセーブしているだけ import win32com.client app = win32com.client.Dispatch("Excel.Application") app.Visible = False app.DisplayAlerts = False wb = app.Workbooks.Open(exel_file_name) wb.SaveAs(exel_file_name) app.Quit() -[[PythonでExcelのチェックボックスのラベル値を取得したいです。>https://teratail.com/questions/331090]] import win32com.client from win32com.client import CDispatch from pathlib import Path def proc_xls(fnam:str) -> None: app:CDispatch = win32com.client.Dispatch("Excel.Application") print(type(app)) app.DisplayAlerts = False workbook = app.Workbooks.Open(Path(fnam).resolve()) #Excel定数 EXCEL_xlon = 1 EXCEL_xlOff = -4146 for chk in workbook.Worksheets("個別契約").Checkboxes: print(chk.Name + " のCheck状態は " + str(int(chk.Value) == EXCEL_xlon)) workbook.Close() app.DisplayAlerts = True app.Quit() ** Excelのプロセスが残ってしまう問題 [#aec4d53c] 参考:C#によるExcel制御 -Workbookをクローズしているのになぜかプロセスが残ってしまう問題がある。 -ReleaseComObject的な処理をしてやれば消えるのだろうが、Pythonでどうやったらいいのか不明。 -とりあえず、Application.Quit()をすればプロセスは消えるが、今度はPythonで起動したExcelとは関係なく別で開いていたExcelまで巻き込んで終了してしまう。 -この問題は2022.10時点でまだうまい解決方法が見つからない。 -試行錯誤の結果、とりあえず現時点では下記のようなコードでなんとなく動かし、プロセスが残ったら手動でkillしている。 @classmethod def initExcelApp(cls) -> None: cls.__app = win32com.client.Dispatch("Excel.Application") cls.__app.Visible = False cls.__app.DisplayAlerts = False @classmethod def termExcelApp(cls) -> None: if cls.__app is not None: cls.__app.Visible = True cls.__app.DisplayAlerts = True if cls.__app.Workbooks.Count == 0: cls.__app.Quit() del cls.__app # 数式を反映させるために実Excelで開いてセーブする @classmethod def exel_update(cls, exel_file_name:str) -> None: cwd : str = os.getcwd() path:str = cwd + '\\' + exel_file_name wbs = cls.__app.Workbooks wb = wbs.Open(path) wb.Save() wb.Close(SaveChanges=True) wb = None del wb # wbs.Close() # wbs = None # del wbs -参考:[[Can't close Excel completely using win32com on Python - Stack Overflow>https://stackoverflow.com/questions/10221150/cant-close-excel-completely-using-win32com-on-python]] 2022 -参考:[[python - COM: excelApplication.Application.Quit() preserves the process - Stack Overflow>https://stackoverflow.com/questions/18421457/com-excelapplication-application-quit-preserves-the-process/18421814#18421814]] 2022.10 -参考:[[python - Using Excel Interop library with python3 ctypes - Stack Overflow>https://stackoverflow.com/questions/66603199/using-excel-interop-library-with-python3-ctypes]] 2022