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

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

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


Python エクセル Excel pywin32 win32com

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

第24回.エクセルを操作する(openpyxl)
PythonでExcelファイルを扱ってみましょう。それには、外部ライブラリのopenpyxlを使うと便利ですし、簡単に扱う事が出来ます。openpyxlはとても機能が豊富で、エクセルに対するかなり多くの事が出来ます。

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

VBA入門
VBAはExcelの操作を自動化するマクロ機能で使われているプログラミング言語です。「VisualBasicApplications」の略になります。マクロVBA入門シリーズでは、始めはより詳しく丁寧に解説し、少しずつ難易度を上げることで無理なく学習を進められるようにしています。
VBA再入門
VBAを学習しようとして、本を読んでもWEBをみても、結局挫折してしまった方を対象に、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入門
他のブック中にあるプロシージャー(Sub,Function)を実行する場合は、Application.Runメソッドを使います。別々に作成されたマクロVBAの入ったブックを連携させる時には必須になります。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)
第25回.エクセルを操作する(pywin32:win32com)
第26回.WEBスクレイピング(selenium)


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

WEBスクレイピング(selenium)|Python入門(10月11日)
エクセルを操作する(pywin32:win32com)|Python入門(10月5日)
エクセルを操作する(openpyxl)|Python入門(10月3日)
pipコマンド(外部ライブラリのインストール)|Python入門(10月1日)
CSV読み書き(csvモジュール)|Python入門(9月29日)
「Excel 4.0 マクロ」の使い方|VBA技術解説(9月28日)
CSV読み込みとopen()関数とwith文|Python入門(9月28日)
フォルダとファイルの一覧を取得(os,glob,pathlib)|Python入門(9月26日)
import文(パッケージ・モジュールのインポート)|Python入門(9月24日)
例外処理(try文)とexception一覧|Python入門(9月23日)


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

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.マクロって何?VBAって何?|VBA入門
6.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
7.繰り返し処理(For Next)|VBA入門
8.セルに文字を入れるとは(Range,Value)|VBA入門
9.とにかく書いてみよう(Sub,End Sub)|VBA入門
10.マクロはどこに書くの(VBEの起動)|VBA入門




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


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



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