Python入門
エクセルを操作する(pywin32:win32com)

Pythonの初心者向け入門解説、人気のプログラミング言語Python
公開日:2020-10-05 最終更新日:2022-06-11

第24回.エクセルを操作する(pywin32:win32com)


Python エクセル Excel pywin32 win32com

PythonでExcelファイルを扱ってみましょう。
前回は外部ライブラリのopenpyxlを使いました。

第24回.エクセルを操作する(openpyxl)
・openpyxlのインストール ・公式リファレンス ・ブックの操作 ・シートの操作 ・セルの操作 ・表示形式・フォント・罫線・列幅・行高 ・CSVを読み込んでエクセルで出力

今回は外部ライブラリのpywin32を使います。
pywin32は、PythonからWindowsAPIへのアクセスを提供してくれます。
実際にエクセルを操作する部分はVBAになります。
したがって、VBAの知識が無ければ全く使う事はできないことは理解しておいてください。
VBAについては以下を参照にしてください。

VBA入門
・VBA学習の進め方について ・1. VBAの基礎・基本:VBA入門 ・2. VBA入門に必要なVBEの基本的使い方 ・3. VBAプログラミングの基礎・基本 ・4. Excel各種機能とオブジェクトの理解:VBA入門 ・5. VBA初級からVBA中級を目指して ・6. VBA入門の後日追加記事 ・7. VBA入門その後の学習について ・「VBA入門」の記事を学校の授業もしくは企業研修でお使いになる場合
VBA再入門
・準備:VBA再入門 ・セルを扱う:VBA再入門 ・エクセルの便利機能:VBA再入門 ・ブック・シートを扱う:VBA再入門 ・マクロ全体を最適化する:VBA再入門 ・自動化への道:VBA再入門 ・最後に:VBA再入門 ・VBAエキスパートを受験する人は

pywin32を使ったエクセル操作はVBAの説明になってしまいます。
ここではVBAの説明は一切せずに、実際のpywin32を使ったサンプルコードを掲載します。
サプルコードは、基本的な操作については網羅するように各種パターンで作成しました。



目次

pywin32のインストール

pipを使ってopenpyxlをインストールします。

Visual Studio

「PyPIとインストールされたパッケージの検索」
ここに「pywin32」これを入れてください。
文字を入れた後にEnterするとそのままインストールされます。

コマンド プロンプト

コマンド プロンプトで以下のコマンドを入れます。

pip install pywin32

詳しくは以下を参照してください。

公式URL

GitHub - mhammond/pywin32: Python for Windows (pywin32) Extensions

一応これが公式だと思うのですが、GitHubでもあり詳しい説明はみあたりませんでした。
ただし、そもそもpywin32は、PythonからWindowsAPIへのアクセスを提供しているだけなので、使い方そのものに困ることは無いと思います。


pywin32:win32comのエクセル操作サンプル

ライブラリ名は、pywin32ですが、
モジュールは、from win32com.client になります。
使う場合は以下のように記述します。
import win32com.client
xl = win32com.client.Dispatch("Excel.Application")
from win32com.client import Dispatch
xl = Dispatch("Excel.Application")
Excelが起動されている場合はGetObjectを使う事も出来ます。
xl = win32com.client.GetObject(Class="Excel.Application")

import win32com.client
#すでにExcelが起動されている場合はそのタスクが使われる #エラー終了するとタスクは残ります xl = win32com.client.Dispatch("Excel.Application") #動いている様子を見てみる xl.Visible = True
#ブック追加 wb = xl.Workbooks.Add()
#シート追加 ws = wb.Worksheets.Add()
#シート名変更 ws.Name = "練習1"
#不要シート削除 xl.DisplayAlerts = False #無くても良いようだが for sh in wb.Worksheets: if sh.Name != ws.Name: sh.Delete()
# セルに値を設定 for i, cell in enumerate(ws.Range("A1:B5")): cell.Value = i
#セル値を2次元配列で取得:タプルで取得される ary1 = ws.Range("A1:B5").Value print(f"{ary1=}")
#セルに入れるために2次元タプルを2次元リストに変換 ary2 = [[c for c in r] for r in ary1] print(f"{ary2=}")
#2次元配列の値を2倍 for r, row in enumerate(ary2): for c, col in enumerate(row): ary2[r][c] = col * 2
#2次元配列をセルに入れる ws.Range("A1:B5").Value = ary2
#Rangeのコピー ws.Range("A1:B5").Copy(Destination=ws.Range("D1"))
#セルの削除 ws.Columns(5).Delete()
#セルの削除 ws.Range(ws.Cells(2,4),ws.Cells(4,4)).Delete(Shift=-4162) #-4162=xlUp
#罫線設定 ws.Range("A1:B5").Borders.LineStyle = 1
#表示形式 ws.Range("B1").NumberformatLocal = "0.0%"
#フォント ws.Range("A1").CurrentRegion.Font.Bold = True ws.Range("A1").CurrentRegion.Font.Size = 14 ws.Range("A1").CurrentRegion.Font.Color = 0x0000FF #赤
#その他のRangeのプロパティ・メソッドの確認 ws.Rows(3).Hidden = True ws.Range("A1:B5").EntireColumn.AutoFit()
#これ以降は出力シートを変更 ws = wb.Worksheets.Add() ws.Name = "練習2"
#以降の結果をセルに出力するので:セル出力には2次元配列が必要 titles = (("Sum",), ("CountIf",), ("Match",), ("VLookup",), ("Range(""A1"")",), ("Range(""A1:B5"")",), ("Range(Cells,Cells)",), ("UsedRange",), ("CurrentRegion",), ("SpecialCells",), ("End(xlUp)",), ("Offset(1, 1)",), ("Offset(2, 2)",), ("Offset(3, 3)",), ("Resize(2, 2)",), ("Resize(3, 3)",), ("Address(0, 0)",), ("InputBox",)) ws.Range("A1:A18").Value = titles
#WorksheetFunction ws.Range("B1").Value = xl.WorksheetFunction.Sum(ws.Range("A1:A5"), ws.Range("B1:B5")) ws.Range("B2").Value = xl.WorksheetFunction.CountIf(ws.Range("A1:B5"),">10") try: #検索値が無い場合はエラーになるので ws.Range("B3").Value = xl.WorksheetFunction.Match("Match", ws.Range("A:A"), 0) except Exception as e: #タプルの入れ子かつ数値文字混在なのでちょっと面倒です。 ws.Range("B3").Value = ",".join([str(x) for x in e.args[2]]) try: ws.Range("B4").Value = xl.WorksheetFunction.VLookup("VLookup", ws.Range("A:A"), 1, False) except Exception as e: ws.Range("B4").Value = ",".join([str(x) for x in e.args[2]])
#Offset:1ずれている?、承知して使うのは怖い気がする ws.Range("B12").Value = ws.Range("A1").Offset(1, 1).Address ws.Range("B13").Value = ws.Range("A1").Offset(2, 2).Address ws.Range("B14").Value = ws.Range("A1").Offset(3, 3).Address
#Resize:これはおかしいので使えない ws.Range("B15").Value = ws.Range("A1").Resize(2, 2).Address ws.Range("B16").Value = ws.Range("A1").Resize(3, 3).Address
#Addressに引数が指定できない?:'str' object is not callable try: ws.Range("B17").Value = ws.Range("B27").Value = ws.Range("A1").Address(False, False) except Exception as e: ws.Range("B17").Value = str(e)
#InputBox: ws.Range("B18").Value = xl.InputBox("入力してください。")
#ブックを保存:相対パスはExcel.Applicationから見た位置になります。 import os wb.SaveAs(os.getcwd() + "/test.xlsx") #.pyと同ディレクトリ wb.Close(SaveChanges=True)
#他のブックが開いていなければExcelを終了 if xl.Workbooks.Count == 0: xl.quit()
スクリプト内のコメントと併せて、ステップインで確認すると動きが良く分かると思います。

Python エクセル Excel pywin32 win32com

Python エクセル Excel pywin32 win32com

Python エクセル Excel pywin32 win32com


エクセルのマクロを起動する

import win32com.client
import os
xl = win32com.client.Dispatch("Excel.Application") xl.Visible = True
wb = xl.Workbooks.Open(Filename=os.getcwd() + "/Book1.xlsm", ReadOnly=1) xl.Run("Book1.xlsm!SampleMacro")
wb.Close(SaveChanges=False) if xl.Workbooks.Count == 0: xl.quit()
OpenによりOpenイベトも起動されます。
Runメソッドの詳細については以下を参照してください。
第127回.他のブックのマクロを実行(Runメソッド)|VBA入門
・Application.Runメソッド ・Application.Runの使用例 ・Application.Runの必要性


pywin32の問題点

実際に使って見て感じた問題点としては、
・大文字小文字が区別される
・プロパティの名前付き引数が機能しない
・正しく機能しないプロパティがある
大きく分けるとこの3点だと思います。
もしかすると、僅かな記述の乱れから全て発生しているのかもしれませんが、詳細は不明なままです。
また、これは当然のことですが、Excelがインストールされていないと動作しませ。

大文字小文字が区別される

使う上で一番苦労するのは、大文字小文字が区別されることにあります。
VBAでは大文字小文字を区別しないので、通常はこれを意識することはありません。
VBAが相当出来る人でも、識別子のスペルを大文字小文字まで含めて正しく記憶している人は少ないでしょう。

また、これは仕方ない事ですが、
VBA定数およびxl定数は使えないので、VBEのイミディエイトなりで調べる必要があるのは、かなり面倒です。

結局は、VBAで書いたものをVBA定数等を数値に直したものを移植することになると思います。

プロパティの名前付き引数が機能しない

いろいろ試した中では、プロパティの名前付き引数がまともに使えないように見受けられました。
あまり多くの確認は出来ていませんが、メソッドの引数は機能しているようです。
残念ながら現在のところは、プロパティの引数を正しく機能させる方法は見つけることが出来ませんでした。

Python エクセル Excel pywin32 win32com

Python エクセル Excel pywin32 win32com

上はPythonのエラー、下はVBAのオブジェクトブラウザです。
これがエラーになってしまうのでは、他に指定方法があったとしても使う事は難しくなります。

雰囲気としては、Optionalの名前付き引数の指定が上手く機能していないように感じました。

ただしPythonとは違い、VBAでは名前付き引数が強要されることはないので、位置指定だけで問題ありません。
したがって、何らかの代替え手段は見つかると思います。

正しく機能しないプロパティがある

これは、プロパティの名前付き引数が機能しないことと関係しているように思いますが、
いずれにしても、本来とは違う挙動をするものがある以上、使う上ではかなり注意が必要です。

RangeオブジェクトのOffsetプロパティとResizeプロパティが正しく使えないのはちょっと残念ですが、
VBAには代替方法がいくらでもあるのでそんなに困ることは無いと思います。

Addressプロパティは用途が限定されているので問題無いと思います。




同じテーマ「Python入門」の記事

第16回.Pythonの引数は参照渡しだが・・・
第17回.リスト内包表記
第18回.例外処理(try文)とexception一覧
第19回.import文(パッケージ・モジュールのインポート)
第20回.フォルダとファイルの一覧を取得(os,glob,pathlib)
第21回.CSV読み込みとopen()関数とwith文
第22回.CSV読み書き(csvモジュール)
第23回.pipコマンド(外部ライブラリのインストール)
第24回.エクセルを操作する(openpyxl)
第24回.エクセルを操作する(pywin32:win32com)
第26回.WEBスクレイピング(selenium)


新着記事NEW ・・・新着記事一覧を見る

ブール型(Boolean)のis変数・フラグについて|VBA技術解説(2024-04-05)
テキストの内容によって図形を削除する|VBA技術解説(2024-04-02)
ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)
VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
累計を求める数式あれこれ|エクセル関数応用(2024-01-22)
複数の文字列を検索して置換するSUBSTITUTE|エクセル入門(2024-01-03)
いくつかの数式の計算中にリソース不足になりました。|エクセル雑感(2023-12-28)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
3.RangeとCellsの使い方|VBA入門
4.ひらがな⇔カタカナの変換|エクセル基本操作
5.繰り返し処理(For Next)|VBA入門
6.変数宣言のDimとデータ型|VBA入門
7.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
8.並べ替え(Sort)|VBA入門
9.セルのクリア(Clear,ClearContents)|VBA入門
10.Findメソッド(Find,FindNext,FindPrevious)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。


このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ